Forum: Mikrocontroller und Digitale Elektronik STM32F030 / I2C EEPRom / Komisches Verhalten


von Markus S. (acepilot)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Versuche seid geraumer Zeit mit meinem STM32F030C8T6 eine stabile I2C 
Kommunikation hinzubekommen. Mittlerweile sehe ich aber den Wald vor 
lauter Bäumen nicht mehr. Programmiert wurde das ganze in der CoocCox 
IDE. Der Controller sitzt auf einer selbst entwickelten Platine und 
zeigt so auch keine Auffälligkeiten. An die ganzen Blockkondensatoren 
sowohl für den Kontroller als auch für das EEPROM wurden gedacht. Die 
I2C Busleitungen werden über 4k7 auf Vcc (3,3 Volt) gezogen. Der 
Kontroller läuft mit 44,236 MHz. Die I2C Timings wurden mittels der ST 
Excel Tabelle ermittelt.

Steppe ich durch mein Programm im Debugger Schritt für Schritt durch 
klappt alles und die Daten werden sauber in das EEPRom geschrieben. 
Versuche ich die Schreibfunktion im ganzen auszuführen schreibt er ein 
Byte, beim Versuch ein weiteres Byte zu schreiben bleibt er hängen und 
bekommt das I2C_FLAG_TXIS nicht gesetzt.

Aufruf der Schreibfunktion:
1
      EEPRom_Write(I2CDev,EEPROMAddr, 0x80, hbyte);
2
      EEPRom_Write(I2CDev,EEPROMAddr, 0x81, lbyte);

Implementation beschreibung des EEPROMS:
1
void EEPRom_Write(I2C_TypeDef* I2Cx, uint16_t address, uint8_t Reg, uint8_t Val) {
2
  //Wait until I2C isn't busy
3
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) == SET);
4
5
  //"Handle"
6
  I2C_TransferHandling(I2Cx, address, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
7
8
  //Ensure the transmit interrupted flag is set
9
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TXIS) == RESET);
10
11
  //Send the address of the register we wish to write to
12
  I2C_SendData(I2Cx, Reg);
13
14
  //Ensure that the transfer complete reload flag is
15
  //set, essentially a standard TC flag
16
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TCR) == RESET);
17
18
  //Now that the EEPROM knows which register
19
  //we want to write to, send the address again
20
  //and ensure the I2C peripheral doesn't add
21
  //any start or stop conditions
22
  I2C_TransferHandling(I2Cx, address, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);
23
24
  //Again, wait until the transmit interrupted flag is set
25
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TXIS) == RESET);
26
27
  //Send the value you wish you write to the register
28
  I2C_SendData(I2Cx, Val);
29
30
  //Wait for the stop flag to be set indicating
31
  //a stop condition has been sent
32
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF) == RESET);
33
34
  //Clear the stop flag for the next potential transfer
35
  I2C_ClearFlag(I2Cx, I2C_FLAG_STOPF);
36
}

Damit bei Bedarf besser geholfen werden kann, habe ich auch noch das 
Komplette Coocox Projekt angehängt.

Wäre super, wenn jemand etwas Licht ins dunkle bringen könnte.

Gruß,
Markus

von hp-freund (Gast)


Lesenswert?

Moin,

habe kein Coocox, würde aber erst einmal die Takte prüfen.
Hast Du Messmöglichkeiten?

Wenn ja, die Möglichkeiten des MCO nutzen...
Ist die ms korrekt?

Weiterhin ist mir aufgefallen das deine eeprom.c viele \00 enthält.
Weiß aber nicht ob das eine Rolle spielt.

von Markus S. (acepilot)


Angehängte Dateien:

Lesenswert?

Hallo hp-freund, deine Vermutung geht schon einmal in die richtige 
Richtung. Habe gerade mal den I2C Bus oszillographiert. Ich konnte dabei 
kaum meinen Augen trauen. Das erste Oszillogram zeigt mehr als deutlich 
das die I2C Clock gegen 180kHz geht, was natürlich viel zu schnell für 
das EEPROM ist (scope_0.bmp).

Also habe ich darauf nochmal angefangen, alles von Anfang an zu 
kontrollieren. Verwendet wird ein 14,745 MHz Quartz. Mit den Coocox 
standard Projekten wird versucht den Takt über HSE und einen PLL 
Multiplikator von 6 zu erzeugen. Über diese gesamte Konfiguration kann 
man auch wunderbar drüber steppen. Nur 14,745 MHz mal 6 sind alles 
andere als 44,236 MHz. Ein wunder das der Controller das überhaupt 
mitgemacht hat und nicht viel früher ausgestiegen ist.

Nachdem ich dies korrigiert habe, sieht das zweite Oszillogram auch 
schon viel besser aus (scope_1.bmp). Und die Frequenz liegt zumindest in 
der richtigen Region, wenn sie auch nicht zu 100% getroffen wurde.

Leider ändert das noch nichts an dem beschreiben des EEPRoms. Ein 
wiederholtes lesen ist unbegrenzt möglich. Versuche ich Daten in das 
EEPROM zu schreiben bleibe ich beim selben Problem hängen das die I2C 
Flags nicht sauber ankommen.

Ich werde versuchen spätestens morgen nochmal den MCO Pin zu 
oszillographieren damit man ein vollständiges Bild bekommt.

Sollte noch jemand weitere Anmerkungen haben, sind diese herzlich 
willkommen.

von Markus S. (acepilot)


Lesenswert?

Ich habe gerade testweise nach jedem Aufruf der EEPRom Schreibfunktion 
ein Delay von einer Millisekunde eingefügt. Mit diesem Delay läuft auch 
das Beschreiben des EEPRoms ohne Probleme.

Da kann doch, meines Verständnisses nach, nur noch etwas an meiner 
Routine faul sein. Es kann ja nicht die Lösung sein ein Delay 
einzufügen...

von Schnulli (Gast)


Lesenswert?

Markus S. schrieb:
> Da kann doch, meines Verständnisses nach, nur noch etwas an meiner
> Routine faul sein. Es kann ja nicht die Lösung sein ein Delay
> einzufügen...

Die Lösung dürfte darin bestehen, daß man das Schreiben des vorherigen 
Bytes ins EEPROM auch abwartet. Das ist doch selbstverständlich!
Alternativ gibt es den page mode, bei dem auch mehrere Bytes - Anzahl 
steht im Datenblatt - am Stück geschrieben werden können und nur am Ende 
gewartet werden muß.

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.