PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Input beim MCP23017



modtronic
08.03.2017, 12:11
Mahlzeit

Ich experimentiere länger schon mit dem MPC 23017 herum.
Inzwischen funktioniert er auch und ich kann die Ausgänge und Register schreiben.

Leider bekomme ich das nicht hin, mir die Ports als Eingänge zu nutzen.
Das ich die Register 0x00 und 0x01 dafür verwende, das weiss ich. im Grundzustand sind diese ja auch als Eingänge definiert.

Leider komme ich auch aus dem Datenblatt da nicht so ganz schlau.
wenn ich das richtig lese ist dafür 0x12 und 0x13 zuständig..jedoch stehe ich da irgendwie auf dem Schlauch..
.ich möchte das die Pins im Grundzustand Low sind, das mache ich über Pull Down Widerstände.
mir reicht es die Gesamte Information eines Bytes in eine Variable zu schreiben. (0-255)

kann mir da jemand auf die Sprünge helfen.bzw hat das schonma in C Programmiert ?

Gruss
modtronic

HaWe
08.03.2017, 14:09
die Gretchenfrage lautet: für welche Zielplattform?

Für nackte Atmels sieht der Code völlig anders aus als für Arduinos und erst recht für Raspis, einfach weil die i2c-Libs völlig anders implementiert sind.

Ich selber habe Tonnen von Code für den

Raspi http://www.mindstormsforum.de/viewtopic.php?f=78&t=8689&p=68574#p70059

und Arduino: http://www.mindstormsforum.de/viewtopic.php?f=78&t=8491&start=75#p69287 .

modtronic
08.03.2017, 14:59
Hallo

Ich arbeite mit den klassischen Atmels AT Mega 8,16 und 32.
Ich programmiere mit Codevision in der Sprache C.

Gruss
Patrick

- - - Aktualisiert - - -

Hallo

Ich arbeite mit den klassischen Atmels AT Mega 8,16 und 32.
Ich programmiere mit Codevision in der Sprache C.

i2c Bus ist eine Routine von CV..

ich spreche den BUs mit i2c_start an,,bzw i2c_stop.
mit write und read kann man halt schreiben oder lesen

Feuerring
08.03.2017, 22:37
das hatten wir doch schon mal ...

Register 0 /1 und 12/13 wie folgt schreiben ...

Register 0 (A) DIR 0=OUT / 1=IN
Register 1 (B) DIR 0=OUT / 1=IN

Register 12 (A) Pull-UP 0=aus / 1=ein
Register 13 (B) Pull-UP 0=aus / 1=ein


und Register 18 /19 einlesen ...


Register 18 (A) IO 0=LOW / 1=HIGH
Register 19 (B) IO 0=LOW / 1=HIGH

modtronic
08.03.2017, 22:56
das hatten wir doch schon mal ...

Register 0 /1 und 12/13 wie folgt schreiben ...

Register 0 (A) DIR 0=OUT / 1=IN
Register 1 (B) DIR 0=OUT / 1=IN

Register 12 (A) Pull-UP 0=aus / 1=ein
Register 13 (B) Pull-UP 0=aus / 1=ein


und Register 18 /19 einlesen ...


Register 18 (A) IO 0=LOW / 1=HIGH
Register 19 (B) IO 0=LOW / 1=HIGH

Vielen Dank

ich möchte jedes der 8 Eingänge in eine Variable schreiben..
da habe ich gerade irgendwie ein Problem..oder ich seh den Wald vor lauter bäumen nicht

Gruss
Patrick

HaWe
09.03.2017, 09:51
du liest ja bytes, also 8 Eingänge als Bitmuster auf einmal.
Ist dein Problem, wie du das Byte in ein Bitpattern auflösen kannst, wo jedes Bit einen diskreten Eingang repräsentiert?

das wäre dann so etwas was du meinst...? (source ist dein Byte, funktioniert aber auch mit int)

#define bitRead(source, bit) ( ((source) >> (bit)) & 0x01 )

daneben kann man noch machen:

#define bitSet (source, bit) ( (source) |= (1UL << (bit)) )
#define bitClear(source, bit) ( (source) &= ~(1UL << (bit)) )
#define bitWrite(source, bit, bitvalue) ( bitvalue ? bitSet(source, bit) : bitClear(source, bit) )

modtronic
09.03.2017, 17:05
Hallo

Nein..ich möchte einfach 1 Byte eines MCP23017 auf einen anderen Übertragen...relativ simpel.
über eine Expander soll der Bus dann ca 10 - 15 Meter überwinden. Auf der Eingabeseite sollen dann 4 MCP sitzen mit der CPU und sender und auf der anderen Seite der Empfänger mit 4 MCP23017 als Ausgabe. also nix wildes. so spare ich mir halte viele Adern.

Daher der Gedanke immer ein Byte in eine Variable Lesen z.b int data1, int data2..etc und einfach auszugeben.

vom Programm her wäre das ub.
data = i2c_read (0x12)..lesen vom MCP..aber irgendwie will er das nicht so machen

Gruss
Patrick

RoboHolIC
10.03.2017, 16:11
Hast du jetzt schon zwei MCPs auf dem Bus? Falls ja, mit unterschiedlichen HW-Adressen?

modtronic
10.03.2017, 17:14
Hast du jetzt schon zwei MCPs auf dem Bus? Falls ja, mit unterschiedlichen HW-Adressen?

Hallo

Ja..habe zwei Stück am Bus
einer sind alle Adresspins auf Low der andere alle auf HIgh.
zum testen reicht es ja erstmal.

bei einem wollte ich alle 16 Pins über Pull Down auf Masse legen, habe ich aber noch nicht gemacht
der andere sind 16 Leds über 2 ULN 2804 Treiber angeschlossen

Gruss
Patrick

modtronic
17.03.2017, 13:10
Hallo

Keiner der mir hier helfen kann ?
Das mit den Registern verstehe ich nicht, was ihr meint

Laut Datenblatt muss ich 0x12 und ox13 lesen für die Eingangpins.
Leider weiss ich auch noch nicht so ganz welche Adresse er zb bei alle Adresspins auf LOw braucht

0x21 ? 0x41 ?

Beispiel
i2c_start();
i2c_write(0x21); (0x41) ??
data = i2c_read(0x12);
i2c_stop();

kann mir hier mal einer auf die Sprünge helfen ? beim PCF 8574 war das kein Problem

Hat den keiner nen kleinen Programmauszug ? stehe grade irgendwie auf dem Schlauch

Patrick

RoboHolIC
18.03.2017, 00:24
Hallo modtronic.


Laut Datenblatt muss ich 0x12 und ox13 lesen für die Eingangpins.
Leider weiss ich auch noch nicht so ganz welche Adresse er zb bei alle Adresspins auf LOw braucht

0x21 ? 0x41 ?


0x12 und 0x13 sind richtig nach einem Reset, ohne Manipulation des BANK-Bits (ich schrieb bereits darüber), ist also OK nach PowerUp.
Die selben Register kannst du im Ziel-/Output-IC auch beschreiben. Die Werte werden aber in die OLATx-Register geschrieben, die Output LATches.
"Richtiger" wäre es, die OLATx direkt zu beschreiben, macht aber nix.

Oh ja, die liebe Adressverwirrung bei I2C in der Praxis dank des separat betrachteten r/W-Bits :((
Inklusive des R/W-Bits muss aus Controllerperspektive als Control Byte zur Schreibadressierung eine 0x40 und zur Leseadressierung eine 0x41 in das Senderegister des Controllers geschrieben werden, wenn alle Adresspins LOW sind.- so kenne ich das zumindest.
Wenn alle Adresspins HIGH sind, müssen das entsprechend 0x4E und Leseadresse 0x4F sein.

In meinem Datenblatt ist das in Kap. 1.4 "Hardware Address Decoder" aufgezeichnet. Daran sollte man es eigentlich erkennen können. Mag sein, dass manche Library die Unterscheidung zwischen Adresse und Control Byte nachvollzieht; dann wären die Adressen eben 0x20 (Adr. LLL) und 0x27 (Adr. HHH). (letztere Betrachtungsweise finde ich irreführend, wiel ich bei 0x'irgendwas' eben an 8-Bit-Einheiten denke.)
Setz dich wirklich damit auseinander, damit du das unter die Füße kriegst. Wenn's doch nicht klarer wird, frag nochmal nach.

modtronic
23.03.2017, 08:33
Hallo modtronic.



0x12 und 0x13 sind richtig nach einem Reset, ohne Manipulation des BANK-Bits (ich schrieb bereits darüber), ist also OK nach PowerUp.
Die selben Register kannst du im Ziel-/Output-IC auch beschreiben. Die Werte werden aber in die OLATx-Register geschrieben, die Output LATches.
"Richtiger" wäre es, die OLATx direkt zu beschreiben, macht aber nix.

Oh ja, die liebe Adressverwirrung bei I2C in der Praxis dank des separat betrachteten r/W-Bits :((
Inklusive des R/W-Bits muss aus Controllerperspektive als Control Byte zur Schreibadressierung eine 0x40 und zur Leseadressierung eine 0x41 in das Senderegister des Controllers geschrieben werden, wenn alle Adresspins LOW sind.- so kenne ich das zumindest.
Wenn alle Adresspins HIGH sind, müssen das entsprechend 0x4E und Leseadresse 0x4F sein.

In meinem Datenblatt ist das in Kap. 1.4 "Hardware Address Decoder" aufgezeichnet. Daran sollte man es eigentlich erkennen können. Mag sein, dass manche Library die Unterscheidung zwischen Adresse und Control Byte nachvollzieht; dann wären die Adressen eben 0x20 (Adr. LLL) und 0x27 (Adr. HHH). (letztere Betrachtungsweise finde ich irreführend, wiel ich bei 0x'irgendwas' eben an 8-Bit-Einheiten denke.)
Setz dich wirklich damit auseinander, damit du das unter die Füße kriegst. Wenn's doch nicht klarer wird, frag nochmal nach.

Guten Morgen

Leider verstehe ich das nicht was du mir sagen willst
die 0x12 und 0x13 habe ich schon ausgelesen jedoch bekomme ich keine Daten vom MCP

also muss ich 0x41 schreiben
und kan dann 0x12 und 0x13 in eine Integer Variable schreiben?

so ?
i2c_start();
i2c_write(0x41);
data = i2c_read(0x12);
i2c_stop();

das habe ich so schon gemacht..in der Variable tut sich gar nix

Das hier ist doch für C-Programmierung gedacht..hier sind doch leute die es schon gemacht haben
kann da nicht mal einer nen kleines Beispiel schreiben,,mit du musst diese Register auslesen komme ich nicht weiter

Gruss
Patrick

Feuerring
23.03.2017, 08:56
Leider verstehe ich das nicht was du mir sagen willst
die 0x12 und 0x13 habe ich schon ausgelesen jedoch bekomme ich keine Daten vom MCP

steht ja auch in 0x18/0x19

Klebwax
23.03.2017, 09:45
Mag sein, dass manche Library die Unterscheidung zwischen Adresse und Control Byte nachvollzieht

Dann würde sie sich daran orientieren, was im geschriebenen Standard (www.nxp.com/documents/user_manual/UM10204.pdf) und eigentlich auch in allen Datenblättern der Bausteine steht. Es gäb dann natürlich auch nicht mehr soviele Threads in den Foren "Kann meinen I2C Slave nicht ansprechen" oder


Er hört allerdings auf die Adresse 0x40 anstatt auf 0x20..gibt es hier Bauart Unterschiede


(letztere Betrachtungsweise finde ich irreführend, wiel ich bei 0x'irgendwas' eben an 8-Bit-Einheiten denke.)

Warum grad 8 und nicht 16, 32 oder 64? Es gibt auch genügend kleinere Werte, Prescaler Register z.B. die dann auch noch auf ungraden Bitadressen liegen. I2C mit Adresse und R/W Bit ist ja noch harmlos, schau dir mal andere Protokolle an. Da werden die Bytes (meist Oktets genannt) munter mit unterschiedlich großen Werten gefüllt. Und wenn 8 mal nicht reichen, 16 aber zu viel sind werden die Reste in einem Byte gesammelt (Nunchuk). Wenn man damit arbeiten will, muß man sich das natürlich immer passend zusammensetzen.

MfG Klebwax

HaWe
23.03.2017, 11:08
@modtronic:
zum Einen darfst du nicht vergessen: i2c-Funktionen sind keine Funktionen der Sprache C oder C++, das gibt es dort nicht. Deshalb gibt es keinen Standard dafür.
Es sind mehr oder weniger komplexe Implementierungen in Form von verschiedensten API libs, die die Basis-Funktionen (reine file Operationen) mit Wrappern "angenehmer" machen.
Aber auch File-I/O ist eigentlich kein C-Standard, sondern wieder in optionalen Libs definiert, wie zB. stdio.h .
Gerade AVRs haben aber gar nicht das "übliche" stdio.h, sondern was ganz anderes, z.B. lib.c und ähnliches, was es aber für gcc C auf Linux nicht in dieser Form gibt.
Also ist dein Problem kein C Problem, sondern ein ganz spezielles AVR-Library-Problem; wie es mit gcc samt Linux Libs geht, habe ich ja oben erklärt, da sind die Libs halt einfach besser verständlich oder praktischer anwendbar.
Noch einfacher als Basis-File-I/O gehen komplexere Libs wie wiringPi, die dort ebenfalls gern verwendet werden.
Aber auch für AVRs gibt es so etwas für C/C++, z.B. von Arduino, deswegen wird Arduino so gern genommen (hier ist es die Wire-Class).
Nützt dir ntl nichts, wenn es so etwas für deine Plattform nicht gibt, dann musst du es selber bauen.

Oder zu Arduino überwechseln.

Zu deinem Problem:
Bevor du an 2 Fronten mit 2 MCPs kämpfst, musst du erstmal jeden einzeln beherrschen.
Es klingt ja, als ob du den 1. schon mal auslesen kannst.
Jetzt versuche deinen 2. MCP mit anderer Adresse von einem extra Programm aus einzeln anzusprechen, zum Schreiben.
Versuche z.B. einzelne LEDs einzeln mit Software-Befehlen an und auszuschalten (ohne externe Taster, z.B. einfach als Lauflicht in einer for() Schleife).
Kannst du das?
Mit "meinen" gcc Linux API Libs klappt das, also muss es auch mit "deinen" funktionieren, nur eben mit anderer Syntax (die ich aber nicht kenne).
Wenn du das dann kannst, versuche den Input vom ersten (z.B. per 16 einzelne Taster) 1:1 auf den 2. zu übertragen (Anzeige dort über 16 einzelne LEDs).

Hier siehst du so ein Beispiel für gcc mit Linux und wiringPi, nur um das Prinzip deutlich zu machen:
http://wiringpi.com/extensions/i2c-mcp23008-mcp23017/