Forum: Mikrocontroller und Digitale Elektronik Probleme mit TWI und ACK


von ben.pu (Gast)


Lesenswert?

Hallo,

Seit einiger Zeit probieren wir uns schon die Finger wund um eine Master 
Slave-Kommunikation herzustellen. Jedoch gibts immer irgendwelceh 
Probleme.
Zuerst am besten die Codes...

main-Funktion vom Sender:
1
int main(void) {
2
3
  TWBR = 18;
4
5
6
  while (1)
7
  {
8
9
    for(volatile unsigned long i = 1; i < 30000; i++);
10
11
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
12
    while (!(TWCR & (1<<TWINT)));
13
14
    TWDR = (0x22 << 1);
15
    TWCR = (1<<TWINT)|(1<<TWEN);
16
    while (!(TWCR & (1<<TWINT)));
17
18
    TWDR = 0x99;
19
    TWCR = (1<<TWINT)|(1<<TWEN);
20
    while (!(TWCR & (1<<TWINT)));
21
22
    TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
23
24
  }
25
26
  return 0;
27
}


Main-Funktion vom Empfnger:
1
int main(void) {
2
3
  TWBR = 18;
4
  TWAR  = (0x22 << 1);
5
  TWCR |= (1<<TWEA) | (1<<TWEN);
6
7
8
  while (1)
9
  {
10
      
11
      if(TWSR == 0x60)
12
          //String aufm LCD
13
  }
14
15
  return 0;
16
}

Pull up Widerstnde zu VCC sind dran und beide Controller haben den 
selben Takt. Jeder für sich liefert auf dem Oszi ein wunderbares Bild 
ab. Wenn man sie jedoch zusammenhngt entsteht auf beiden Leitungen eine 
Nullinie. Möglich ist auch dass eins von beiden auf High war.

Wenn man das ACK-Configurationsbit auf 0 setzte sah der Bus wieder 
wunderbar aus aber der Slave aber der Slave empfing noch immer nichts. 
Wenn man dafür auch die Adresse unterschiedlich gesetzt hat trat das 
selbe Phänomen auf. Das Oszibild war wunderbar aber ACK war halt HIGH 
und es wurde kein String ausgegeben.

Wir wissen nicht mehr so richtig weiter. Hoffe ihr könnt uns ein 
bisschen weiterhelfen. Vielen Dank, ben.pu

von Stefan B. (stefan) Benutzerseite


Lesenswert?

µC? Taktrate? Mit was (Toolchain) wie (Optimierung) übersetzt?

> Jeder für sich liefert auf dem Oszi ein wunderbares Bild ab.

Der TWI-Slave darf von sich aus nix abliefern. Nur nach Aufforderung 
durch den TWI-Master!

von ben.pu (Gast)


Lesenswert?

Hallo Stefan,

Stefan B. schrieb:
> µC? Taktrate? Mit was (Toolchain) wie (Optimierung) übersetzt?
>

ATmega8 und Atmega168, Programmierung mit Eclipse und WinAVR Toolchain, 
Optimierung Os

>> Jeder für sich liefert auf dem Oszi ein wunderbares Bild ab.
>
> Der TWI-Slave darf von sich aus nix abliefern. Nur nach Aufforderung
> durch den TWI-Master!

ja das war ein bischen unglücklich ausgedrückt... Ich meinte damit dass 
der Master Code auf beiden Mikrocontrollern gut funktioniert. Also 
einfach nur wenn man beide trennt und jeder für sich den Master Code 
ausführen lässt. Hat nix wirklich zu bedeuten - wollte das nur mal 
sagen...

Bin über jede Meinung erfreut,
Benny

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Atmega8 könnte ich per Software und Hardware testen. Atmega168 nur per 
Software (Simulator).

Ich persönlich wäre bei einem µC-Typ geblieben - bei zwei verschiedenen 
muss man IMHO zu oft die Toolchain umstellen und ein Datenblatt mehr 
wälzen.

Fürs Testen wären komplette Quellcodes für den Slave (ATmega8?) und den 
Master (ATmega168?) sinnvoll. Die Schnippsel oben sind nicht fehlerfrei 
kompilierbar.

Mit

>   for(volatile unsigned long i = 1; i < 30000; i++);

hast du eine Taktraten- und Toolchain-abhängige Zeitschleife drin, die 
ich so nicht implementieren würde. Ich würde hier ein _delay_ms() aus 
der Library verwenden.

Die Frage nach der Taktrate ist noch offen. Nur bei Kenntnis der 
Taktrate kann man abschätzen, ob deine magische Zeile TWBR = 18; 
sinnvoll ist.

Pi*Daumen rät man anhand dieser Zeile dass Master und Slave mit einer 
Taktrate F_CPU um die 5,2 MHz arbeiten müssten, um auf eine SCL-Speed 
von 100 kHz zu kommen; 400 kHz sind schon außerhalb der Spezifikation 
(20,8 MHz).

von ben.pu (Gast)


Lesenswert?

Stefan B. schrieb:
> Atmega8 könnte ich per Software und Hardware testen. Atmega168 nur per
> Software (Simulator).
>
> Ich persönlich wäre bei einem µC-Typ geblieben - bei zwei verschiedenen
> muss man IMHO zu oft die Toolchain umstellen und ein Datenblatt mehr
> wälzen.
>
> Fürs Testen wären komplette Quellcodes für den Slave (ATmega8?) und den
> Master (ATmega168?) sinnvoll. Die Schnippsel oben sind nicht fehlerfrei
> kompilierbar.
>

Zwei gleiche Mikrocontroller stehen leider nicht zur Verfügung. Da ich 
mit Eclipse arbeite kann man zwei Projekte gleichzeitig, mit den 
jeweiligen Einstellungen, bearbeiten. Das Hin- und Herswitchen stellt 
hier kein Problem dar, da sich AVRDude nur das aktive Projekt flasht und 
auch prüft ob die Signaturen übereinstimmen - da machen sich zwei 
unterschiedliche Controller ausgezahlt :-) - und nur das jeweilige 
selektierte File und das dazugehörige Projekt kompilliert werden. Ich 
denk mal die Methode ist ziemlich sicher...

Die Codes werden bei mir fehlerfrei kompilliert. Wo hakts denn bei dir?
Master soll der Atmega8 werden und Atmega168 der Slave.

> Mit
>
>>   for(volatile unsigned long i = 1; i < 30000; i++);
>
> hast du eine Taktraten- und Toolchain-abhängige Zeitschleife drin, die
> ich so nicht implementieren würde. Ich würde hier ein _delay_ms() aus
> der Library verwenden.

Die Länge der Pause ist hier meiner Meinung nach für den Mikrocontroller 
unerheblich. Gewünscht ist dass überhaupt eine Pause ensteht und das 
Oszilloskop genau auf die Startbedingung Triggern kann.

>
> Die Frage nach der Taktrate ist noch offen. Nur bei Kenntnis der
> Taktrate kann man abschätzen, ob deine magische Zeile TWBR = 18;
> sinnvoll ist.
>

Sorry habsch vergessen... 8Mhz

> Pi*Daumen rät man anhand dieser Zeile dass Master und Slave mit einer
> Taktrate F_CPU um die 5,2 MHz arbeiten müssten, um auf eine SCL-Speed
> von 100 kHz zu kommen; 400 kHz sind schon außerhalb der Spezifikation
> (20,8 MHz).

Da hab ich wohl einen Fehler gemacht. Ich bin davon ausgegangen dass die 
Taktfrequenz des TWI ziemlich egal ist, sondern nur gleich sein muss.

Wäre für TWPS=0 und Fcpu=8Mhz und Ftwi=100mhz die Einstellung nach

TWBR = (CPU/SCL - 16) / 2
TWBR = 32

richtiger?

Vielen Dank für die Hilfe,
der Benny.

von Fabian B. (fabs)


Lesenswert?

Was heisst Taktfrequenz muss gleich sein. Da der Slave seinen TWI Takt 
aus der SCL Leitung bezieht, braucht ihr gar nichts im TWBR eingetragen 
zu werden. Der Systemtakt des Slaves muss nur <= 16 * SCL-Takt sein.

Gruß
Fabian

von ben.pu (Gast)


Lesenswert?

Arggghhh Stimmt... Nächste Frage:
Muss die Frequenz 100kHz betragen oder gehen auch andere?

von Fabian B. (fabs)


Lesenswert?

Die Frequenz kann auch 37,48kHz oder 375kHz betragen. Ist im Prinzip 
egal, solange dein Slave mitkommt. Bis 100kHz bewegt man sich laut 
Standard halt im "Standard-Mode" und bis 400kHz dann im Fast-Mode.
Und wenns zu schnell wird kann er ja mit SCL-Clock-Streching auch noch 
bremsen.

Es musste oben natürlich heissen: Systemtakt-Slave >= 16 * SCL-Takt.

Gruß
Fabian

von Peter D. (peda)


Lesenswert?

ben.pu schrieb:
> while (1)
>   {
>
>       if(TWSR == 0x60)
>           //String aufm LCD
>   }

Da hatter recht, daß er SCL auf GND zieht forever.
Das ist nämlich Quatsch.

Du mußt das Interruptflag abtesten und zum Schluß auf 1 setzen:
1
while(1){
2
  uint8_t twcr;
3
  do{
4
    twcr = TWCR;
5
  while( (twcr & 1<<TWINT) == 0 );
6
  // nu mache was
7
  TWCR = twcr;
8
}


Peter

von ben.pu (Gast)


Lesenswert?

Kann ich das so verstehen, dass der Slave nach dem ACK abbricht und 
würde erst weitermachen wenn der Slave den Bus wieder "freigibt"?
Das passiert dann durch das setzen des TWINT?

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.