Hallo, Habe heute den ganzen Tag damit verbracht einem MCP23009 IOExpander via I2C von einem STM32F103 anzusprechen - leider geht noch immer nichts. Vielleicht kann hier mir jemand einen Ratschlag geben. Grundsätzlich funktioniert die Kommunikation via I2C. Problem 1: IOs werden nicht gesetzt. Problem 2: IOs einlesen geht auch nicht. Zu 1: Am Ausgang hängt eine LED. Kathode am GPIO, dann Vorwiderstand dann GND. Zuerst setzte ich via mcp23009_setIODirection(0x00) alle IOs als Ausgang. Siehe Bild scope_0.png. Versuche ich danach via mcp23009_writeIOs(0x02) den GPIO2 zu setzen, tut sich nichts. Geschrieben wird auf das Register OLAT (0x0A). Siehe Bild scope_2.png. Im DB steht: "A write to this register modifies the output latches that modifies the pins configured as outputs." Das sollte doch so passen, oder muss sonst noch etwas gemacht werden? Zu 2: Die Reihenfolge wie man die Eingänge wieder liest, ist für mich nicht ganz nachvollziehbar. Im DB, ist folgende Zeichnung (Siehe Bild protocol.png) angegeben. In der Routine mcp23009_readIOs(), mach ich folgendes: - START - Schreibe Adresse mit Write Bit - Schreibe 0x0A (GPIO Register) - RESTART - Schreibe Adresse mit Read Bit - Lese mit ACK - Lese mit NACK (Hier stollen die IOs stehen) - STOP Aber irgendwie passt da was nicht. Es werden auch immer zu viele Bytes zurückgeschickt, egal ob ich mit NACK quittiere. Eventuell stimmt das RESTART nicht oder die Reihenfolge also solches. Siehe Bild scope_3.png Vielleicht könnte sich mal jemand den Code anschauen und da Tips geben. Bin für jede Hilfe dankbar. Danke, Max
:
Bearbeitet durch User
Markus M. schrieb: > Kathode am GPIO, dann Vorwiderstand dann GND. Sieht falsch aus, wenn es wirklich so ist.
Markus M. schrieb: > Es werden auch immer zu viele Bytes > zurückgeschickt, egal ob ich mit NACK quittiere Das verstehe ich nicht. Bei I2C wird nichts geschickt. Der Master taktet soviele Bytes aus dem Slave, wie er will. Von alleine kommt nichts vom Slave. Sind zu viele Bytes auf dem Bus, liest der Master zu viele. pegel schrieb: > Wie hast du ADDR beschaltet? Muß richtig sein, der Slave liefert ein ACK MfG Klaus
Klaus schrieb: > Markus M. schrieb: >> Es werden auch immer zu viele Bytes >> zurückgeschickt, egal ob ich mit NACK quittiere > > Das verstehe ich nicht. Bei I2C wird nichts geschickt. Der Master > taktet soviele Bytes aus dem Slave, wie er will. Von alleine kommt > nichts vom Slave. Sind zu viele Bytes auf dem Bus, liest der Master zu > viele. Ja, du hast recht. Von alleine kann der Slave nichts schicken - der Master gibt ja den Takt vor. Hier nochmal der "Netto"-Code, ohne meine Unterfunktionen:
1 | // START
|
2 | while( I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY) ); |
3 | I2C_GenerateSTART(I2C1, ENABLE); |
4 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) ); |
5 | |
6 | // Address und Write Bit
|
7 | I2C_Send7bitAddress(I2C1, 0x40, I2C_Direction_Transmitter); |
8 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) ); |
9 | |
10 | // Transmit Byte
|
11 | I2C_SendData(I2C1, 0x09); |
12 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) ); |
13 | |
14 | // RESTART
|
15 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) ); |
16 | I2C_GenerateSTART(I2C1, ENABLE); |
17 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) ); |
18 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) ); |
19 | |
20 | // Address und Read Bit
|
21 | I2C_Send7bitAddress(I2C1, 0x40, I2C_Direction_Receiver); |
22 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) ); |
23 | |
24 | // Receive with ACK
|
25 | I2C_AcknowledgeConfig(I2C1, ENABLE); |
26 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED) ); |
27 | I2C_ReceiveData(I2C1); |
28 | |
29 | // Receive with NACK
|
30 | I2C_AcknowledgeConfig(I2C1, DISABLE); |
31 | while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED) ); |
32 | io_data = I2C_ReceiveData(I2C1); |
33 | |
34 | // STOP
|
35 | I2C_GenerateSTOP(I2C1, ENABLE); |
36 | while( I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF) ); |
Fällt dir da was auf? > pegel schrieb: >> Wie hast du ADDR beschaltet? > > Muß richtig sein, der Slave liefert ein ACK Ja, die Adresse passt. Der ADDR Pin liegt auf GND.
pegel schrieb: > Sieht falsch aus, wenn es wirklich so ist. Beschaltung sieht so aus. Müsste schon passen, oder? Vielleicht noch einen Pull-Down auf die Interrupt-Leitung (INT) zum MC.
Der Expander hat doch Open-Drain Pins.. die Schalten nach Masse. bedeutet normalerweise das man die Dioden an Plus legen muss und minus über den Expander schaltet. falls die Dioden danach negiert sind lässt sich das mit IO-Direction ändern
Markus M. schrieb: > Beschaltung sieht so aus. Mal abgesehen vom i2c, warum gönnst Du der grünen LED keinen Vorwiderstand? Und 5Ohm für die blaue mag zwar rechnerisch passen, praktisch ist der aber zu klein.
Markus M. schrieb: > Beschaltung sieht so aus. Bei 220µA Pullup sollten die LEDs nicht sonderlich hell sein.
Philipp K. schrieb: > Der Expander hat doch Open-Drain Pins.. die Schalten nach Masse. > > bedeutet normalerweise das man die Dioden an Plus legen muss und minus > über den Expander schaltet. > > falls die Dioden danach negiert sind lässt sich das mit IO-Direction > ändern Oje, ich befürchte du hast recht. Da hab ich das DB schlecht gelesen grrrr Ich bin extra vom PCF8574 auf diesen umgestiegen weil ich die Versorgung schalten muss. Hatte das auch mit dem MCP23008 am Steckbrett getestet und dachte dass der MCP23009 das auch kann. Danke für den Hinweis. Jetzt werde ich doch den 08er im kleinen QFN Package nehmen müssen. Damit sollte das erste Problem schon mal behoben sein.
2k Ohm Pull-Ups ist auffälig wenig, bist du sicher, daß dein Chip genug Strom liefern kann? Ich würde das mal analog mit einem Oszilloskop prüfen.
Stefan U. schrieb: > 2k Ohm Pull-Ups ist auffälig wenig, bist du sicher, daß dein Chip genug > Strom liefern kann? Ich würde das mal analog mit einem Oszilloskop > prüfen. Bei 2k schaut das Signal nicht so schlecht aus ... werde aber auf 4k7 aufstocken.
Ich habe das auch probiert. I2C Pullups 10k. GP0 und GP1 -> Kathode LED -> R -> VCC. Dann habe ich es auf Steckbrett mit Reset Leitung und ohne probiert. Dabei ist mir aufgefallen das die sehr empfindlich ist. Der Reset erfolgt schon wenn man den isolierten Draht berührt. Habe dann ein STM32 Pin dazu verwendet. Die LEDs leuchten mit der Übertragung wie im Bild.
Markus M. schrieb: > Stefan U. schrieb: >> 2k Ohm Pull-Ups ist auffälig wenig, bist du sicher, daß dein Chip genug >> Strom liefern kann? Ich würde das mal analog mit einem Oszilloskop >> prüfen. > > Bei 2k schaut das Signal nicht so schlecht aus ... werde aber auf 4k7 > aufstocken. Holla, mal langsam. In der I2C-Spec steht, dass ein Fast-Mode Device (ein solches ist der genannte Portexpander!) 12mA sinken können muss, denn soviel darf an Pullupstrom verwendet werden. Nach Adam Riese ist das bei 5V ein 416Ohm-Widerstand. Und das sagt mir, 2k sind kein Problem für den Portexpander! Nein, die 2k sind ein vernünftiger Wert für 400kHz. Weder ist der Strom besonders hoch (es sind nur 2,5mA bei 5V), noch wird irgenwas warm. Der MPC23009 stirtbt erst bei 25mA (siehe S29 Datenblatt). Da bist du um Faktor 10 drunter... Literatur: http://www.ti.com/lit/an/slva689/slva689.pdf http://esd.cs.ucr.edu/webres/i2c20.pdf
Bei 400kHz sieht es etwas Haiflossig aus, ist aber auch mit 10k i.O.
Markus M. schrieb: > Zu 1: Am Ausgang hängt eine LED. Kathode am GPIO, dann Vorwiderstand > dann GND. Da ist so ziemlich alles falsch, was bei 2 Bauteilen eben möglich ist. Der GPIO besitzt einen Open Drain Ausgang (Datenblatt S.1), d.h. er kann grundsätzlich nur nach Gnd schalten. Wie soll die LED jemals Strom bekommen, wenn das andere Ende ebenfalls (über den Widerstand) an Gnd hängt. So wie du es beschreibst, hängt die Anode über den Widerstand an Gnd. Mit der Anode an Gnd und der Kathode an irgendeinem positiveren Potential, kann die LED nicht leuchten - egal was du programmierst. Bei zufälligem Verschaltung von LED/VCC/GND und GPIO gibt es vier Möglichkeiten, von denen genau eine funktionert. Du hast mit sicherem Griff diejenige Möglichkeit erwischt, bei der es aus zwei Gründen nicht funktionieren kann (LED-Polung, Typ der GPIO Ausgangsstufe). Bevor du dich an I2C-Kommunikation mit so einem Chip wagst, solltest du dich erstmal mit den Grundlagen von LEDs und elementarsten digitalen Schaltstufen beschäftigen.
Ja, das ist schon geklärt. Ich weiß dass ich den falschen IO Expander erwischt habe. Ich hatte ursprünglich den PCF8574 geplant, der hat aber auch Open Drain Ausgänge und kann nur gegen GND schalten. Dann bin ich auf den MC23008 umgestiegen hatte alles getestet und am Steckbrett hat alles wunderbar funktioniert. Aufgrund der kleineren Bauform hab ich mich dann für den MC23009 entschieden und bin fälschlicherweise davon ausgegangen dass der die selbe Ausgangsbeschaltung wie der MC23008 hat. Mein Fehler. Jetzt werde ich wieder auf den MC23008 im QFN Package umstiegen! Mir ist nur noch nicht klar ob mein I2C RESET passt. Das werde ich mir aber anschauen wenn ich den MC23008 verbaut habe. Liebe Grüße, Markus
Ich kenne den Chip nicht, aber bei allen Bekannten wurde - so Du ihn denn brauchst - ein Zieh-Hoch am Interruptausgang benötigt. Meist mit dem gleichen Wert wie bei SCL und SDA. Ist halt OC. Eventuell kann man auch mit den internen (µP) Zieh-Hochs spielen.
pegel schrieb: > Bei 400kHz sieht es etwas Haiflossig aus, ist aber auch mit 10k i.O. Klar kann das gehen. Deswegen habe ich die Appnote von TI verlinkt. Im Endeffekt hängt es mit der Kapazität im Bus zusammen. Meine Erfahrung ist allerdings: Umso niederohmiger die Pullups, umso zuverlässiger. Und die 2,5mA von den 2k stören nicht wirklich. Ich sehe keinen logischen Grund, diese nicht zu verwenden. Sie verheizen sogar bei 5V lediglich 12,5mW, selbst ein 0402er SMD-Widerstand lacht darüber nur. Und weil I2C notorisch zickig ist, ist jedes bischen Zuverlässigkeit hochwillkommen ;-)
So, update ... aber noch immer nicht geschafft. Ich bin jetzt auf den MCP23008 (aus oben erwähnten Gründen) umgestiegen. Am Steckbrett funktioniert alles soweit, nur in meiner eigenen Schaltung, bleibt das ACK nach dem senden der I2C Adresse aus. Anbei zwei Oszi Screenshots. Erstes Bild (mit OK) zeigt die funktionierende Kommunikation. Wobei da der MC auch auf meinem eigenen Board sitzt, der MCP23008 am Steckbrett. Im zweiten Bild (ERROR) sieht man das fehlende ACK. Selber MC in der selben Schaltung nur das der MCP auf einer zweiten Platine von mir sitzt. Die PullUps auf SCL, SDA sind in beiden Fällen 10k, wobei ich auch schon mit 4,7K probiert hab. Irgendwie zieht der MCP in meiner Schaltung die Datenleitung für das ACK nicht runter. Hat vielleicht jemand eine Idee, was da nicht passen könnte?
Bildformate sind kein Hexenwerk Mit verlustfreier komprimierung von PNG verliert man absolut nichts.
Naja ... wenn man zu blöd zum routen ist, dann kann das nicht funktionieren. Aber jetzt haut alles hin!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.