www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit TWI / SCL geht nicht


Autor: Flo S. (agemta)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hey

Ich bin seit einer Woche dran, einen TWI Bus zwischen 2 ATMega8 zu 
programmieren (in C mit Code::Blocks). Und ich verzweifle fast. Das 
Prinzip habe ich verstanden. Aber es geht nicht.

Es kommt nicht mal ein Takt auf dem SCL an. Ich habe externe Pull up 
Widerstände von 2,2 kOhm. An meinem PortB habe ich 8 LEDs angeschlossen 
um den Status des TWI anzuzeigen. Nun sehe ich, dass der Master 0xF8 und 
der Slave 0x00 im TWSR hat. Was hat das zu bedeuten?

Meine Programme habe ich angehängt!

Bitte helft mir! Ich bin verzweifelt!

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Fehler sind lt. TWI.h:
/* no state information available */
#define TW_NO_INFO    0xF8

/*  illegal start or stop condition */
#define TW_BUS_ERROR    0x00

Ausserdem glaub ich mal, dass  _delay_ms(1000); in der Start-Funktion 
nix zu suchen hat. Der Timeout der TWI-Hardware beisst da zu, noch bevor 
delay überhaupt in den 2-Stelligen ms-Bereich kommt. Raus damit.
Das Senden von Start-Kondition, Slave-ID, Daten, Stop-Kondition sollte 
möglichst in einer Funktion OHNE delays erfolgen.

Autor: Flo S. (agemta)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Ich hab die delay Funktion rausgeschmissen. Und siehe da, es 
funktioniert! aber leider nur teilweise! Beim Senden das DATA Bytes 
bricht es ab und bekommt als Status die 0x58 . Das bedeutet laut 
datenblatt:Databyte has been received, ACK has been returned
d.h. ich habe den Master nicht im "sende"modus sondern im 
"empfangs"modus!
Muss ich beim Senden der Slaveadresse das R/W Byte 0 oder 1 machen damit 
ich daten schicken kann?

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass er abbricht, ist sozusagen normal. 0x58 heisst, dass vom Slave ein 
NACK zurückgekommen ist, d.h. der Slave will keine weiteren Daten mehr.
Wenn er mehr will, muss mit ACK geantwortet werden.

R/W-Byte: Zum Senden Master=>Slave: 0, fürs Auslesen eines Slaves: 1.

Autor: Flo S. (agemta)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ok..also ich habe jetzt mal beim Master das Datenbyte einfach hochzählen 
lassen nach jedem senden und dann beim Slave das Datenbyte auf den PORTB 
gelegt. Es ändert sich nichts. Es wird immer nur der Startwert (0) des 
Datenbytes angezeigt. D.h. der Slave empfängt noch keine Daten. Ich 
verstehen das nicht. Die Adresse wird richtig übermittelt aber er 
erkennt dann nicht das Datenbyte!
So ein S....!!!
Habt ihr vielleicht noch eine Idee für mich!
Ich hänge noch mal den überarbeiteten Quelltext an.
Danke schon mal für eure schnelle Hilfe!

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo S. schrieb:

> Ich hänge noch mal den überarbeiteten Quelltext an.

Als ich das hier:
    if(help==0x60)  TWSI_TW_SR_SLA_ACK();              //x60
  if(help==0x68)  TWSI_TW_SR_ARB_LOST_SLA_ACK();     //x68
  if(help==0x70)  TWSI_TW_SR_GCALL_ACK()  ;          //x70
    if(help==0x78)  TWSI_TW_SR_ARB_LOST_GCALL_ACK();   //x78
    if(help==0x80)  Data=TWSI_TW_SR_DATA_ACK();        //x80
    if(help==0x88)  Data=TWSI_TW_SR_DATA_NACK ();      //x88
    if(help==0x90)  TWSI_TW_SR_GCALL_DATA_ACK();       //x90
    if(help==0x98)  TWSI_TW_SR_GCALL_DATA_NACK();      //x98
    if(help==0xA0)  TWSI_TW_SR_STOP();                 //xA0
    if((help!=0x60)|(help!=0x68)|(help!=0x70)|(help!=0x78)|(help!=0x80)|(help!=0x88)|(help!=0x90)|(help!=0x98)|(help!=0xA0)) error();


in slave.c ziemlich weit oben sah, habe ich aufgehört, weiterzulesen.

Nehmen wir mal an, dass help == 0x60 ist, dann:

1. ... muss der arme µC trotzdem noch weitere 9 if-Statements 
durchchecken, weil Du das "else" vor allen weiteren ifs vergessen hast.
Optimal wäre übrigens ein case-switch.

2. ... dann ist die Bedingung "(help != 0x68)" TRUE und es wird nach 
error() gesprungen. Übrigens wird - egal, welcher Wert help tatsächlich 
hat, immer nach error() gesprungen! Denn mindestens 8 Deiner 9 
Bedingungen, die Du mit dem Operator "|" verknüpfst, sind immer gegeben!

Bedingungen verknüpfen macht man nicht mit "|" oder "&", sondern mit 
"||" bzw. "&&". Lerne bitte die Unterschiede zwischen logischen und 
bitweisen Operatoren. Du hättest hier "&&" statt "|" nehmen müssen. Aber 
das letzte if-Statement ist sowieso für die Tonne, denn bei "else" 
braucht man das nicht:
    if(help==0x60)       TWSI_TW_SR_SLA_ACK();              //x60
    else if(help==0x68)  TWSI_TW_SR_ARB_LOST_SLA_ACK();     //x68
    else if(help==0x70)  TWSI_TW_SR_GCALL_ACK()  ;          //x70
    else if(help==0x78)  TWSI_TW_SR_ARB_LOST_GCALL_ACK();   //x78
    else if(help==0x80)  Data=TWSI_TW_SR_DATA_ACK();        //x80
    else if(help==0x88)  Data=TWSI_TW_SR_DATA_NACK ();      //x88
    else if(help==0x90)  TWSI_TW_SR_GCALL_DATA_ACK();       //x90
    else if(help==0x98)  TWSI_TW_SR_GCALL_DATA_NACK();      //x98
    else if(help==0xA0)  TWSI_TW_SR_STOP();                 //xA0
    else error();        // alle anderen erzeugen Fehler!

Deine Hausaufgabe wäre nun, das Ding auf einen case-switch 
umzuschreiben. Ist schneller, kompakter und lesbarer.

Ob noch mehr Köpse in Deinem Source sind, kann ich nicht beurteilen. Wie 
gesagt, ich habe danach aufgehört, weiterzulesen.

Gruß,

Frank

Autor: Flo S. (agemta)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Frank! ich werde es gleich ändern! Hab die switch case 
fallunterscheidung total vergessen!

Autor: Flo S. (agemta)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab es verbessert. Aber leider hat sich rein gar nichts geändert! 
der slave hat zuerst 0x60 im TWSR (bedeutet das er die Adresse empfangen 
hat und ACK zurück geendet hat) und danach gleich 0xA0(bedeutet das Stop 
gesendet wurde). Das heißt es kommen keine Daten an! Aber ich habe beim 
Master doch alles so programmiert, wie es im Datenblatt steht und alle 
anderen es auch machen! :-(

Autor: Da I (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also nen weiteren Fehler find ich da jetzt nicht.
Nur sind mir einige Dinge aufgefallen, die zwar jetzt nicht falsch sind, 
aber früher oder später für Probleme sorgen könnten.

Die SlaveID wird immer direkt angegeben, idealerweise als Hex-Wert (z.B. 
bei I2C-EEPROMS 0xA0). Nicht als ungerade Zahl und dann verdoppeln durch 
Shift.

Und Punkt 2, in der Init-Funktion:
TWCR |= ((1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)|(1<<TWEN)|(1<<TWIE)); 

Wie sicher bist du dir bei dieser Zeile, dass z.B. das Bit TWST0 auch 
wirklich 0 ist? (Tip: Was ist, wenn es vor dieser Zeile 1 ist?)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.