PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I²C - Stop Bestätigung?



CowZ
13.10.2006, 20:47
Hi,

wollte euch mal fragen, ob ihr wisst, wie ich bei dem I²C Protokoll in nem AVR (HW) gucken kann, ob die STOP Bestätigung gesendet wurde, bzw. auf was ich danach warten muss, bevor das nächste START kommt.

Vielen Dank für eure Hilfe :)

Gruß, Lasse

Pascal
13.10.2006, 20:57
Willst du direkt nach dem STOP wieder ein START schicken? Dann kannst du auch einen sogenannten "repeated start" machen. Das bedeutet, du sendest einfach wieder ein START, ohne davor ein STOP zu senden, so kann man z.B. die Addressierung ändern, ohne, dass der AVR die Kontrolle über den TWI-Bus evtl. an einen anderen µC verliert.

Falls du aber doch ein STOP senden willst, kannst du meines Wissens nach durch das Bit TWSTO im TWCR feststellen, ob STOP gesenden wurde. Dieses Bit wird ja gesetzt, um ein STOP zu senden. Und, wenn das Bit nicht mehr gesetzt ist, ist die Übertragung fertig.

CowZ
13.10.2006, 21:20
Hi,
danke für die Antwort.

Ich möchte kein Repeated Start machen, sondern wirklich wissen, wann mein STOP fertig ist.

Ist da die Variante mit TWSTO wirklich richtig? Weil beim Start wartet man ja einfach ab, dass TWINT gesetzt wird. Beim STOP scheint(!) diese Variante aber nicht zu funktionieren.

edit: kleine Zwischenfrage: Sehe ich das richtig, dass ich bei nur einem Master kein STOP brauche, sondern nur Repeated Start einsetzen kann?

Gruß, CowZ

Pascal
13.10.2006, 21:27
Ist da die Variante mit TWSTO wirklich richtig?

Ob sie wirklich richtig ist, weiß ich nicht, aber bei mir funktionierts damit.



Weil beim Start wartet man ja einfach ab, dass TWINT gesetzt wird. Beim STOP scheint(!) diese Variante aber nicht zu funktionieren.

Beim STOP verwendet man ja auch nicht die Methode mit TWINT, sondern mit TWSTO.

CowZ
13.10.2006, 21:34
Ja, bei mir funktionierts auch :)

Die Frage, ob das "richtig" ist, bleibt natürlich. Könnte ja auch nur n netter workaround sein oder so. Aber trotzdem erstmal danke dafür :)

Gruß, CowZ

Pascal
13.10.2006, 21:50
Writing the TWSTO bit to one in Master mode will generate a STOP condition on the Two-wire Serial Bus. When the STOP condition is executed on the bus, the TWSTO bit is cleared automatically.

Das steht im Datenblatt des ATMega8 in der Definition des TWSTO-Bits im TWCR-Register.
Meiner Meinung nach stützt das unsere Vermutung.

linux_80
13.10.2006, 22:08
Hallo,

hast Du da schon mal reingeguckt:
https://www.roboternetz.de/wissen/index.php/TWI_Praxis
da hab ich das durch setzen der Register gemacht.

Nach dem STOP warte ich nicht mehr, denn bis zum nächsten START, sollte es auf jeden Fall gesendet sein, solange das START nicht direkt gleich die Zeile danach kommt.
Ein STOP ist ja nur die beiden Leitungen loszulassen, kann man ja mal ausrechnen wieviel Takte der AVR macht, bis das geschehen ist.

Normalerweise fragt man das Statusregister ab nachdem TWINT gesetzt ist, und kann dann entscheiden was passiert ist, in Abhängigkeit was man eigentlich vor hatte.
Für STOP gibts aber keinen speziellen Status.
Steht auch nix besonderes im DB was passiert nach dem STOP.

Edit:
ich seh grad, das steht doch drin:
"Note that TWINT ist NOT set after a STOP condition has been sent."

CowZ
14.10.2006, 00:34
Hi,

die Definition des TWSTO ist sehr hilfreich, danke :)

Nicht auf das Ende des Stops zu warten empfinde ich als "Katastrophe" ;) Vorallem, da du dir nicht sicher sein kannst, mit welcher Geschwindigkeit der Bus läuft (da diese von den Slaves gedrosselt werden kann).

Daher ist die Lösung mit TWSTO wohl optimal :) Danke :)

Gruß, CowZ

linux_80
14.10.2006, 01:24
Warum soll das eine Katastrophe sein, :-k
wenn's so eilt ein Start auf ein STOP zu senden, kann man das doch auch gleich als ein Befehle machen, ist zumindest im AVR so vorgesehen !
Also gleichzeitiges setzen von TWSTO und TWSTA nach der letzten Aktion.

Ich denke es gibt auch nichts was ein abgesetztes STOP noch verhindern könnte.

Und in einem normalen Ablauf dauerts doch ein paar Takte, bis sich wieder entscheidet, das was gesendet werden soll, und da ist das Stop schon durch.
Chaos könnte dann nur noch passieren, wenn zB. in verschiedenen ISRs etwas am TWI gemacht wird, die sich nicht synchronisieren.

CowZ
14.10.2006, 01:34
Hi :)

Manchmal kann man eben nicht wissen, ob im nächsten Takt schon wieder ein START kommt, oder eben nicht. Und daher sollte man imho auf das Ende des STOPS warten. Ob das nun irgendwas stört oder nicht, kann ich nicht einschätzen, aber ich finde es einfach unschön ;)

Gruß, CowZ

linux_80
14.10.2006, 01:49
Ich will ja von nix abhalten, will nur selber wissen obs das auch braucht.

Es wird auf jeden Fall interessant sein zu sehen wie lange das TWSTO nun gesetzt bleibt, das DB meint ja :
"When the STOP condition is executed on the bus, the TWSTO bit is cleared automatically."
Das können doch max. 2 Takte zu, sagen wir mal, 100kHz sein,
kommt dann auf 320 Takte bei 16MHz ? oder :-k

schau ma mal ... 8-[

CowZ
14.10.2006, 02:11
Hi,

dabei musst du bedenken, dass I²C auch wesentlich langsamer (Slave-Drosselung) und wesentlich schneller (FastMode) sein kann.

Aber ansich ein schönes Experiment. Freu mich auf deine Ergebnisse ;)

Gruß, CowZ

linux_80
14.10.2006, 13:25
Ja dann sind wir mal nicht so ;-)
ich hab als Testprogramm das aus der Wiki-Seite verwendet, und gleich nach der Stop übergabe diese Warteschleife eingebaut:

Do
Incr Testcnt
Loop Until Twcr.twsto = 0

Print "stop: " ; Testcnt
Bei 16Mhz komme ich auf den Wert 9.

So schaut das ganze in Assembler aus:


# Do
# Incr Testcnt
+00000106: E6A4 LDI R26,0x64 Speicherort von Testcnt
+00000107: E0B0 LDI R27,0x00
+00000108: 918C LD R24,X Wert aus SRAM holen
+00000109: 5F8F SUBI R24,0xFF +1
+0000010A: 938C ST X,R24 Wert wieder ins SRAM

+0000010B: 2700 CLR R16 Clear Register
+0000010C: 27BB CLR R27 Clear Register
+0000010D: E5A6 LDI R26,0x56 TWCR über SRAM holen
+0000010E: 918C LD R24,X Load indirect
+0000010F: FB84 BST R24,4 Bit store from register to T, TWSTO ist Bit4

# ... Twcr.twsto = 0 ?
+00000110: F40E BRTC 0x0112 Branch if T flag cleared

+00000111: E001 LDI R16,0x01 Load immediate
+00000112: E040 LDI R20,0x00 Load immediate
+00000113: 1704 CP R16,R20 Compare
+00000114: F011 BREQ 0x0117 Branch if equal, fertig

# loop
+00000115: 940C0106 JMP 0x00000106

+00000117: ....
kann ja mal jemand nachrechnen wieviel Takte das sind ;-)

CowZ
14.10.2006, 14:15
Hi,

mhh...
15 Takte pro Schleife, 9 Schleifen
=> 135 Takte
Kommt natürlich nich ganz hin, weil am Ende das BRTC schon anschlägt usw. aber so ~100 Takte sollten hinkommen.

Viel genauer brauchen wir das ja aber auch nicht, da ja - wie gesagt - die Busgeschwindigkeit variieren kann.

Gruß, CowZ

linux_80
14.10.2006, 15:39
Also dauert der Vorgang keinen ganzen Takt auf TWI-seite,

jetzt müsste man noch mit höherer Busgeschwindigkeit probieren, ob es da auch schneller geht, und das man sieht ob der Vorgang von der TWI-Geschwindigkeit abhängt.
Denn es muss ja nur SDA losgelassen werden.

linux_80
14.10.2006, 21:25
Dann kommt auch noch das Ergebnis zu der Busgeschwindigkeit von 400kHz,
nach dem STOP zählt er jetzt nur noch bis 3.
Ist dann auch ca. die Dauer eines Taktes vom TWI.

CowZ
15.10.2006, 03:54
Ja, sollte ja auch so sein ;)

Und die 300 µC-Takte sollte er dann keine neuen Sachen anfangen. Daher ist also ein warten auf das STOP schon sinnvoll. (Oder? ;))

Gruß, CowZ

linux_80
15.10.2006, 12:55
Ich würde trotzdem sagen, das Warten der falsche Begriff ist, nach dem Stop würde ich jetzt immer noch nicht warten, wenn ich sehe was man da nur machen kann in der Zeit, das braucht man ja schon um zu entscheiden das man ein neues Start will, besser ist es noch vor einem neuen Start nachzuschauen ob das STOP evtl. noch gesetzt ist !

Ist ja sonst nur Zeitverschwendung ;-)

CowZ
15.10.2006, 15:51
Hi,

ja ok, so wollte ich es ja auch machen :P

Gruß, CowZ