Guten morgen. Ich will einen Aduc70xx mit ARM Core als I2C Master verwenden, um ein Poti, DS 1803, anzusteuern. Ich habe die I2C Spzeifikation von Phillips gelesen und im Handbuch zum Aduc das I2C Kapitel mehrmals gelesen. Ich habe mir auch den Beispielcode angesehen. Mein Problem ist, dass ich die I2C Spezifikation im Handbuch nicht wiedererkenne. Wenn ein Master auf einen Slave schreiben will, läuft folgendes auf dem Bus ab: 1. Master sendet START 2. Master sendet 7bit SlaveAdresse + letzte Bit 0 3. Slave sendet ACK 4. Master sendet Command Byte 5. Slave sendet ACK 6. Master sendet Daten Byte 7. Slave sendet ACK 8. Master sendet STOP Auf dem uC habe ich im Master-Mode folgende Register: I2C1MSTA (R): Statusregister. Bits werden gesetzt, wenn kein ACK empfangen wurde, Sende-Fifo leer etc. I2C1MRX (R): Empfangsregister I2C1MTX (W): Senderegister I2C1ADR (R/W): Hier ist mit Sinn noch nicht 100% klar, desshalb aus dem Handbuch: I2CxADR are master address byte registers. The I2CxADR value is the device address that the master wants to communicate with. It automatically transmits at the start of a master transfer sequence if there is no valid data in the I2CxMTX register when the master enable bit is set. I2C1CFG: Konfiguration des I2C-Bus. Mit diesem Register wird Master Clock, Master Mode und IRQs konfiguriert. I2C1DIV (R/W): Taktrate des Bus I2C1CNT (R/W): Wofür ist das gut= Wenn mehre Bytes empfangen werden sollen? I2CxCCNT are 8-bit start/stop generation counters. They hold off SDA low for start and stop conditions. I2C1FSTA (R): Status des Tx-Fifo Jetzt zu meinen Problemen. Ich will das Poti ds 1803 Einstellen. Laut Handbuch müssen hierfür 3 Bytes übertragen werden: Slave Adresse, Command Byte, Data Byte Zum Initialisieren setze ich folgende Register GP1CON |= 0x2200; // Aktiviere I2C Bus Nr. 2 I2C1DIV = 0xCFCF; // normal mode 100kHz I2C1CFG = 0x82; // Aktiviere Clock und Master Mode Wie übertrage ich die eigentlichen Daten? Was passiert, wenn ich ein Byte in das Senderegister schreibe? Wird dann autoamtisch eine START-Condition gesendet, auf die dann mein Byte folgt? Woher weiß der Controller, wann die STOP-Condition gesendet werden soll? So etwas wird im Handbuch nirgens erwähnt. Ich hätte die Daten so übertragen: Schreibe Slave-Adresse in I2C1ADR; Warte bis Sende-Fifo Leer Überprüfe ob ACK gesendet wurde Sende Command Byte Warte bis Sende-Fifo Leer Überprüfe ob ACK gesendet wurde Sende Data Byte Warte bis Sende-Fifo Leer Überprüfe ob ACK gesendet wurde ?? Setze STOP-Condition Mit dieser Funktion versuche ich zu senden: int SendI2C(char SlaveAddress, char Command, char Data) { //SlaveAddress ^= 0x01; // Beim Schreiben ist das letzte Bit der Adresse 0 I2C1ADR = SlaveAddress; // Sende Adresse des Slave zu Fifo I2C1MTX = Command; // Sende Befehl //I2C1CNT = 3; // Anzahl der Bytes der Übertragung // Kein ACK angekommen oder Arbitration Loss char status = I2C1MSTA; if ((status & 0x08)!=0) WritelnUart ("Kein ACK"); if ((status & 0x10)!=0) WritelnUart ("Arbitration Loss"); WritelnUart("XX"); I2C1MTX = Data; status = I2C1MSTA; if ((status & 0x08)!=0) WritelnUart ("Kein ACK"); if ((status & 0x10)!=0) WritelnUart ("Arbitration Loss"); return 0; } Als Ausgabe erhalte ich: XX Arbitration Loss Warum erhalte ich den Fehler? Dummerweise erhalte ich die die selbe Ausgabe, wenn ich eine ungültige Slave Adresse verwende. Leider habe ich keine Ahnung, wo ich mit der Fehlersuche anfangen soll .... Gruß, Tilo
Nach über 5 Stunden Suche bin ich leider immer noch nicht weiter. Ich habe im Forum Beispielcode von Mike Schaub für den LPC2194 gefunden und ich denke ich habe den Code soweit verstanden. Ich habe daraus und dem oben angehängten Beispielcode versucht, passende I2C Funktionen zu schreiben. Ich habe die Funktionen angehängt. Diesen Code führe ich aus: StartI2C(0x50); // Digitales Stereopoti, Adresse 0101000 + 0 char data[2] = {0xA9,0x7F}; // A9==Schreibe beide Potis 7F=Wert WriteI2C(data, 2); StopI2C(); StartI2C(0x51); char data2[2]; ReadI2C(data2, 2); // Lese Poti-Einstellung StopI2C(); IntToUart(data2[0]); IntToUart(data2[1]); Das ganze funktioniert hinten und vorne nicht. 1. Problem: Es werden keinerlei Interrupt ausgelöst. Mein Interrupt-Code ist OK. Interrupts von Timern oder Uart werden abgearbeitet. Ich aktiviere dort den Interrupt genauso. 2. Problem: Auch wenn nichts angeschlossen ist, erhalte ich keinen Fehler, dass kein ACK empfangen wurde. 3. Problem WaitSI() wird immer mit Timeout abgebrochen. 4. Problem: Ich habe den Eindruck, es laufen kleinerlei Daten über den Bus. Mein Oszi zeigt die ganze Zeit High-Pegel(3,3V) an ohne zu flackern. Ziehe ich den 10k Pullup Widerstand ab, liegt der Pegel noch bei 2,3V. Leider werden die Register für den I2C bei Analog anderst als beim LPC gesetzt. Ich habe im Netz nur Beispiele für die aduc8xx Familie gefunden, die völlig anderst zu sein scheint. Sieht einer von euch, was an meinem Code falsch ist? Vielen Dank und noch ein schönes Wochenende, Tilo
Wenn der I2C überhaupt nicht zuckt, dann ist wahrscheinlich die Initialisierung des Controllers nicht in Ordung. Wenigstens die Start Condition un das Adressbyte müssen zu sehen sein. MfG Falk
Hallo Tilo, hier findest Du einen ganz einfachen SLAVE: Beitrag "TWI / I2C einf. MASTER SLAVE Beispiel(Assembler) ATmega8" Eigentlich macht er nichts sinnvolles, aber er antwortet wenigstens korrekt und gibt einen Fehler aus, wenn Ein Bus-Error auftritt. Somit kannst Du Dich ersteinmal in aller Ruhe auf Deine Master-Routinen konzentrieren. Gruß Bernhard
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.