Forum: Mikrocontroller und Digitale Elektronik I2C Data nicht gesendet


von Stehpan-th67 (Gast)


Lesenswert?

Hallo,
ich Programmiere derzeit auf einem LPC2148.
Ich versuche derzeit I2C in Gang zu bekommen, doch leider funktioniert 
es nicht ganz.
Es läuft alles(Slave adressegesendet+ ACK erhalten). Aber sobald ich 
Daten senden will und in der ISR in I20DAT mien Daten lade undSi-Falg 
lösche, wird SDA auf LOw gezogen und nichts passiert, der Stautscode ist 
dann 0x10(also repeated start?). Auf SCL ist jedoch ein Clock mit 9 
Pulsen zu sehen.

Kann jemand helfen?

Gruß Stephan

von Stehpan-th67 (Gast)


Lesenswert?

Ich frage nochmal, vielleicht sieht es jemand, der ein ähnliches Problem 
hatte.
Es funtkioniert alles, bis ich Daten senden will, die Clockleitung macht 
auch das was sie tun soll, nur Sobald ich Daten senden will, wird SDA 
auf LOW gezogen, während auf SCL 9 Takte zu sehen sind.
Wie schon erwähnt steht im Statuscode dann der falsche Code von 0x10, wo 
eigentlich 0x28 (Daten gesendet+ ACK) stehen müsste oder 0x30 für Daten 
gesendet und NACK erhalten.

Wäre schön wenn mir jemand helfen könnte.

Gruß Stephan

von space (Gast)


Lesenswert?

Moin,

wie sich Dein Beitrag liest, hast Du am Bus ein Speicheroszi
hängen, was sehr hilfreich bei der Fehlerdiagnose ist.
Letztens hatten wir ähnliche Probleme bei einem 8051-Derivat.
Wir haben ein Programmbeispiel von Atmel verwendet, das wir
noch reichlich umstricken mussten.
Hast Du einen Slave am Bus? Wie ist die Adresse? Wird sie
korrekt umgesetzt?
Die Slaves brauchen bei hohen Taktraten Pausen zwischen den
Befehlen. In Basic fällt das kaum auf, aber in Assembler sehr
wohl.
Vielleicht hilft's
Stefan

von Stehpan-th67 (Gast)


Lesenswert?

Die Slaveadresse ist 1001 dann Hardwaremäßig 000.
Wie meinst du korrekt umgesetzt? Also ein ACK bekomm ich.
Ich weiss dass da Pausen benötigt werden(so 10ms), aber wie kann ich die 
ein bauen. Mein Programm springt ja garnicht aus der ISR. Es Wird die 
Startcondition ausgelöst, dann ist der Statuscode 0x08, dann springt das 
Programm in die Behaldlung von 0x08, dann wird die Slaveadresse 
gesendet, dann ist der Satuscode 0x18, dann werden dort die Daten 
gesendet, und ich galube vor dem Daten senden müsste ich warten,oder?
1
void I2C_ISR(void) __irq
2
{  
3
  int temp1 = 0;
4
  temp1 = I20STAT;
5
  
6
  switch(temp1)
7
  {
8
    case 0x08:
9
    {  
10
      I20DAT = slaveaddr; //addr      
11
    }
12
    break;
13
14
    case 0x10:
15
    {
16
      I20DAT = slaveaddr;
17
    }
18
    break;
19
20
    case 0x18:
21
    {    
22
      I20DAT = 0xAA;//hier nur Beispielwert
23
    }
24
    break;
25
26
    case 0x20:
27
    {
28
      i2c_stop();  
29
    }
30
    break;
31
32
    case 0x28:
33
    {
34
      I20DAT = 0xAA;//hier nur Beispielwer
35
    }
36
    break;
37
38
    case 0x30:
39
    {
40
      i2c_stop();    
41
    }
42
    break;
43
         }
44
  I20CONCLR = (1 << SIC); // | (1 << STA);
45
  VICVectAddr = 0;
46
  
47
    
48
}

von space (Gast)


Lesenswert?

Moin,

zuerst wird die Adresse des Slaves gesendet:
das erste gesendete Bit ist das MSB der Adresse.
Die Adresse ist 7 Bit lang und das 8. Bit definiert,
ob gelesen (1) oder gelesen (0) werden soll.
Beim Schreiben werden also nur gerade Werte übertragen.
Das lässt sich sehr gut auf dem Oszi ablesen.
Die Adresse 00h ist ein "General Call", also ein Befehl
an ALLE Slaves!
Noch zwei Tipps:
1. Zum Testen der Routine habe ich diese einmal durchlaufen
lassen und das Programm in einer Endlosschleife enden lassen.
Das Oszi habe ich auf "Single Shot" gestellt und bei richtiger
Einstellung der Zeitbasis kann man Takt und Daten sehr schön
sehen. PS: Ich habe ein Fluke 196.
2. Zum Testen, welche "Cases" durchlaufen werden habe ich
LEDs gesetzt.
Viel Erfolg
Stefan

PS: Da sich nicht jeder mit Deinem Controller auskennt wäre
es sinnvoll vor den "case"-Anweisungen diese mit aussagekräftigen
Kommentaren zu versehen. Das mag Dir sinnlos erscheinen, aber es
erhöht die Lesbarkeit Deines Programms. Das wirst Du aber erst
in ein paar Wochen feststellen, wenn Du diese Routine noch mal
nachvollziehen willst und erst wieder Handbücher wälzen darfst.

von Stehpan-th67 (Gast)


Lesenswert?

So ich habe mal die cases kommentiert. Danke für den Tip, auf sowas wie 
kommentieren kommt man in der Hitze des Gefechts nicht...
Ich debugge des Ganze mit Hitop5, ich sehe also die cases sehr schön.
DAs Problem ist nur, das folgerder Fall eintritt, der Meiner Meinung 
nach garnicht möglich sein sollte: Beim Senden der Daten wird SDA auf 
LOW gezogen und es werden ja 9 TAkte erzeugt, es werden also nur Nullen 
übertregen, obwohl im Datenregister ein Wert != 0 steht. Beim löschen 
des SI(Interrupt) Flags wird scheinbar ein repeated Start ausgefürt, 
jedenfalls sagt das das Statusregister und auch auf dem Oszi ist eine 
Startcondition zu sehen.

void I2C_ISR(void) __irq
{
  int temp1 = 0;
  temp1 = I20STAT;

  switch(temp1)
  {
    case 0x08:  //Startcondition erzeugt
    {
      I20DAT = slaveaddr; //addr
    }
    break;

    case 0x10:  //Repeated Startcondition erzeugt

    {
      I20DAT = slaveaddr;
    }
    break;

    case 0x18:    //Slaveadresse+Writebit gesendet, ACK erhalten
    {
      I20DAT = 0xAA;//hier nur Beispielwert
    }
    break;

    case 0x20:   ////Slaveadresse+Writebit gesendet, NACK erhalten
    {
      i2c_stop();
    }
    break;

    case 0x28:   //DAten gesendet ACk erhalten
    {
      I20DAT = 0xAA;//hier nur Beispielwer
    }
    break;

    case 0x30:    //DAten gesendet NACk erhalten
    {
      i2c_stop();
    }
    break;
         }
  I20CONCLR = (1 << SIC); // | (1 << STA);
  VICVectAddr = 0;


}

von space (Gast)


Angehängte Dateien:

Lesenswert?

Tach,

dann überprüfe, ob I20DAT und slaveaddr korrekt initialisiert
und zugeordnet worden sind. Es wäre auch zu prüfen, ob die
Variablen und Register nicht versehendlich überschrieben
werden. Gib in der Interruptroutine, zu Tests, die Adresse
fest vor.
Mit Kommentaren ist die Routine wirklich besser lesbar :o)
Viel Erfolg
Stefan

PS: Im Anhang ist das Oszillogramm eines I²C-Schreibbefehls.
Das erste Paket ist die Adresse, danach kommen zwei Pakete
mit Daten.

von (prx) A. K. (prx)


Lesenswert?

Die Bits in ICONSET setzen sich nicht alle von selbst zurück, 
beispielsweise nicht STA. In den Tabellen 148+ des Manuals ist 
beschrieben, was im jeweiligen Zustand von der Software erwartet wird. 
Dazu gehört auch, diese Bits entsprechend zu setzen oder zu löschen.

Beispielcode findet man in der Application Note AN10369 von NXP.

PS: Seltsamerweise war vor ein paar Tagen ein anderer(?) Anwender mit 
gleichem Controller, gleichem Compiler und ähnlichem Problem unterwegs. 
Ist das grad ansteckend?

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.