Forum: Mikrocontroller und Digitale Elektronik AVR I2C Slave und Sleep


von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Hallo zusammen,

ich hab mit meinem ATmega128P ab und zu folgendes Problem: Das Ding 
arbeitet als I2C Slave, und steuert ein LCD an. Wenn nix zu tun ist, 
schicke ich das teil in den "extended standby", da arbeitet TWI slarw 
match weiter, und der AVR sollte in 6 Takten wieder voll einsatzfähig 
sein. Taktquelle ist ein externer Quarz mit 16 MHz.

Nun bekomme ich am Master (ein zweiter AVR) ab und zu (alle paar 
Minuten) ein NAK auf das erste gesendete Datenbyte. Sieht für mich so 
aus, als würde der Slave nicht schnell genug aufwachen, um das Datenbyte 
mit ACK zu quittieren. Das SLA+RW wird aber erfolgreich geACKt (aber das 
macht die Hardware, nicht die ISR).

Sobald ich den Sleep-Mode deaktiviere, funktioniert alles problemlos.

am Slave laufen nur noch zwei sehr einfache und kurze Timer2-ISRs.

hat da jemand eine Erklärung dafür? und was man dagegen tun kann?

Ausmessen mit Oszi ist eher mühsam, wenn es nur alle paar tausend 
I2C-Übertragungen zum Fehler kommt...

von Stefan (Gast)


Lesenswert?

Eine niedrigere Bitrate könnte helfen. Zumindest für das erste Byte nach 
der Slave-Adresse.

von Michael L. (nightflyer88)


Lesenswert?

Ich habe auch schon ein I2C Slave mit einem Attiny85 programmiert. Der 
Tiny hat jedoch ein USI Interface, und man muss ziemlich viel per 
Software machen, damit der I2C funktioniert.

Ich hatte damals auch Probleme, dass die ISR mit der Datenverarbeitung 
des I2C zuviel Zeit brauchte, da wahren nur etwa 4 oder 5 Takte 
Spielraum. Je nach dem, wenn der uC noch andere Sachen erledigen sollte, 
und somit die ISR des I2C verzögerte, hatte ich genau das gleiche 
Problem (der Slave antwortetet mit NAK, weil er nicht nachkam).

Ich hatte dann die ISR soweit optimiert, so das ich minimum 20 Takte 
Spielraum hatte. Nun hat der Tiny auch genügend Zeit um in die ISR zu 
springen. Das Problem ist nie wieder aufgetaucht.

Ich denke, bei dir ist das Problem ein ähnliches. Ich kenne zwar das TWI 
interface des Atmega128 nicht.

von Peter D. (peda)


Lesenswert?

Michael L. schrieb:
> Ich hatte damals auch Probleme, dass die ISR mit der Datenverarbeitung
> des I2C zuviel Zeit brauchte

I2C ist völlig unkritisch, die I2C-Hardware hält SCL solange auf low, 
bis der Interrupt abgearbeitet ist.
Man darf nur das Interruptflag nicht zu früh löschen, sondern erst am 
Ende des Interrupts.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Danke euch. nachdem ich noch einige lästige Probleme am Master nun 
hoffentlich gelöst habe (richtige Behandlung von Bus Error, manueller 
I2C-Reset, ... der Beispielcode von ATmel ist an der Stelle manchmal 
"fragwürdig") ist das problem immer noch da.

Momentan hab ich es so gelöst, dass seitens des masters bei einem NAK 
auf Daten ähnlich wie beim NAK auf sla+rw einfach nochmal versucht wird. 
Scheint bisher stabil zu laufen.

Allerdings hab ich immer noch keine Erklärung woher das Problem kommt.

von Peter D. (peda)


Lesenswert?

Michael Reinelt schrieb:
> Das SLA+RW wird aber erfolgreich geACKt (aber das
> macht die Hardware, nicht die ISR).

Das ACK macht immer die Hardware.
Du müßtest mal debuggen, welchen Status Code der Slave hatte vor dem 
NACK.
Bei NACK müßte es ja 0x88 sein.
Und Du müßtest TWEA auf 0 gesetzt haben.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Peter Dannegger schrieb:
> Michael Reinelt schrieb:
>> Das SLA+RW wird aber erfolgreich geACKt (aber das
>> macht die Hardware, nicht die ISR).
>
> Das ACK macht immer die Hardware.
Ja schon, ich meinte auf das erste ACK auf die Adressierung habe ich 
wenig Einfluss, für alle weiteren Datenbytes kann ich's mir aussuchen ob 
ACK oder NAK.

> Du müßtest mal debuggen, welchen Status Code der Slave hatte vor dem
> NACK.
Ja, wenn das so einfach wäre :-)

> Bei NACK müßte es ja 0x88 sein.
eigentlich Nachher, nicht vorher. (das "vorher" und "nachher" bei der 
TWI-StateMachine bringt mich auch immer durcheinander). In die 
State-Machine kommt er ja immer erst nach dem Quittieren.

> Und Du müßtest TWEA auf 0 gesetzt haben.
Nein, eigentlich nicht.

Hier mal der relevante Ausschnitt aus der ISR:
1
    case 0x60:      // own SLA+W has been received; ACK has been returned
2
  I2C_Busy = 1;    // transmission started
3
  I2C_RxIndex = 0;  // reset packet index
4
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);  // send ACK
5
  break;
6
7
    case 0x80:      // previously addressed with own SLA+W; data has been received; ACK has been returned
8
    case 0x88:      // previously addressed with own SLA+W; data has been received; NAK has been returned
9
  index = I2C_RxIndex;  // local cache
10
  if (index < I2C_PACKETSIZE) {
11
      I2C_RxBuffer[index++] = TWDR;  // store received data
12
      I2C_RxIndex = index;  // write back cache
13
  }
14
  if (index < I2C_PACKETSIZE - 1) {
15
      TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);  // send ACK
16
  } else {
17
      TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);  // last byte, send NAK
18
  }
19
  break;

(I2C_PACKETSIZE ist eine Konstante (#define) mit Wert 64, also groß 
genug)

Da der Slave auf die Adressierung noch mit ACK geantwortet hat, müsste 
er mit 0x60 in die ISR gekommen sein. Dort sag ich ihm, er soll das 
nächste Byte mit ACK quittieren.

Dann kommt das erste Datenbyte, dieses wird aber offensichtlich NICHT 
mit ACK quittiert. Also müsste 0x88 im TWSR stehen.

Es gibt keinen Code-Pfad, der TWEA nicht auf 1 setzt, nach 
erfolgreicher Adressierung.

Die einzige Möglichkeit, die ich sehe, ist dass das TWI in Hardware die 
Adressierung quittiert, danach versucht die ISR aufzurufen, wo TWEA auf 
1 gesetzt würde, aufgrund des sleeps das aber zu langsam / zu spät 
erfolgt.

Da der AVR aber angeblich in 6 Takten aufwacht, und mit 16 MHz läuft, 
müsste er ja fast unendlich zeit dafür haben...

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.