Forum: Mikrocontroller und Digitale Elektronik Ack-Bit bei I2C lässt sich nicht in µC einlesen


von Christian S. (roehrenvorheizer)


Angehängte Dateien:

Lesenswert?

Hallo allerseits,

ich habe eine Schaltung, in der ein Tiny44 mit einem I2C-Display 
verbunden ist. Der µc läuft mit 5V und das Display mit 3,3V. Es 
funktioniert ohne TWI oder USI, sondern nur über direkt gesteuerte Pins.
Auf das Display läßt sich schreiben wie erwartet. Bisher sollte nur 
geschrieben werden, ohne auf das ACK-Bit zu achten, das das Display als 
Antwort zurück gibt.

Neuerdings möchte ich das ACK-Bit auswerten können, um erkennen zu 
können, wenn z.B. das Display nicht antwortet.

Was ich gemacht habe:

Ich habe eine kurze Programmschleife erstellt, die nach dem 
Initialisieren des Displays nur noch "die Adresse und Scrolle zwei 
Zeilen nach unten" angibt, dann kurz wartet. Das Display zeigt den Text 
eben um zwei Zeilen verschoben an.
Somit lassen sich die zwei zu übertragenen Bytes samt ACK-Bit auf dem 
Oszilloskop darstellen. Bei falscher Adresse erscheinen keine ACK-Bits, 
also ACK bleibt high, bei korrekter Adresse erscheint nach beiden Bytes 
ACK = 0 low.

Nur gelingt es mir trotz aller Versuche nicht, das ACK-Bit im Programm 
zu erkennen. Es ist immer 0. Warum nur? Liegt es am Pegel oder doch am 
Programm?

Vielleicht kann mir bitte jemand auf die Sprünge helfen, wo mein 
Denkfehler liegt oder mir zeigen, wie das richtig geht.

Im Anhang findet sich eine gekürzte compilierbare Programmmversion, die 
im Wesentlichen die direkte I2C-Übertragung zeigt.
Das Unterprogramm "GetAck" wird immer am Ende der Übertragung eines 
Bytes aufgerufen. Es soll des SDA-Pin auf Eingang umschalten und den 
Zustand dieses einen Pins einlesen, sowie SCL weiter schalten.

Vielen Dank schonmal.
mit freundlichem Gruß

von A. S. (Gast)


Lesenswert?

Christian S. schrieb:
> das ACK-Bit im Programm zu erkennen. Es ist immer 0.

Was meinst Du mit "0"? Es soll doch low (0) sein, oder?

Übrigens sehe ich nicht ganz, wie Du das Clock-Stretching realisierst. 
Sollte hier aber jetzt keine Problem sein.

von Christian S. (roehrenvorheizer)


Lesenswert?

Falls die Adresse falsch ist, soll es aber 1 sein.

MfG

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian S. schrieb:
> Falls die Adresse falsch ist, soll es aber 1 sein.

 Deine Routinen benutzen "WaitHalfCycle()", welche (mit Aufruf)
 17 Taktzyklen braucht. 17 Taktzyklen sind bei 8MHz 2.25us.
 Mal 2 ergibt 4.5us. Ergibt 222KHz.
 Bei 4MHz sind es immer noch 111KHz.
 Selbst mit Pinumschalten dazwischen ist das sehr knapp.

 Aber egal.

 Solange du nur schreibst gibt es auf SDA definierte Zustände,
 entweder LOW oder HIGH.
 Wenn du aber lesen willst, brauchst du PullUp auf SDA, entweder
 direkt am I2C Bus oder internen PullUp von Tiny.

 Und ich sehe nicht, dass bei dir etwas eingeschaltet wird.
 Falls das Display keine Pullup Widerstände hat, geht so etwas mit
 sehr hoher Wahrscheinlichkeit in die Hose, weil bei NACK der BUS
 nur HiZ (Potentialfrei) ist und das ist bei 3V3 auf 5V wahrscheinlich
 nicht gut genug.

von Christian S. (roehrenvorheizer)


Lesenswert?

Es sind Pullup-Widerstände 2,2k zu +3,3V eingebaut.

MfG

von Michael U. (amiga)


Lesenswert?

Hallo,

I2C ist ein Bus, der High nur von den PullUp-Widerständen bekommt und 
bei dem nur aktiv Low gesteuert wird. Insofern ist der Ansatz, hart ein 
H anzulegen, ohnehin riskant.
Ein Slave kann prinzipiell jederzeit SDA oder SCL auf Low ziehen (Clock 
Stretching wurde ja schon genannt), dann wird ein auf H befindlicher 
Ausgang des AVR vom Slave auf L gezogen... Das ist mehr oder weniher ein 
Kurzschluß und nicht so gesund für die Hardware.

Üblicherweise wird der SDA und SCL als Ausgang/Low für Low oder als 
Eingang als High gesetzt. Es wird also über das DDR gesteuert. Damit 
gibt es auch keine Konflikte beim Einlesen, wenn SDA/SCL vom AVR auf 
"High" gesetzt sind, sind sie ohnehin Eingang und können jederzeit 
gelesen werden.

Also SDA/SCL auf per DDR Eingang und Output auf Low ist Ruhepegel High 
durch externem PullUp. Für Low jetzt nur DDR aus Ausgang und dann wieder 
auf Eingang.

Gruß aus Berlin
Michael

von Christian S. (roehrenvorheizer)


Lesenswert?

Hallo,

danke für die Antworten.

Im Prinzip wollte ich es ja so verwirklichen, wie Du erklärt hast.

Ganz oben in meinem Programm steht:
"Achtung!!! Damit das Display niemals über 4 Volt abbekommt, dürfen die 
I2C-Ausgänge NIEMALS hart gegen + schalten, sondern müssen immer nur 
gegen GND schalten und für high auf hochohmig geschaltet werden."

Ich denke, das war von vornherein klar.

Mit freundlichem Gruß

von Christian S. (roehrenvorheizer)


Lesenswert?

ACK oder NOACK?

von Christian S. (roehrenvorheizer)


Lesenswert?

Hallo,

war vielleicht schon jemand mit einem solchen Fall konfrontiert?

MfG

von grundschüler (Gast)


Lesenswert?

vielleicht helfen dir meine bitbang-i2c-routinen weiter. Müsste 
eigentlich das gleiche Problem sein. Funktioniert einwandfrei.

Beitrag "Re: stm32f103 i2c_read"

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
Noch kein Account? Hier anmelden.