Ack-Bit bei I2C lässt sich nicht in µC einlesen

OP #4904826
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ß
Angehängte Dateien:
(Firma: Vescomp) #4904924
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.
#4905003
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
OP #4905604
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ß

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren