Forum: Mikrocontroller und Digitale Elektronik I2C Implementierungsproblem


von Tilo (Gast)


Angehängte Dateien:

Lesenswert?

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

von Tilo (Gast)


Angehängte Dateien:

Lesenswert?

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

von Falk (Gast)


Lesenswert?

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

von Bernhard S. (bernhard)


Lesenswert?

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
Noch kein Account? Hier anmelden.