Forum: Mikrocontroller und Digitale Elektronik STM32 I2C Bus bleibt hängen


von Michi (Gast)


Lesenswert?

Hi,

ich möchte mit dem STM32 Cortex M3 einen I2C Sensor auslesen. Allerdings 
scheitere ich schon an der Konfiguration der Schnittstelle. Ich nutze 
folgenden Code:
1
I2C_InitTypeDef  I2C_InitStructure;
2
I2C_DeInit(I2C1);
3
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
4
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
5
I2C_InitStructure.I2C_OwnAddress1 = 0x03A2;
6
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
7
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
8
I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
9
I2C_Init(I2C1, &I2C_InitStructure);   
10
I2C_Cmd(I2C1, ENABLE);
11
  
12
13
I2C_GenerateSTART(I2C1, ENABLE);
14
  
15
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

Das Programm bleibt immer an der while Schleife hängen.
I2C1 und GPIO Clock habe ich im RCC eingeschaltet. SDA, SCL (PB6, PB7) 
sind als GPIO_Mode_AF_OD konfiguriert. Die SDA und SCL sind mit 4k7 Ohm 
Pull Ups beschalten.
Ich habe heute schon den ganzen Nachmittag nach dem Fehler gesucht, aber 
nichts gefunden. Kann mir bitte jemand einen Hinweis geben, was ich 
falsch mache?

Vielen Dank

von Plan (Gast)


Lesenswert?

Das geht so einfach nicht....

Du musst ALLE Bits der Register I2C_SR1 und I2C_SR2 EINZELN 
auswerten und eine Fehlerbehandlung implementieren.

Dieses I2C_CheckEvent() klappt nur wenn die Bits haar genau so sind wie 
hier in I2C_EVENT_MASTER_MODE_SELECT definiert. Ist noch irgend ein 
anderes Bit gesetzt, dann bleibt das ganze für immer hängen.

Schreibe diese beiden Register immer noch in eine extra Variable, dann 
kannst Du debuggen was für ein Bit da noch nervt und bedient werden 
möchte.

von Michi (Gast)


Angehängte Dateien:

Lesenswert?

Ich konnte das ganze etwas eingrenzen, eine Lösung habe ich aber immer 
noch nicht gefunden:
Nach dem Senden der Startbedingung wird das SB Bit nicht gesetzt. Lt. 
Reference Manual soll das per Hardware geschehen.

von Mike R. (thesealion)


Lesenswert?

Wenn ich mir das angehöngt Bild ansehe, sieht es so aus, also ob der I2C 
Bus Busy ist. Vielleicht solltest du bevor du versuchst das Start zu 
senden erst warten, bis der Bus frei ist.
1
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

Ansonsten sah meine Testroutine genauso aus und die hat lauf Scope 
funktioniert.

von (prx) A. K. (prx)


Lesenswert?

Häng mal versuchsweise die Initialisierung der Portpins auf AF hinter 
die des I2C-Moduls. Ich meine mich zu erinnern, dass beim Initialisieren 
vom I2C-Modul die Pins kurz auf GND gehen.

von Plan (Gast)


Lesenswert?

Ist das Bit RxNE im I2C_SR1 gesetzt?
Wenn ja, dann musst Du erst ein Dummy Read machen.

Ist im I2C_SR1 ein Fehlerbit gesetzt?
Wenn ja, dann schreibe 0 auf das Register.

von Michi (Gast)


Lesenswert?

Danke schonmal für die Antworten.
In den SR Registern ist nur das Busy Flag gesetzt.
Ich habe sowohl die Initialisierung der GPIO nach der I2C 
Initialisierung als auch das Warten bis der Bus frei wird versucht. Ohne 
Erfolg.
Sobald ich initialisiere geht der Bus auf Busy. Ich hab wirklich keine 
Ahnung woran das liegen kann. Ich hab auch schon versucht, wie in der 
Reference Manual beschrieben, ein Stop Signal zu senden wenn der Bus 
Busy ist, aber das hat auch nichts gebracht. Hat noch jemand einen Tipp 
für mich?

von Christoph (Gast)


Lesenswert?

Hi Michi

ich weiß nicht ob es dir hilft aber ich hatte mal Probleme beim lesen 
von 2 Byte Daten. Bei mir hat das Vorziehen von I2Cx->CR1 = 0xC01; vor 
die Start Bedingung Abhilfe geschaffen.


  /* Send START condition */
  I2Cx->CR1 = 0xC01; /* ACK=1, POS =1, PE = 1  */
  I2C_GenerateSTART(I2Cx, ENABLE);
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

Viel Erfolg
Christoph

von Plan (Gast)


Lesenswert?

Ja, bei mir kam das auch vor.
Da ist wohl noch ein Device im Sende-Mode und zieht eine Leitung auf 
LOW.

Da muss der Port-Pin auf GPIO umgeschaltet werden und es muss manuell so 
viele Clocks generiert werden bis der Bus frei ist (DAT auf Hi).
Dann muss manuell ein STOP erzeugt werden, dann wieder die PortPins auf 
IIC Funktion umschalten.

Es ist schon eine verfluchte fummelei wenn der Bus irgendwo im nirwana 
hängt bis der wieder geht.

Es gibt auch noch ein Reset-Bit mit dem man den gesammten IIC Controller 
reseten kann. (Siehe I2C_DeInit())

von Holm T. (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal eine Problemlösung für Andere die danach suchen..
Danke für den Tip..hat mir auch geholfen bei einem seltsamen Fehler auf 
einem STM32F103. Der erste Versuch einen PCF8582 zu lesen funktionierte, 
danach blockierte der Bus.

Ursache war ein nicht leeres Empfangsregister und gesetztes RxNE Flag in 
SR1. Im Empfangsregister hockt wohl noch das 2. Byte das im Lesen mit 
einem NACK beantwortet wird. Es ist mir schleierhaft wieso der originale 
Code woanders funktioniert...

Der recht verbreitete Quellcode im Netz sieht beim Lesen eines Bytes vom 
EEPROM keinen Test darauf vor, ich habe das mal ein gefügt:
1
uint8_t I2C_EE_ByteRead( uint16_t ReadAddr)
2
{
3
        uint8_t tmp;
4
5
        /* While the bus is busy */
6
        while(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));
7
8
-> Hier
9
10
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_RXNE))    // read out some junk;
11
                tmp=I2C_ReceiveData(I2C_EE);
12
13
        /* Send START condition */
14
        I2C_GenerateSTART(I2C_EE, ENABLE);
15
16
        /* Test on EV5 and clear it */
17
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
18
19
        /* Send EEPROM address for write */
20
        I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS, I2C_Direction_Transmitter);
21
22
        /* Test on EV6 and clear it */
23
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
24
25
        /* Clear EV6 by setting again the PE bit */
26
        I2C_Cmd(I2C1, ENABLE);
27
28
#ifdef BIG_EEPROM
29
30
        /* Send the EEPROM's internal address to read from: MSB of the address first */
31
        I2C_SendData(I2C_EE, (uint8_t)((ReadAddr & 0xFF00) >> 8));
32
33
        /* Test on EV8 and clear it */
34
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
35
#endif
36
37
        /* Send the EEPROM's internal address to read from: LSB of the address */
38
        I2C_SendData(I2C_EE, (uint8_t)(ReadAddr & 0x00FF));
39
40
        /* Test on EV8 and clear it */
41
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
42
43
44
        /* Send STRAT condition a second time */
45
        I2C_GenerateSTART(I2C_EE, ENABLE);
46
47
        /* Test on EV5 and clear it */
48
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
49
50
        /* Send EEPROM address for read */
51
...

Wenn das RxNE Flag gesetzt ist, wird ein Byte gelesen und dann 
verworfen.

Die Bilder zeigen  den Fehler und dessen Behebung.

BTW: weiß Einer warum sich Pulseview das dekodieren des 2. Zugriffs 
spart?

Edit: Sorry hab vergessen die Bildschirmfotos zu beschneiden.

Gruß,

Holm

von STM Apprentice (Gast)


Lesenswert?

Holm T. schrieb:
> Die Bilder zeigen  den Fehler und dessen Behebung.

STM Apprentice schrieb:
> Ich schweife vom Thema ab, aber:
>
> Wieder mal, ich liebe meine Soft-I2C-Library!

Mit jedem Beitrag zum Thema STM-I2C-Probleme mehr und mehr.

von Holm T. (Gast)


Lesenswert?

STM Apprentice schrieb:
> Holm T. schrieb:
>> Die Bilder zeigen  den Fehler und dessen Behebung.
>
> STM Apprentice schrieb:
>> Ich schweife vom Thema ab, aber:
>>
>> Wieder mal, ich liebe meine Soft-I2C-Library!
>
> Mit jedem Beitrag zum Thema STM-I2C-Probleme mehr und mehr.

Deine Soft-I2C Library ist sicher ganz toll, ich benutze auch 
Sowas..wenn ich mal wieder einen 8051 mit einem EEPROM vergriesgnaddeln 
muß...

Gruß,

Holm

von Stefan F. (Gast)


Lesenswert?

Michi schrieb:
> ich möchte mit dem STM32 Cortex M3 einen I2C Sensor auslesen

Gut das es nur gefühlt hunderte gibt. Bitte nenne immer das konkrete 
Modell, denn ST hat viele unterschiedliche I²C Schnittstellen verbaut.

Zur Kontrolle würde ich mal LED's + 1kΩ Vorwiderstände parallel zu den 
Pull-Up Widerständen schalten. Im Ruhezustand müssten sie aus sein. 
Jetzt wäre es interessant, welche davon im Fehlerfall leuchtet.

> Ich meine mich zu erinnern, dass beim Initialisieren
> vom I2C-Modul die Pins kurz auf GND gehen.

Nicht, wenn man die Initialisierung in der richtigen Reihenfolge 
vornimmt. Hier mal ein korrektes Beispiel ohne HAL: 
http://stefanfrings.de/stm32/stm32f1.html#i2c

von Holm T. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Michi schrieb:
>> ich möchte mit dem STM32 Cortex M3 einen I2C Sensor auslesen
>
> Gut das es nur gefühlt hunderte gibt. Bitte nenne immer das konkrete
> Modell, denn ST hat viele unterschiedliche I²C Schnittstellen verbaut.
>
> Zur Kontrolle würde ich mal LED's + 1kΩ Vorwiderstände parallel zu den
> Pull-Up Widerständen schalten. Im Ruhezustand müssten sie aus sein.
> Jetzt wäre es interessant, welche davon im Fehlerfall leuchtet.
>
>> Ich meine mich zu erinnern, dass beim Initialisieren
>> vom I2C-Modul die Pins kurz auf GND gehen.
>
> Nicht, wenn man die Initialisierung in der richtigen Reihenfolge
> vornimmt. Hier mal ein korrektes Beispiel ohne HAL:
> http://stefanfrings.de/stm32/stm32f1.html#i2c

Ich hatte (bewußt) eine Leiche ausgegraben Stefan..ich denke aber nicht 
das Michi immer noch dieses Problem hat.

Gruß,

Holm

von Stefan F. (Gast)


Lesenswert?

Holm T. schrieb:
> Ich hatte  eine Leiche ausgegraben

Oh, das habe ich nicht bemerkt.

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.