Forum: Mikrocontroller und Digitale Elektronik AVR I2C Master Receiver kein ACK


von Raph (Gast)


Lesenswert?

Hallo zusammen

Ich versuche verzweifelt mit einem AVR im TWI MasterReceiver Mode Daten 
von einem Slave abzuholen.
Mit einem LA sehe ich, dass die Adresse + R an den Slave gesendet wird, 
dieser mit einem ACK Antwortet, die ersten 8 Datenbit ausgibt und 
daaaaannn, bestätigt mein lieber AVR den Empfang mit einem NACK womit 
der Slave natürlich abbricht zu senden.
Ich bin kurz davor durchzudrehen! Bekomme es einfach nicht hin, dass er 
mit ACK bestätigt.
Kann mir jemand helfen?

1
case 10: // Daten abholen
2
  chrPos++;      // Anzahl empfangener Daten erhöhen
3
  if (chrPos < chrLen)
4
  {  // Mehr Daten zum empfangen --> ACK
5
    TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
6
    chrState = 10;  // In diesem case bleiben
7
  }
8
  else
9
  {  // Keine weiteren Daten empfangen --> NACK
10
    TWCR = (1 << TWINT) | (1 << TWEN);
11
    chrState++;
12
  }
13
  // Auf Daten warten
14
  while (!(TWCR & (1 << TWINT))) { FALLOUT; }
15
  RESFALLOUT;
16
  *ptchrData++ = TWDR;  // Daten in Array ablegen, Adresse erhöhen
17
  break;

Viele Grüsse Raph

von Raph (Gast)


Lesenswert?

Hey Gemeinde

Bin ich denn er einzige der andauernd Probleme mit diesem TWI Modul im 
AVR hat?
Hat niemand von euch schon einmal mehrere Daten von einem I2C Slave 
abgeholt?

von Tim (Gast)


Lesenswert?

>Bin ich denn er einzige der andauernd Probleme mit diesem TWI Modul im
>AVR hat?

Sicher nicht.

>Hat niemand von euch schon einmal mehrere Daten von einem I2C Slave
>abgeholt?

Denke mal das du dir das selbst beantworten kannst.

Vielleicht hättest du die komplette .c mal anhängen sollen.
Oder die PDF zu ende lesen sollen....

Status Code 0x10 alleine hilft nicht, da der nur 1x kommt:
Aus dem pdf: 'A repeated START condition has been transmitted'
Du braucht auch noch 0x50 und 0x58.

Ausserdem denke ich mal das dem "case 10:" noch ein 0x fehlt....

von Raph (Gast)


Lesenswert?

Hallo Tim

Erstmal danke für die Antwort.

Am Anhang findes du das komplette .c-File. Die Funktion "I2C_Task()" 
wird zyklisch aufgerufen.
Ich verwende überigens ein ATMEGA88.

>Du braucht auch noch 0x50 und 0x58

0x10 = TWSTO: TWI STOP Condition Bit
0x50 = TWI Enable Acknowledge Bit & TWSTO: TWI STOP Condition Bit
0x58 = zusätzlich noch TWI Write Collision Flag?

Falls du die 0x50 und 0x58 von "Figure 21-14" hast, muss ich dir leider 
sagen, dass dies der Code im TWSR ist, welches nur gelesen werden kann.
Die ganze Steuerung findet ja mit dem TWCR statt und da habe ich TWEA 
gesetzt. Ich muss allerdings gestehen, dass ich nicht ganz verstanden 
habe was Atmel bei den 3 Bedingungen meint. Meiner Ansicht nach, sind 
das alles Dinge die mich nicht betreffen da ich im MasterReceiver Mode 
arbeite und nicht im Slave:

>The TWEA bit controls the generation of the acknowledge pulse.
>If the TWEA bit is written to one, the ACK pulse is generated on the TWI bus
>if the following conditions are met:
>1. The device’s own slave address has been received.
>2. A general call has been received, while the TWGCE bit in the TWAR is set.
>3. A data byte has been received in Master Receiver or Slave Receiver mode.
>By writing the TWEA bit to zero, the device can be virtually
>disconnected from the 2-wire Serial
>Bus temporarily. Address recognition can then be
>resumed by writing the TWEA bit to one again.

>Ausserdem denke ich mal das dem "case 10:" noch ein 0x fehlt....

Das ist korrekt so, ich habe die cases Dezimal nummeriert

Grüsse Raph

von Raph (Gast)


Angehängte Dateien:

Lesenswert?

Hier kommt noch der Anhang

von Raph (Gast)


Lesenswert?

Hallo zusammen

Jetzt geht es.
Ich vermute, dass der Controller zu lange gewartet hat, bis er die Daten 
abgeholt hat. Weil dann das TWDR noch belegt war, wurde ein NACK 
zurückgegeben. Aber wie gesagt, ist nur eine Vermutung.

Grüsse Raph

von Tim (Gast)


Lesenswert?

Ach so.... du verwendest
1
switch (chrState)
und Passt den wert von chrState entsprechend an.
Das war leider im 1. Post nicht ersichtlich.

Normalerweise bastelt man eine Interrupt rutiene die
vom TWI aufgerufen wird. Selbige entscheidet dann anhand
des Statuscodes aus TWSR was sie machen soll und
schreibt das jeweils gewollte in TWCR.
Man kann sich so eine schöne Ablaufsteuerung zusammenbauen,
da das TWI für jede mögliche Situation einen eigenen
Statuscode hat.
Deswegen der Hinweiss auf 0x.

In deinem Fall müstest du "nur" die Status Codes der Tabellen
21-2, 21-3 und 21-6 bearbeiten.
ggf ist noch ein Timeout sinnvoll.

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.