Forum: Mikrocontroller und Digitale Elektronik STM32 I2C Übertragungsende abwarten


von Dennis X. (Gast)


Lesenswert?

Hallo zusammen!
Programmiere derzeit ein wenig für den STM32 und habe nun die 
I²C-Schnittstelle auch zum laufen gebracht.
Geholfen hat mir dabei dieser Code sehr:
http://www.micromouseonline.com/2011/09/10/i2c-use-on-the-stm32f103r-medium-density-devices/#axzz1oM1D8P00

Jetzt hab ich aber derzeit die While-Schleifen, in welchen auf das Ende 
einer Übertragung gewartet wird, auskommentiert, da sich mein Programm 
immer in diesen verläuft.
Es gibt zu diesem Problem schon Beiträge (Ja, SuFu benutzt...;-)), aber 
die haben alle keine Lösung dieses Problems oder sind nicht zu ende 
geschrieben.
An was kann es liegen? Kann ich die Abfrage etwas anderst gestalten? Hab 
auch in meinem Code schon das hier probiert:
1
    /* initiate start sequence */
2
    I2C_GenerateSTART(I2C1, ENABLE);
3
    /* check start bit flag */
4
    while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB));
5
6
    /*send write command to chip*/
7
    I2C_Send7bitAddress(I2C1, I2C1_SLAVE_ADDRESS7<<1, I2C_Direction_Transmitter);
8
    /*check master is now in Tx mode*/
9
    while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR));
10
    //while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
11
    /*mode register address*/
12
    I2C_SendData(I2C1, 0x01);
13
    /*wait for byte send to complete*/
14
    while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF));
15
    //while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
16
    /*clear bits*/
17
    I2C_SendData(I2C1, 0x02);
18
    /*wait for byte send to complete*/
19
    while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF));
20
    //while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
21
    
22
    /*generate stop*/
23
    I2C_GenerateSTOP(I2C1, ENABLE);
24
    /*stop bit flag*/
25
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));

Also eben auf das Flag gewartet und nicht die Event-Funktion.
Hat das schonmal einer gemacht und möchte sich dazu outen? Wäre echt 
dankbar!

Grüße
Dennis

von Dennis X. (Gast)


Lesenswert?

Langsam glaube ich dass da was in der Lib nicht stimmt:
1
  if(i2creg != 0)
2
  {
3
    /* Get the I2Cx SR1 register address */
4
    i2cxbase += 0x14;
5
  }
6
  else
7
  {
8
    /* Flag in I2Cx SR2 Register */
9
    I2C_FLAG = (uint32_t)(I2C_FLAG >> 16);
10
    /* Get the I2Cx SR2 register address */
11
    i2cxbase += 0x18;
12
  }

Warum zum Teufel wird I2C_FLAG, ein zu dem Zeitpunkt immer 8-Bit breiter 
Wert, ganze 16-Bit ins Nirvana geschoben. Ist doch klar, dass dann das 
Soll-Flag NULL ist, verglichen mit dem Registerinhalt ist das immer 
unwahr.

Gibts jemanden, der das zum laufen gebracht hat? Bitte melden, bin am 
verzweifeln.

von (prx) A. K. (prx)


Lesenswert?

Dennis X. schrieb:

> Warum zum Teufel wird I2C_FLAG, ein zu dem Zeitpunkt immer 8-Bit breiter
> Wert, ganze 16-Bit ins Nirvana geschoben.

Dieser Zweig greift nur wenn i2creg == 0, also Bits 28-31 == 0, und dann 
liegen die interessanten Bits durchweg in der oberen Hälfte.

von (prx) A. K. (prx)


Lesenswert?

Dennis X. schrieb:

> Gibts jemanden, der das zum laufen gebracht hat? Bitte melden, bin am
> verzweifeln.

I2C funktioniert interrupt-basiert besser als in einfachen 
Aktion-warten-Aktion-warten Abfolgen. Die neigen dazu, sich in 
unerwarteten Situationen aufzuhängen. Wenn sich die Statemachine des 
I2C-Controller nicht exakt so benimmt, wie du es erwartest, dann ist 
Sense.

Mit Interrupts bestimmt hingegen die Statemachine die Aktionen des 
Programms. Man kann das auch ohne Interrupts machen, aber die 
Arbeitsweise sollte so sein, dass der Zustand der Statemachine die 
Handlungen des Programms bestimmt, nicht etwa das Programm auf einen 
bestimmten Zustand wartet. Das gilt für alle Arten von Controllern, ob 
AVR oder STM32.

Wenn dein Programm also hängen bleibt, dann solltest du überprüfen, ob 
die Statemachine sich tatsächlich dort befindet, wo du sie vermutest. Du 
solltest also beim Warten mal in die Statusregister reinsehen.

von Dennis X. (Gast)


Lesenswert?

Hallo A.K. hab gesehn, dass du in einem anderen Thread auch bei den 
Interrupts und I²C geschrieben hast. Hast du vielleicht ein Beispiel. 
Initialisiert ist ja alles soweit, bei mir scheitert es daran, 
abzuwarten, ob und was auf dem Bus passiert.
Wär echt nett.
Dennis

von (prx) A. K. (prx)


Lesenswert?

Dennis X. schrieb:

> Hast du vielleicht ein Beispiel.

Nichts was dir helfen würde. Ich gehe bei sowas anders an die Sache ran, 
und was dabei rauskommt ist eine C++ Klasse mit Abhängigkeit von einigen 
anderen selbstgebauten Dingen. Soll heissen, ich baue eine eigene 
Library, mit viel höherem Abstraktionsniveau als ST, und das ohne 
Verwendung der StdPeriphLib.

von Timm T. (Gast)


Lesenswert?

Ich habs nicht so mit C: Ist das jetzt der Hardware-I2C oder eine 
Software-I2C-Implementierung, die da benutzt wird?

von (prx) A. K. (prx)


Lesenswert?

Hardware.

von Dennis X. (Gast)


Lesenswert?

Timm Thaler schrieb:
> die da benutzt wird?

Und benutzt wird da auch noch nicht viel... Aber ich hab grad eine 
fertige Interrupt Implementierung gefunden, probier die grad mal aus.

von Reinhard B. (brainstorm)


Lesenswert?

Bei manchen STM32 steht auch Einiges zum I2C Interface im Errata. 
Vielleicht lohnt sich ein Blick.

Vielleicht hat es auch damit was zu tun:
Beitrag "Re: stm32 Cortex I2C : Master zieht SCL auf Masse"

Ein paar Beiträge weiter unten gibts korrigierte Versionen.

mfg

von Dennis X. (Gast)


Lesenswert?

Phuu, hab ja grad auch nochmal eine Lib direkt von ST gefunden, doch bis 
die mal lief... Naja ich glaub ich schreib echt auch noch was eigenes. 
Man kann sich zwar ein weig damit anfreunden, doch was eienes ist 
einfach nochmal ein Stück vertrauter.

Danke nochmal!
Dennis

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.