Forum: Mikrocontroller und Digitale Elektronik TWI ACK/NACK Problem


von Dirk R. (freak)


Lesenswert?

Hallo,

ich hoffe, die Frage wurde nicht schon tausend mal gestellt und ich habs 
nur nicht gefunden, aber ich habe folgendes Problem.

Ich möchte zwei Controller per TWI miteinander kommunizieren lassen. 
Dabei sollen die zu übertragenden Daten jedoch variabel lang sein. Auf 
Empfängerseite weiß ich jedoch erst beim Empfang des letzten Bytes, dass 
es das letzte war. Also eigentlich schon zu spät, um ein NACK zu senden. 
Wenn ich TWCR erst jetzt so setze, dass er ein NACK sendet, wird das 
nächste Start byte vom Master 'abgelehnt', und die zweite Übertragung 
schlägt dadurch fehl.

Wie wird sowas elegant gelöst? Mir fallen spontan folgende Wege ein:
- keine Variable Länge
- nach dem Senden des letzten Bytes (auf Senderseite) einfach noch ein 
'Füllbyte' senden
- Längenangabe als erstes Byte

Oder habe ich vielleicht ein prinzipielles Rangehensproblem?

Danke
Dirk

von Alex S. (thor368)


Lesenswert?

Tach Dirk,

ein Herangehensproblem ist das sicherlich nicht. Allerdings lässt du 
viele Fragen offen. Ich stückle mir das mal zusammen:

Du benutzt AVRs?
Der Master empfängt eine undefinierte Zahl bytes?

Ich gehe mal davon aus.
Die eleganteste Variante ist den slave die Framelänge bekannt geben zu 
lassen. Sprich das erste byte vom slave zum master ist das längen byte.

Die unelegantere Variante ist ein Stopzeichen zu definieren. ZB eine 0 
oder 255 oder sonst was. Unschön ist natürlich, dass dieses Zeichen dann 
nicht mehr in den Nutzdaten auftauchen darf. Man muss also auch noch ein 
Ersatzzeichen definieren, das das Stopzeichen gegebenfalls maskiert.

Es ist eigentlich wieder eine uhralte Glaubensfrage: Pascal arbeitet mit 
Längenbyte und C mit Stopzeichen.

Thor

von Wolfgang (Gast)


Lesenswert?

Alex S. schrieb:
> Es ist eigentlich wieder eine uhralte Glaubensfrage: Pascal arbeitet mit
> Längenbyte und C mit Stopzeichen.

Der Unterschied ist nur, dass Pascal beliebige Zeichen übertragen kann, 
C nicht. Bei jedem 0x00 geht C von einem Stringende aus.

von spess53 (Gast)


Lesenswert?

Hi

Das ist doch eindeutig geregelt. Wenn der Master sendet beendet er die 
Übertragung mit STOP. Und wenn er empfängt beendet er das mit NACK+STOP.

MfG Spess

von Cyblord -. (cyblord)


Lesenswert?

Wolfgang schrieb:
> Alex S. schrieb:
>> Es ist eigentlich wieder eine uhralte Glaubensfrage: Pascal arbeitet mit
>> Längenbyte und C mit Stopzeichen.
>
> Der Unterschied ist nur, dass Pascal beliebige Zeichen übertragen kann,
> C nicht. Bei jedem 0x00 geht C von einem Stringende aus.

Also String sind in C keine beliebigen Daten, sondern Text. Und in einem 
Text kommen selten 0x00 Bytes vor. Wieso sollte man Nullbytes als 
Nutzdaten in einen String packen wollen? Das macht überhaupt keinen 
Sinn.

gruß cyblord

von Alex S. (thor368)


Lesenswert?

Tach allerseits,

: Der Unterschied ist nur, dass Pascal beliebige Zeichen übertragen
: kann, C nicht. Bei jedem 0x00 geht C von einem Stringende aus.
so sieht's aus. Bei den ANSI strings wurde kein Maskierungszeichen 
definiert. Hätte man das gäbe es keinen praktischen Unterschied zwischen 
den beiden Varianten. Außer, dass the pascal side of the force halt eine 
Ecke eleganter ist.

: Das ist doch eindeutig geregelt. Wenn der Master sendet beendet er die
: Übertragung mit STOP. Und wenn er empfängt beendet er das mit
: NACK+STOP.
Mhh, und was ist, wenn der master nicht weiß wie lang der frame ist?

Thor

von Alex S. (thor368)


Lesenswert?

Tach

: Also String sind in C keine beliebigen Daten, sondern Text. Und in 
einem
Text kommen selten 0x00 Bytes vor. Wieso sollte man Nullbytes als
Nutzdaten in einen String packen wollen? Das macht überhaupt keinen
Sinn.
Schon mal die API comport Funktionen benutzt? Die sind nun mal 
stringbasiert. Und da kann es schon mal vorkommen, dass man eine binäre 
null senden/empfangen möchte. Ich stimme dir ja auch zu, dass strings 
nicht geeignet sind binäre Daten aufzunehmen. Trotzdem sind sie einfach 
so verdammt einfach als dynamische Arrays zu misbrauchen und finden 
desshalb auch nicht nur als Textspeicher Anwendung.

Thor

von Wolfgang (Gast)


Lesenswert?

cyblord ---- schrieb:
> Also String sind in C keine beliebigen Daten, sondern Text.

Das ist schon eine "tolle" Kodierung, bei der man nicht alle möglichen 
Codes verwenden darf, sondern auf einen Sub-Set beschränkt ist.

von Kurt (Gast)


Lesenswert?

Pascal- gegen C-Strings für die Eignung zur
TWI-Übertragung abwägen?

- Setzen, SECHS! Würde auch der beste Lehrer sagen.

Wer was missbraucht, muss wissen, was er tut.
Wenn was "Merkwürdiges" dabei rauskommt,
wusste er/sie das wohl eindeutig nicht! ;-)

von spess53 (Gast)


Lesenswert?

Hi

Macht euch doch keinen Kopf. Der TO hat lediglich ein 
Verständnisproblem. Und ihr wahrscheinlich auch.

MfG Spess

von Dirk R. (freak)


Lesenswert?

Hätte ich geahnt, dass das so ausartet... :D
Ich wollte lediglich ein Best-Practice o.ä. wissen order einfach eine 
zweite Meinung (danke an die erste Antwort ;) )

Aber zur Klärung: Da sollen beliebige Binärdaten rübergehen, u.a. 
Strings.
Da ich jedoch die Länge der Daten benötige, um zum richtigen Zeitpunkt 
mit NACK zu antworten, gebe ich die Länge der Daten als erstes Byte mit.
Da wäre es sinnlos mit speziellen Start und Stop Bytes zu arbeiten, da 
diese dann im Payload escaped werden müssten. Das setzt natürlich 
voraus, dass der Master beim absenden schon weiß, wieviele Daten es 
sind.

Weiß selbst er das nicht und es entscheidet sich einfach im Laufe der 
Übertragung, wann schluss ist, müsste man natürlich zusätzlichen Stop 
Markierungen arbeiten.

So...jetzt sollten alle glücklich sein! Ich bin es :)
Gute nacht!

von spess53 (Gast)


Lesenswert?

Hi

>Da ich jedoch die Länge der Daten benötige, um zum richtigen Zeitpunkt
>mit NACK zu antworten, gebe ich die Länge der Daten als erstes Byte mit.
>Da wäre es sinnlos mit speziellen Start und Stop Bytes zu arbeiten, da
>diese dann im Payload escaped werden müssten. Das setzt natürlich
>voraus, dass der Master beim absenden schon weiß, wieviele Daten es
>sind.

Sieh dir bitte mal die I2C-Spezifikation in Ruhe an. Der Slave sendet 
kein NACK.

MfG Spess

von Dirk R. (freak)


Lesenswert?

Ich hab mich an das Atmega64 Datenblatt gehalten, welches sagt:

"When the Receiver has received the last byte, or for some reason cannot 
receive any more bytes, it should inform the Transmitter by sending a 
NACK after the final byte. "

Dirk

von holger (Gast)


Lesenswert?

>: Das ist doch eindeutig geregelt. Wenn der Master sendet beendet er die
>: Übertragung mit STOP. Und wenn er empfängt beendet er das mit
>: NACK+STOP.
>Mhh, und was ist, wenn der master nicht weiß wie lang der frame ist?

Der Master weiss immer wie lang der Frame ist. Er holt ihn ja
schliesslich aktiv ab, bzw. der Slave sendet nichts von alleine.
Dein Problem ist also keins.

von spess53 (Gast)


Lesenswert?

Hi

>Ich hab mich an das Atmega64 Datenblatt gehalten, welches sagt:

>"When the Receiver has received the last byte, or for some reason cannot
>receive any more bytes, it should inform the Transmitter by sending a
>NACK after the final byte. "

Der Satz im Datenblatt ist etwas unglücklich da nicht ersichtlich ist, 
um welchen Mode es sich handelt. Sieh dir mal weiter hinten im 
Datenblatt

Transmission Modes->Master Receiver Mode

an. Dort siehst du, wer wann ACK bzw. NACK sendet.

MfG Spess

von Dirk R. (freak)


Lesenswert?

Ich bin aber im Slave receiver mode.

Dirk

von spess53 (Gast)


Lesenswert?

Hi

>Ich bin aber im Slave receiver mode.

Da wird jedes Byte vom Slave mit einem ACK bestätigt bis der Master Stop 
sendet. Ausnahme: der Slave kann keine Daten mehr aufnehmen. Dann sendet 
er ein NACK.

MfG Spess

von Dirk R. (freak)


Lesenswert?

Also auch das letzte Byte?

von spess53 (Gast)


Lesenswert?

Hi

>Also auch das letzte Byte?

Ja. Nach dem letzten Byte sendet der Master STOP. Du bringst irgend wie 
Master und Slave Receive Mode durcheinander.

Im Master Receive Mode kennzeichnet der Master das letzte Byte mit einem 
NACK.

MfG Spess

von Dirk R. (freak)


Lesenswert?

So grad probiert...funktioniert nicht.
Ich befürchte grad, der Fehler liegt ganz woanders.

Nochmal als ganzes:
Ein Controller im Master transmitter Mode, ein anderer im Slave receiver 
Mode.
- Master sendet start.
- Master sendet SLA+W und empfängt ACK
- Master sendet Bytes und Slave antwortet auf JEDES Byte mit ACK.
- Master sendet Stop und Slave setzt TWCR = 
(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);

- Master sendet Start für neue Übertragung
- Master sendet SLA+W und empfängt NACK

Was mache ich falsch?

VG
Dirk

von (prx) A. K. (prx)


Lesenswert?

Wenn der TWI State Machine nicht im Vorhinein das letzte Byte 
signalisiert wird, dann wird durch die State Machine ein Fehler 
signalisiert sobald das STOP eintrudelt. Wenn man dann seinerseits per 
STOP der State Machine das Ende der Übertragung signalisiert, dann ist 
alles wieder in Butter.

Wenn man beim Fehlerzustand jedoch beleidigt oder garnicht reagiert, 
dann geschieht das hier Beschriebene.

von Dirk R. (freak)


Lesenswert?

Reicht es, im SR TWCR = 
(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO) zu setzen, wenn Stop 
empfangen wurde? Bleibt nämlich das selbe Verhalten :(

von (prx) A. K. (prx)


Lesenswert?

Siehe "Miscellaneous States" im Datasheet des weiterhin geheimnisvoll 
bleibenden Controllers.

Ansonsten empfehle ich dir, beiderseits der Übertragung die TWI States 
zu protokollieren um festzustellen, was konkret abgeht.

von Dirk R. (freak)


Lesenswert?

Die States des SR hab ich da:

$60 - SLA+W empfangen - ACK geantwortet
$80 - Byte empfangen - ACK geantwortet
...
$A0 - STOP empfangen - TWINT + TWEA gesetzt (Switched to the not 
addressed Slave mode; own SLA will be recognized)

Von der zweiten Übertragung ist im SR schon nichts mehr zu merken.

Auf der MT Seite erhalte ich auf die zweite Start Anforderung ein NACK.

VG

von (prx) A. K. (prx)


Lesenswert?

Dirk R. schrieb:

> $A0 - STOP empfangen - TWINT + TWEA gesetzt (Switched to the not
> addressed Slave mode; own SLA will be recognized)

Dann ist der garnicht so pingelig wie ich dachte.

Könnte es sein, dass der Master es so eilig hat, dass er den Slave schon 
mit dem zweiten START überrennt, bevor der seinen Abschluss getan hat?

von Dirk R. (freak)


Lesenswert?

Ich geh kaputt!!
Daran lags wirklich...hatte zum Testen einfach zwei Nachrichten 
nacheinander verschickt. Das kann man aber nicht vorher prüfen, oder? Da 
hilft nur nochmal probieren?!

VG

von (prx) A. K. (prx)


Lesenswert?

Ich habe bei sowas ohnehin ein paar Retries drin. Gern auch mit Bisschen 
Pause dazwischen.

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.