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:
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
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.
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.
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.
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.
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.
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?
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
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())
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_tI2C_EE_ByteRead(uint16_tReadAddr)
2
{
3
uint8_ttmp;
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;
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
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.
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
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
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