Forum: Mikrocontroller und Digitale Elektronik Atmega8 hängt in TWI Kommunikation fest (START schlägt fehl)


von Chris K. (dexter86)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich mache gerade meine ersten Gehversuche mit einer Real Time Clock 
(ds1737). Für die Kommunikation benutze ich die TWI Funktionen des 
Atmega8. Der Großteil des Programms ist auch funktionsfähig. Ich kann 
Einstellungen an die RTC übertragen und danach erfolgreich einen Wert 
aus der RTC lesen.

Nach dem lesen des Wertes sende ich ein NACK auf dem TWI und danach ein 
STOP. Versuche ich nun das ganze Prozedere von vorne zu starten, bleibt 
der Controller in der Schleife hängen, in der ich nach dem Senden des 
START Signal auf das setzten von TWINT warte.

(Zeile 108)

Ich bin was Mikrocontroller angeht noch blutiger Anfänger und wundere 
mich eigentlich permanent darüber dass ich bis hierher gekommen bin. 
Aber dieses Problem konnte ich nun seit mehreren Stunden nicht lösen. 
Ich kann mir nicht erklären warum das erneute START Signal nicht 
gesendet wird.

Meine Vermutung ist, dass der BUS aus irgendeinem Grund noch busy ist, 
dürfte er aber nicht sein. Ich habe leider auch kein Oszilloskop um das 
zu überprüfen. Kann es ggf. sein, dass es einen Fehler in meiner 
_twi_send_nack() methode gibt, sodass die RTC nicht aufhört zu senden 
und so das STOP Signal bereits fehlschlägt?

Hat hier jemand eine Idee?

von Spess53 (Gast)


Lesenswert?

Hi

>Ich mache gerade meine ersten Gehversuche mit einer Real Time Clock
>(ds1737).

Und welchen benutzt du wirklich?

MfG Spess

von Chris K. (dexter86)


Lesenswert?

Ehm.. Ups DS1337 heißt das gute Stück...

von Spess53 (Gast)


Lesenswert?

Hi

>  _twi_read(RTC_ADDR);
>  uint8_t secs = _twi_rec();
>  _twi_send_nack();
>  _twi_stop();

sieht etwas ulkig aus. Beim Lesen mehrerer Bytes werden werden bis auf 
das Letzte die Bytes vom Master mit ACK bestätigt. Das letzte Byte wird 
mit einem abschließenden NACK vom Master gelesen. Das Senden eines 
einzelnen NACK funktioniert nicht.

MfG Spess

von Icke ®. (49636b65)


Lesenswert?

Spess53 schrieb:
> Beim Lesen mehrerer Bytes werden werden bis auf
> das Letzte die Bytes vom Master mit ACK bestätigt. Das letzte Byte wird
> mit einem abschließenden NACK vom Master gelesen.

Laut Datenblatt des DS1337 muß das aber so sein.


Christian Kosmowski schrieb:
> Ich habe leider auch kein Oszilloskop

Überprüf mal mit einem Multimeter, ob BEIDE Leitungen vor dem START auf 
H-Pegel sind.

von Spess53 (Gast)


Lesenswert?

Hi

>Laut Datenblatt des DS1337 muß das aber so sein.

Was? Sieh dir doch mal das Datenblatt S.14 an. Das Senden von NACK muss 
aber dem AVR vor dem Lesen des letzten Bytes mitgeteilt werden.

MfG Spess

von Icke ®. (49636b65)


Angehängte Dateien:

Lesenswert?

Nach dem Datenblatt, das ich vom DS1337 habe, muß das letzte gelesene 
Byte mit NACK "bestätigt" werden.

"The DS1337 must receive a “not acknowledge” to end a read."

von Chris K. (dexter86)


Lesenswert?

Habe die beiden Leitungen überprüft. Während der controller sich in der 
Warteschleife tot läuft ist SCL low und SDA high.

von Icke ®. (49636b65)


Lesenswert?

Spess53 schrieb:
> Das Senden von NACK muss
> aber dem AVR vor dem Lesen des letzten Bytes mitgeteilt werden.

Sorry, Mißverständnis meinerseits. Ist klar, der letzte Lesebefehl muß 
OHNE gesetztes TWEA erfolgen, das NACK wird also schon mit übergeben.

von spess53 (Gast)


Lesenswert?

Hi

>Sorry, Mißverständnis meinerseits. Ist klar, der letzte Lesebefehl muß
>OHNE gesetztes TWEA erfolgen, das NACK wird also schon mit übergeben.

Genau das meinte ich.

MfG Spess

von Icke ®. (49636b65)


Lesenswert?

Christian Kosmowski schrieb:
> Während der controller sich in der
> Warteschleife tot läuft ist SCL low und SDA high.

Vermutlich will der DS1337 weiter senden, weil er kein NACK bekommt.

von Chris K. (dexter86)


Lesenswert?

Okay, super. Ich glaube dann habe ich verstanden was das Problem ist. 
Ich lese zuerst das Byte und führe dann die Funktion _twi_send_nack(); 
mit der ich eigentlich nur TWEA auf 0 setze. Ich habe gedacht, er würde 
dann tatsächlich das NACK nochmal "hinterherschicken".

[...]
void _twi_send_nack(){
  TWCR = _BV(TWINT) | _BV(TWEN);
}
[...]
uint8_t secs = _twi_rec();
_twi_send_nack();

tatsächlich, muss aber TWEA VOR dem lesen auf 0 sein und er verschickt 
es dann automatisch nach dem nächsten Lesevorgang. Ist das soweit 
richtig?

Wenn ich das ganze also umdrehe:
_twi_send_nack();
uint8_t secs = _twi_rec();

sollte es klappen.

Klingt zumindest erstmal einleuchtend. Ich werde das nachher mal 
ausprobieren. Vielen Dank schonmal!

von Karl H. (kbuchegg)


Lesenswert?

Chris K. schrieb:

> Wenn ich das ganze also umdrehe:
> _twi_send_nack();
> uint8_t secs = _twi_rec();
>
> sollte es klappen.

Im Sinne der maximalen Verwirrtheit: ja

Tatsächlich solltest du einen Umbau deiner Funktionen ins Auge fassen.
Entweder gibst du der twi_rec Funktion mit, ob sie mit einem ACK oder 
einem NAK weitermachen soll, oder du machst dir 2 getrennte Receive 
Funktionen in denen du die Unterscheidung durchführst. Aber darauf zu 
setzen, dass der Aufrufer das alles schon richtig machen wird - nun, 
heute weißt du das noch. Aber in einem halben Jahr sieht das alles ganz 
anders aus. Es liegt an dir, ob du das heute so gestaltest, dass es in 
Zukunft fehleranfällig ist oder nicht.

so zb sehen die verfügbaren Funktionen bei P.Fleurys Lib aus
1
void i2c_init(void);
2
void i2c_stop(void);
3
unsigned char i2c_start(unsigned char addr);
4
unsigned char i2c_rep_start(unsigned char addr);
5
void i2c_start_wait(unsigned char addr);
6
7
unsigned char i2c_write(unsigned char data);
8
9
unsigned char i2c_readAck(void);
10
unsigned char i2c_readNak(void);

Beachte: es gibt 2 read-Funktionen: readAck und readNak

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.