Atmega8 hängt in TWI Kommunikation fest (START schlägt fehl)

OP #3060266
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?
Angehängte Dateien:
Gast #3060409
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
#3060463
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.
Gast #3060481
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
Gast #3060786
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
OP #3060937
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!
#3060956
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.