Hallo,
ich habe eine Frage zu dem TWI START Condition Bit (TWSTA). Im
Datenblatt (des ATmega324A) steht:
> TWSTA must be cleared by software when the START condition has been transmitted.
Wenn ich TWSTA wie im C-Code unten nach der Start Condition löschen
will, ist das TWI Status Register (TWSR) bei der danach folgenden
Abfrage auf 0x48 anstatt auf 0x08.
1
TWBR=(uint8_t)((F_CPU/F_SCL-16)/2);
2
TWCR=(1<<TWEA)|(1<<TWEN);
3
4
TWCR|=(1<<TWINT)|(1<<TWSTA);
5
while(!(TWCR&(1<<TWINT)));
6
TWCR&=(~(1<<TWSTA));
7
if((TWSR&0xF8)!=TW_START)TWI_error(TW_START);
Wenn ich TWSTA einfach lasse wie es ist steht 0x08 in TWSR.
Im Artikel AVR TWI wird bei dem Beispielcode das TWSTA-Bit nicht
gelöscht.
Bedeutet das, dass hier einfach ein Fehler im Datenblatt ist, oder kann
es noch an was anderem liegen?
Gruß
Michael
Hi
Ich denke es ist einfacher TWCR mit einem 8-Bit Wert zu beschreiben, als
einzelne Bits zu setzen oder zu löschen. Dadurch würde bei einem
nachfolgenden Senden von SLA das Start Bit sowieso gelöscht werden,
vermeide also TWCR |= ... und TWCR &= ...
Zudem sollte zuerst der Status gelesen werden und danach TWCR
beschrieben werden.
Grüße,
Oliver
Hi
>Wenn ich TWSTA einfach lasse wie es ist steht 0x08 in TWSR.
Ist doch richtig:
0x08 A START condition has been transmitted
>Bedeutet das, dass hier einfach ein Fehler im Datenblatt ist, oder kann>es noch an was anderem liegen?
Eher Ersteres. Ich habe noch keine Software gesehen, wo TWSTA explizit
gelöscht wurde. Auch in der Software zur AppNote AVR315 nicht.
MfG Spess
Michael,
Du machst das schon richtig so, auch mit dem bitweisen Einstellen des
TWCR.
Nachdem Du festgestellt hast, dass im TWSR die 0x08 steht, das
START-Signal also erfolgreich gesandt wurde, kannst Du (vorsichtshalber)
im TWCR das TWSTA-Flag auf "Null" setzen. Wenn Du das TWCR im
"read-modify-write"-Verfahren einstellst, ist das nicht wirklich
notwendig; schaden tut's auch nicht ;-).
Ciao,
mare_crisium
Das "read-modify-write" würd ich gern beibehalten, da ich dann zu Beginn
mit einer Init Funktion sämtliche Einstellungen vornehmen kann. Und die
entsprechenden Bits danach so belassen wie sie sind.
> Zudem sollte zuerst der Status gelesen werden und danach TWCR> beschrieben werden.
Wenn ich zuerst den Status lese, danach TWSTA lösche und dann ein SLA+W
sende steht anschließend wieder 0x48 im TWSR. Das macht aber dahingehend
Keinen Sinn, da 0x48 bedeutet:
SLA+R has been transmitted;
NOT ACK has been received
Es müsste zu der Zeit also 0x20 im TWSR stehen (Es ist noch kein Slave
am Bus angeschlossen).
Gruß
Michael
Michael,
> Wenn ich zuerst den Status lese, danach TWSTA lösche und dann ein SLA+W> sende steht anschließend wieder 0x48 im TWSR.
Bist du sicher, dass bei Deiner Sklaven-Adresse, die Du ins TWDR
schreibst, das Bit0 auf "Null" steht? Wenn da aus Versehen eine "Eins"
drin steht, dann denkt die TWI-Hardware, dass Du die Schnittstelle als
Master Receiver betreiben willst. Und dann ist 0x48 die richtige
Reaktion auf den fehlenden Sklaven.
Ciao,
mare_crisium
Außerdem steht die 0x48 genau dann im TWSR wenn ich versuche TWSTA zu
löschen. Wenn ich es nicht lösche steht 0x20 drin.
Um nicht nur Codefragmente zu liefern habe ich mal die ganze Datei
main.c angehängt.
Gruß
Michael
Michael,
na, wenn es so ist:
> Außerdem steht die 0x48 genau dann im TWSR wenn ich versuche TWSTA zu> löschen. Wenn ich es nicht lösche steht 0x20 drin.
dann lies' den Wert von TWSR ZUERST und DANACH schreibst Du die
modifizierten Bits ins TWCR.
Dein C-Programm kann ich leider nicht lesen; ich habe bisher nur mit
anderen Programmiersprachen gearbeitet. Meinen ATmegas sage ich auf
Assembler, was ich von ihnen erwarte.
Bei meinem (interruptgetriebenen) TWI-Handler lese ich zu allerst das
TWSR ein und schiebe es 3 Bits nach links. Den Wert, der dabei
herauskommt, nehme ich als Index in eine Tabelle, in der jedem Wert von
TWSR eine Prozedur zugeordnet ist.
Es gibt also für jeden Wert des TWSR genau eine Prozedur. Diese Prozedur
stellt dann die Reaktion auf das her, was an der Schnittstelle gerade
passiert ist. Der Wert von TWCR wird AUSSCHLIESSLICH innerhalb dieser
Prozeduren festgelegt und in das Register geschrieben. - Also so wie
oben gesagt: Erst das TWSR auswerten, und dann die Bits in TWCR
verändern (und dabei daran denken, dass man das TWINT-Bit löscht, indem
man eine "Eins" hineinschreibt;-) ).
Ciao,
mare_crisium
Hallo Harald,
hab jetzt den Fehler gefunden. Deine Anmerkung zum TWINT hat mich auf
die Idee gebracht.
> und dabei daran denken, dass man das TWINT-Bit löscht, indem> man eine "Eins" hineinschreibt;-)
Beim read-modify-write Verfahren darf ich nicht einfach nur das
TWSTA-Bit löschen, sondern muss auch das TWINT auf Null setzen.
Ansonsten wird ja eine 1 hineingeschrieben und der nächste Sendevorgang
gestartet. Der Kompiler macht also kein Bitbefehl draus :P
So funktionierts:
Michael,
> hab jetzt den Fehler gefunden.
freut mich sehr! Hat Spass gemacht, Dir zu helfen, weil Du immer schön
logisch vorgangen bist :-)
mare_crisium