Forum: Mikrocontroller und Digitale Elektronik Acknowkledge geht nicht bei I2C und ATmega16


von Daniel (Gast)


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;

von Jörg X. (Gast)


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.

von Daniel (Gast)


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

von Jörg X. (Gast)


Lesenswert?

> es funktioniert.
sehr schön :)
Man muss sich nur ein (paar) Mal das Datasheet durchlesen ... ;)

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.