Forum: Mikrocontroller und Digitale Elektronik AVR TWI - Frage zu TWSTA


von Michael L. (eagle87)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von Harald M. (mare_crisium)


Lesenswert?

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

von Michael L. (eagle87)


Lesenswert?

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

von Harald M. (mare_crisium)


Lesenswert?

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

von Michael L. (eagle87)


Angehängte Dateien:

Lesenswert?

Hallo Harald,
für das Senden von SLA+R/W habe ich eine Funktion wie folgt:
1
#define TWI_WRITE 0
2
#define TWI_READ 1
3
#define TWI_SLA 0x78
4
5
...
6
7
void TWI_adr(uint8_t SLA_RW)
8
{
9
  TWDR=SLA_RW;
10
  TWCR|=(1<<TWINT);
11
  while(!(TWCR&(1<<TWINT)));
12
  if((TWSR&0xF8)!=TW_MT_SLA_ACK) TWI_error(TW_MT_SLA_ACK);
13
}

Diese wird wie unten aufgerufen:
1
TWI_adr((TWI_SLA<<1)|TWI_WRITE);

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

von Harald M. (mare_crisium)


Lesenswert?

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

von Michael L. (eagle87)


Lesenswert?

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:
1
TWCR&=(~((1<<TWINT)|(1<<TWSTA)));

Danke für die Tipps
Michael

von Harald M. (mare_crisium)


Lesenswert?

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

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.