Acknowkledge geht nicht bei I2C und ATmega16

Gast #494733
Lesenswert?
• ▲
▼
Hallo,
ich möchte den RAM(TI: BQ27200) eines LiIonen Akku per I2C auslesen. Das 
Protokoll verlangt bei mehreren auszulesenden Werten ein ACK nach jedem 
gelesenen Wert. Nach dem letzten sendet man KEIN ACK sondern nur die 
STOPP-Bedingung.

Lese ich einen Wert aus, funktioniert es ohne Fehler.

Lese ich zwei Werte aus erhalte ich beim zweiten Wert einen Fehler.
1
void READ_RAM_LiIO(void)
2
{
3
//Startbedingung
4
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);           // Startbedingung
5
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
6

7
//ADDR[6..0]-ADDR.7=0
8
  TWDR = 0xAA;                     // Adresse LiIon Akku und schreiben
9
  TWCR = (1 << TWINT) | (1 << TWEN);                   // senden
10
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
11
//CMD[7..0]
12
  TWDR = 0x00;                   // Pointer auf Adresse 0x00 setzen
13
  TWCR = (1 << TWINT) | (1 << TWEN);                   // senden
14
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
15

16
//Startbedingung
17
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);       // Startbedingung
18
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
19

20
//ADDR[6..0]-ADDR.7=0
21
  TWDR = 0xAB;                     // Adresse LiIon Akku und lesen an Adresse Pointer
22
  TWCR = (1 << TWINT) | (1 << TWEN);                   // senden
23
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
24

25
//Umschalten auf Daten-Empfangen
26
  TWCR = (1 << TWINT) | (1 << TWEN);                   // senden
27
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
28
     putchar(TWDR);                                         // Daten aus Register übernehmen
29

30
     TWCR = (1 << TWINT) | (1 << TWEN)| (1 << TWEA);
31
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
32

33
//Umschalten auf Daten-Empfangen
34
  TWCR = (1 << TWINT) | (1 << TWEN);                   // senden
35
  while(!(TWCR & (1<<TWINT)));                   // warte bis fertig
36
     putchar(TWDR);                                         // Daten aus Register übernehmen
37
 
38
 
39
//Stoppbedingung
40
  TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);  // Stoppbedingungtodo=0;
Gast #494851
Lesenswert?
• ▲
▼
KOrrigier mal BITTE die Kommentare, die stimmen ja für den Lese-teil gar 
nicht.
Und du musst das TWEA-Bit setzen BEVOR du ein Byte liest, also du musst 
vorher wissen, ob der µC weiterlesen soll. Das TWI-Modul sendet immer 
ein ganzes Byte oder eine Start/StopKond.- nie "nur" das ACK.

Ach und die putchar() könntest du mal posten, ob man mit _put_char 
tatsächlich ein Byte liest ? ;) (ok. wenn du die selber geschrieben 
hast..)

Und wenn der Code für den avr-gcc is schau mal in die twidemo.c - liegt 
auf jeden Fall bei WinAVR bei.
Gast #494901
Lesenswert?
• ▲
▼
Danke Jörg,
es funktioniert.

die Funkt. putchar() gibt das gelesene Byte in den Sendepuffer des 
UARTs. Damit lasse ich mir den Inhalt des Register in meinem 
Terminalprogramm am PC anzeigen.

>Das TWI-Modul sendet immer ein ganzes Byte oder eine Start/StopKond.- >nie "nur" 
das ACK.
war mir nicht ganz klar, aber jetzt dank dir
Gruß Daniel

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren