I2C auf atmega328p

Ich versuche, über I2C eine Verbindung zu einem IC herzustellen. Um die I2C-Kommunikation zu initialisieren, verwende ich die folgende Funktion:

void init_i2c(void ) {
 uint8_t   twst;
 TWSR = 0;                         // no prescaler
 TWBR = ((F_CPU/SCL_CLOCK)-16)/2; 
 TWCR = (1<<(TWINT))|(1<<TWSTA )|(1<<TWEN);

 printf("TWCR 0x%x \n",TWCR);
 while(!(TWCR & (1<< TWINT)));
 printf(" Start condition has been transmitted \n");
 if( (TWSR&0xF8) != TW_START){
     printf(" Error  at TWSR start 0x%x\n",TWSR);
 }
 // Setting Address 
 TWDR = 0x70; 
 // cleating TWCR 
 TWCR = (1<<TWINT) |(1<<TWEN);
 while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_SLA_ACK){
     printf(" Error at TWSR   0x%x    SLA_ACK  0x%x \n", TWSR, TW_MT_SLA_ACK);  // here is the problem !!!!!!!!!  TWSR value should be 0x18
}else {
    printf(" tell now is good \n");
}

Die Verkabelung ist gut. Ich habe jeden Pin mit einem Oszilloskop gemessen, einschließlich der Frequenz des SCL [50 kHz]. das TWI-Statusregister ** bei der abschließenden if-Anweisung ist **0x20 statt 0x18

Irgendein Hinweis, was ich hier falsch mache?

Warum verwenden Sie keine Standardfrequenz wie 100 kHz oder 400 kHz. Einige I2C-Geräte haben Zeitüberschreitungen und antworten nicht richtig, wenn die Uhr zu langsam ist.
Weil ich den uC mit 1MHz verwende
@Engine Mit welchem ​​IC versuchst du zu kommunizieren?
Wie benutzt du printf? Befindet sich dieser Code auf dem uC oder einer Desktop-Konsolen-App, um mit dem uC zu sprechen? Ein Atmel-Chip hat keine Standardausgabe, nur für den Fall, dass Sie es nicht wussten.
Nun, 0x20 bedeutet einfach "Daten übertragen, NACK empfangen". Sind Sie sicher, dass Ihr Gerät bereit ist, I2C-Befehle zu empfangen? Und Ihre Geräteadresse ist wirklich korrekt? Vielleicht solltest du sagen, um welches Gerät es sich handelt und/oder deine Oszillogramme posten.
@crowie "stdout" ist eine konzeptionelle Eigenschaft einer Softwareumgebung, keine physische Eigenschaft eines Chips. Ein typisches Setup rund um avr-gcc kann mit einer kleinen Menge Kleber erstellt werden, um stdout an den UART eines ATmega zu senden, und das ist oft der effektivste (oder zumindest übliche) Weg, um herauszufinden, was in einem solchen Gerät vor sich geht Die Debugger-Schnittstelle zum ATmega ist proprietär dunkel.
@ChrisStratton Das ist mir klar, aber Sie müssen es in Ihrem eigenen Code neu definieren. Ich verstehe nicht, wie er das gemacht hat. Vielleicht ist dies ein Teil des Problems, mit dem er konfrontiert ist.
@crowie - Ich sehe auch kein "main()". Gut , dass auf dem Plakat nur der entsprechende Code enthalten ist . Und nein, das könnte nicht relevant sein - das Poster meldet Ergebnisse, so dass sie eindeutig eine Möglichkeit haben, eine Ausgabe zu erhalten, entweder von der printf(), die sie zu senden scheint, oder von einem anderen Mechanismus.
@ChrisStratton Ich frage, wie er printf() verwendet, da die Möglichkeit besteht, dass die Verwendung von UART oder SPI gleichzeitig mit der Verwendung von I2C (TWI) Konflikte oder Fehler verursachen kann. Ich habe davon schon einmal gehört.

Antworten (1)

Status 0x20 ist vollkommen gültig und normal, wenn kein Gerät auf die gesendete Adresse antwortet. Daher wäre als erstes zu prüfen, ob die Adresse gültig ist (kein Off-by-One-Bit-Fehler und einschließlich korrektem R/W-Bit). Wenn der Slave schließlich für die I2C-Kommunikation korrekt konfiguriert ist, nicht ausgesetzt usw.

Was sehen Sie auf der SDA-Linie mit einem Oszilloskop? Ist das letzte Bit (Acknowledge) Low oder High? (Das heißt, sieht AVR kein gültiges ACK oder bestätigt das Slave-Gerät die Adresse nicht?) Verwenden Sie die richtige Slave-Adresse? (d. h. kein Ein-Bit-Aus, da die Adressformate 7-Bit und 8-Bit nicht übereinstimmen)

Dies ist keine Antwort. Ich empfehle dringend, die Tour durchzulesen
Entschuldigung, ich habe ein bisschen darüber nachgedacht, aber 1) die ursprüngliche Frage fragt nach einem Hinweis, was zu tun ist (ich glaube, die doppelte Überprüfung der Adresse und welche Seite das Problem verursacht, ist ziemlich Thema), und 2) man kann die Frage nicht kommentieren mit weniger als 50 Punkte (warum?), also war es entweder dies oder nichts. Ich kann diesen Beitrag auch löschen, aber ich frage mich, ob es die Situation besser macht ... ?
im SDA sehe ich 0x20
Jeder Block ist 9 Bit lang (einschließlich ACK-Bit), was genau meinst du dann mit 0x20? Auf der SDA-Leitung sollte 0b01110000x stehen (Adresse 0x70 gesendet + ACK-Bit zurück).
Noch ein Hinweis: Sie sprechen das Slave-Gerät im Schreibmodus an. Ist es richtig? Ist es zulässig, Daten in das Gerät zu schreiben?
@CHendrix: Ich habe meinen Beitrag so umformuliert, dass er antwortähnlicher ist, jetzt besser? Ich würde gerne die ursprüngliche Frage kommentieren, aber man kann nicht ohne Punkte.