STM32F10x : Fehler bei I2C

OP #3623024
Lesenswert?

Hallo zusammen,
ich habe ein Problem mit dem I2C eines STM32F103 in Verbindung mit einem 
EEPROM 24C02. Die I2C-Routinen habe ich nach der Application Note AN2824 
implementiert. Das merkwürdige Verhalten zeigt sich während der Laufzeit 
der Funktion "I2C_Receivebuffer".

Will ich den EEPROM komplett auslesen mit:
1
uint8_t status;
2
uint8_t buffer[EEPROM_SIZE_BYTES];
3

4
status =  eeprom_read_block(buffer,0,EEPROM_SIZE_BYTES);
was die folgende Funktion aufruft:
1
/* Viele Bytes aus EEPROM auslesen                                            */
2
/* Nur getesten fuer EEPROMS vom Typ 24C02, bei groesseren muss die           */
3
/* Speicheradresse in die I2C-Adresse eingerechnet werden                     */
4
/* size = 0 ist immer erfolgreich und fuehrt keine Busoperation aus           */
5
uint_fast8_t eeprom_read_block(uint8_t *buffer,uint8_t addr,uint8_t size) {
6
  uint8_t status;
7

8
  if(size==0) return ee_ok;
9

10
  // Auf gueltige Adresse pruefen
11
  if((addr+size)>EEPROM_SIZE_BYTES) {
12
    return ee_invalidAddress<<4;
13
  }
14
  if((addr)>EEPROM_SIZE_BYTES) {
15
    return ee_invalidAddress<<4;
16
  }
17

18

19
  // Kommando ohne Stopbit senden
20
  status = I2C_Sendbuffer(EEPROM_I2C_DEVICE,EEPROM_I2C_ADDRESS,&addr,1,noStop);
21
  if (status!=0)
22
    goto error;
23

24
  status = I2C_Receivebuffer(EEPROM_I2C_DEVICE,EEPROM_I2C_ADDRESS,buffer,size);
25
  if (status!=0)
26
    goto error;
27

28

29
  error:
30
  I2C_reset(EEPROM_I2C_DEVICE); // STOP wuerde meist auch reichen
31
  return status;
32
}
Leider schlägt die Leseoperation fehl, vermutlich weil der STM32 den 
Empfang des zweiten Bytes mit NACK beantwortet. So sieht der Verkehr auf 
dem I2C aus:
1
sA0a00a
2
sA1a0AnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnppFFnp
und so sollte er aussehen (gleiches EEPROM vom AVR angesprochen):
1
sA0a00a
2
sA1a0Aa03a04a32aFFa3Ca05a00a00a00aD0a07a01a0FaC0a01aB9a1Aa12a13a14a15a16a17a18a19a1Aa1Ba1Ca1Da1Ea1Fa20a21a22a23a24a25a26a27a28a29a2Aa2Ba2Ca2Da2Ea2Fa30a31a32a33a34a35a36a37a38a39a3Aa3Ba3Ca3Da3Ea3Fa40a41a42a43a44a45a46a47a48a49a4Aa4Ba4Ca4Da4Ea4Fa50a51a52a53a54a55a56a57a58a59a5Aa5Ba5Ca5Da5Ea5Fa60a61a62a63a64a65a66a67a68a69a6Aa6Ba6Ca6Da6Ea6Fa70a71a72a73a74a75a76a77a78a79a7Aa7Ba7Ca7Da7Ea7Fn
(Wie man sieht, befinden sich im hinteren Teil des EEPROMs nur 
Test-Muster, die einen guten Wiedererkennungswert auf dem Bus haben.)

Andere Daten werden von der Funktion "I2C_Receivebuffer" korrekt 
empfangen (und mit einem Ack belegt), z.B. hier die Kommunikation mit 
einem TMC222:
1
24640: sC0aFCa
2
24640: sC1aE0aD7a96aD7a96a00aF8aFFnp
3
24641: sC0aFCa
4
24641: sC1aE0aD7a96aD7a96a00aF8aFFnp
der das gleiche Muster aufweist (Gesendet I2C-Adresse + 1 Byte, Anwort 
"lange" Bytefolge.

Den Bustakt habe ich testweise schon auf 100 kHz gesenkt; mit dem AVR 
läuft aber auch alles bei 250 kHz noch korrekt.

Und jetzt stehe ich da, wie der Ochse vom Berg.

Hat jemand einen Ansatzpunkt?

Viele Grüße
W.T.
Angehängte Dateien:
OP #3623227
Lesenswert?

Es ist zum verzweifeln. Das geht:
1
/* Kommando an TMC222 senden und Antwort lesen                                          */
2
/* Der Aufrufer muss einen passenden Puffer zur Verfuegung stellen
3
 * buffer[0]        : Kommando mit Sendeaufforderung
4
 * buffer[1 - ende] : Empfangspuffer
5
 * */
6
uint_fast8_t
7
tmc222_SendCommandAndRead(uint8_t i2c_addr,uint8_t *buffer,uint8_t bufsize)
8
{
9
  uint_fast8_t status;
10

11
  // Kommando ohne Stopbit senden
12
  status = I2C_Sendbuffer(TMC222_I2C_DEVICE,i2c_addr,buffer,1,noStop);
13
  if (status!=0)
14
    goto error;
15
  buffer++;
16

17
  status = I2C_Receivebuffer(TMC222_I2C_DEVICE,i2c_addr,buffer,bufsize-1);
18
  if (status!=0)
19
    goto error;
20

21
  return status;
22

23
  error:
24
  I2C_reset(TMC222_I2C_DEVICE);
25
  return status;
26
}
und liefert:
1
19876: sC0aFCa
2
19876: sC1aE0a00a00a00a00a00aF8aFFnp
Und das funktioniert nicht:
1
/* Viele Bytes aus EEPROM auslesen                                            */
2
/* Nur getesten fuer EEPROMS vom Typ 24C02, bei groesseren muss die           */
3
/* Speicheradresse in die I2C-Adresse eingerechnet werden                     */
4
/* size = 0 ist immer erfolgreich und fuehrt keine Busoperation aus           */
5
uint_fast8_t eeprom_read_block(uint8_t *buffer,uint8_t addr,uint8_t size) {
6
  uint_fast8_t status;
7

8
  if(size==0) return ee_ok;
9

10
  // Auf gueltige Adresse pruefen
11
  if((addr+size)>EEPROM_SIZE_BYTES) {
12
    return ee_invalidAddress<<4;
13
  }
14
  if((addr)>EEPROM_SIZE_BYTES) {
15
    return ee_invalidAddress<<4;
16
  }
17

18

19
  // Kommando ohne Stopbit senden
20
  status = I2C_Sendbuffer(EEPROM_I2C_DEVICE,EEPROM_I2C_ADDRESS,&addr,1,noStop);
21
  if (status!=0)
22
    goto error;
23

24
  status = I2C_Receivebuffer(EEPROM_I2C_DEVICE,EEPROM_I2C_ADDRESS,buffer,size);
25
  if (status!=0)
26
    goto error;
27

28

29
  error:
30
  I2C_reset(EEPROM_I2C_DEVICE); // STOP wuerde meist auch reichen
31
  return status;
32
}
denn es liefert:
1
28407: sA0a01a
2
28408: sA1aAAnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnFFnpFFnp
Und es ist definiert:
1
  #define TMC222_I2C_DEVICE I2C1
2
  #define EEPROM_I2C_DEVICE I2C1

Beide Funktionen sind:
 Start ->Addr->Byte0 -> Start -> Addr+1 -> Byte1 ....
nur die eine Funktion quittiert Byte1 mit ACK und die andere mit NACK. 
Absolut reproduzierbar.
#3623325
Lesenswert?

Hallo, kannst du mir bitte erklären, warum du die EEPROM_I2C_ADDRESSE 
nicht um eins nach links shiften musst?
1
I2C_Sendbuffer(EEPROM_I2C_DEVICE,EEPROM_I2C_ADDRESS,&addr,1,noStop);

Die 7 MSB Bits stellen die Addresse dar und das LSB READ/WRITE,
wenn ich das richtig verstanden habe?!

Auch in der Funktionn Sendbuffer wird nicht mehr geshiftet, bin ich auf 
dem falschen Dampfer? :D
1
/* Send slave address */
2
/* Reset the address bit0 for write*/
3
slaveaddr &= ~1U;
4
I2Cx->DR = slaveaddr;

Gruß Julian
OP #3623331
Lesenswert?

Julian S. schrieb:
> Hallo, kannst du mir bitte erklären, warum du die EEPROM_I2C_ADDRESSE
> nicht um eins nach links shiften musst?

Ganz einfach: Sie ist schon im Define linksbündig. Da man 
nicht-linksbündige Version nirgendwo gebrauchen kann, bietet sich das 
an. Aber laß uns solche Sachen in Deinem Thread diskutieren - da paßt 
das besser hinein. Hier in diesem geht es um die geschlossene 
Problemstellung "Kein ACK beim EEPROM lesen".
OP #3623368
Lesenswert?

Wahrscheinlich habe ich es gefunden: Nach der Initialisierung schlägt 
das erste Lesem immer fehl, wenn mehr als ein Byte gelesen wird. Der 
Grund ist mir noch schleierhaft.

Schlägt das Lesen fehl, wird ein Bus-Reset gemacht (freitakten) und der 
I2C neu initialisiert.

Damit ist jedes Lesen vom EEPROM das erste Mal nach der Initialisierung.

Mache ich ein Dummy-Lesen eines einzelnen Bytes vor dem Lesen eines 
Blocks funktioniert alles.

Danke für's Lesen!

@Julian: Ich mache das jetzt wieder schön, dann kannst Du gern meine 
I2C-Routinen nutzen.

Viele Grüße
W.T.
#3623371
Lesenswert?

Ist schon 'ne Zeit her, dass ich das für einem STM32F103 geschrieben 
habe. Aber soweit ich mich erinnere, war es mehr ein Abschreiben von den 
StdPeriph_Examples. Als EEPROM hatte ich ein 24AA01 eingesetzt. Kannst 
ja mal nachschauen, ob diese beiden EEPROM kompatibel sind. In diesem 
Fall würde ich mal in den Backups nachschauen.
OP #3623405
Lesenswert?

@Julian: Soo...im Anhang finden sich jetzt die funktionsfähigen EEPROM- 
und I2C-Routinen. Ob als hilfreiche Schnipsel oder als warnendes 
Beispiel darf sich jeder selbst aussuchen.

@Mehmet: Mich würde es schon interessieren, ob das Fehl-Lesen, das 
auftritt, wenn das erste Lesen nach der Initialisierung mehr als ein 
Byte ist, "normal" ist. Aber dafür jemanden in altem Quelltext 
herumwühlen lassen kann man wohl niemandem zumuten.

Viele Grüße
W.T.
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren