Forum: Mikrocontroller und Digitale Elektronik STM32F4Discovery I2C-Kommunikation


von Jonny (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebe community,

ich möchte für ein Drucksensor über I2C auslesen, bis der jedoch da ist 
möchte ich Testweise den Baustein CS43L22 auf dem Discovery Board 
auslesen.
Nach studenlangem Durchkauen aller Beiträge zum I2C des STM32 in diesem 
Forum und dutzend anderer im WWW bin ich langsam am Verzweifeln.
Mein Problem ist jetzt die while(!I2C_CheckEvent(I2Cx, 
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); In dieser Schleife bleibt 
er stecken.

Ich hatte heute morgen die Möglichkeit mit einem Oszi beide Pins 
auszulesen. In der Funktion I2C_GenerateSTART(I2Cx, ENABLE); wird die 
SCL Leitung bei der Funktion I2Cx->CR1 |= I2C_CR1_START; auf Low 
gezogen.
Allerdings ist nachfolgend weder ein Clocksignal noch ein Datensignal 
vorhanden.

Es wäre nett wenn vielleicht jemand der schon den I2C des STM32F4 zum 
laufen gebracht hat kurz über den Code schauen könnte.

Hierzu habe ich folgende Initialisierung und Schreibe/Lesefunktion:

void I2C1_Initialisation()
{
  //Modul clock activate
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

  //Modul clock activate
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

   // Set alternate function for I2C1 output
  GPIO_PinAFConfig(GPIOB,GPIO_PinSource6, GPIO_AF_I2C1);
  GPIO_PinAFConfig(GPIOB,GPIO_PinSource9, GPIO_AF_I2C1);

  // I2C1 output settings
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOB, &GPIO_InitStructure);


  //Modul deinitialising
  I2C_DeInit(I2C1);

  //I2C1 Modul settings
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = 
I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = 100000;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_OwnAddress1 = 0x33;

  // Modul on
  I2C_Cmd(I2C1, ENABLE);

  I2C_Init(I2C1, &I2C_InitStructure);

}

void I2C_writeOneByte(I2C_TypeDef* I2Cx, uint8_t slave, uint8_t 
register_address, uint8_t Data)
{

    while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));

    /* Send I2C1 START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on I2C1 EV5 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send slave Address for write */
    I2C_Send7bitAddress(I2Cx, slave, I2C_Direction_Transmitter);

    /* Test on I2C1 EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, 
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send I2C1 slave register address */
    I2C_SendData(I2Cx, register_address);

    /* Test on I2C1 EV8_2 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send I2C1 slave Register data */
    I2C_SendData(I2Cx, Data);

    /* Test on I2C1 EV8_8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send I2C1 STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

}


Gruß
Jonny

von Jan H. (jan_h74) Flattr this


Lesenswert?

Ich verwende die I2C lib von naechste app.note : 
STM32F10x_AN2824_FW_V4.0.0  Seitdem lauft das problemlos auf meine 
Discovery STM32. Moglicherweise functioniert das auch auf das 
F4-Discovery. In diesen lib gibt eine function für I2C mit polling, oder 
ueber Interrupt. Ich verwende die "polling" function. I2C slaves sind 
ADXL345, BMP085, HMC5883L und L3G4200D (10 DOF IMU).
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00209826.pdf
Eine andere link fur I2C on the F4 : http://instk.org/blog/?p=92

von Jonny (Gast)


Lesenswert?

Danke für eine Antwort.

Ich habe das Projekt in dem zweiten Link verwendet und umgebaut sodass 
ich mit den gleichen Funktionen den Baustein auf dem Discoverybaord mit 
I2C auslesen kann. Leider ohne Erfolg, hier steckt er sogar schon in der 
GenerateStart Funktion fest.

Ich habe mal versucht das Demoprojekt Audio_playback_and_recording (da 
in diesem Projekt auch die I2C Schnittstelle verwendet wird) zum laufen 
zu bekommen. Leider tut sich da auch nichts auf dem Board...

Hat jemand ein Funktionierendes Programm das den Baustein CS43L22 auf 
dem Board ausliest?

von Michael K. (damichl)


Lesenswert?

In der Beschreibung der StdLib (für den F4!) sind funktionierende 
Beispiele.

von Thomas W. (ratos)


Lesenswert?

Probiere mal aus, "I2C_DeInit(I2C1);" zwischen 
"GPIO_PinAFConfig(GPIOB,GPIO_PinSource6, GPIO_AF_I2C1);" und 
"RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);" zu schreiben

von Jonny (Gast)


Lesenswert?

Danke für die Tipps. Das mit I2C_DeInit(I2C1); hat leider nicht zum 
Erfolg geführt. Ich werde mich dann nochmal an die Beispielprogramme 
machen.

Ich nehme an dass du die Beispiele von 
STM32F4xx_DSP_StdPeriph_Lib_V1.0.1
gemeint hast?

von Michael K. (damichl)


Lesenswert?

Genau die. Lass Dich von dem DSP nicht irritieren. Leider wird in den 
Beispielen oft ein großes STM Eval Board verwendet. Die Beispiele lassen 
sich aber sehr leicht auf das Discovery anpassen. Habe damit bisher nur 
gute Erfahrungen, auch wenn manche Examples für einen ersten Kontakt 
etwas überfüllt sind :)

von Gerhard G. (g_g)


Lesenswert?

Hallo,

Jonny schrieb:
> Es wäre nett wenn vielleicht jemand der schon den I2C des STM32F4 zum
> laufen gebracht hat kurz über den Code schauen könnte.

du musst unbedingt den RESET aktivieren,
sonst funktioniert das Ganze nicht!!


#define AUDIO_RESET_GPIO_CLK           RCC_AHB1Periph_GPIOD
#define AUDIO_RESET_PIN                GPIO_Pin_4
#define AUDIO_RESET_GPIO               GPIOD


 void Codec_Reset(void)
  {
    /* Power Down the codec */
    GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_RESET);

    /* wait for a delay to insure registers erasing */
    delay_ms(50); //Delay(CODEC_RESET_DELAY);

    /* Power on the codec */
    GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_SET);
  }
usw...


Kann bei mir den ID über 0x01 auslesen. ID =0x43







Gruß G.G.

von Jonny (Gast)


Angehängte Dateien:

Lesenswert?

Danke für den Tipp.

Habe nun den Reset eingebaut. Leider mache ich wohl immer noch irgendwas 
falsch.

Dürfte ich dein funktionierendes Programm zum Vergleichen haben?

Gruß
Jonny

von Jan (Gast)


Lesenswert?

Mal ne ganz blöde Frage:

Ein ; hinter einer "while"-Anweisung?! ;-)
Liegt da vll der Hund begraben?

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,



Jonny schrieb:
> Dürfte ich dein funktionierendes Programm zum Vergleichen haben?



gerne, in CooCox

von Jonny (Gast)


Lesenswert?

Tut mir leid ich versteh nicht was gemeint ist. Die While schleifen in 
der Lese-/Sendefunktion?

In den Schleifen wird doch gewartet bis die Flags gesetzt werden.

von Jonny (Gast)


Lesenswert?

Vielen Dank, dann werde ich mir mal das Programm mal vorknöpfen.

von Jan (Gast)


Lesenswert?

Sorry hab gestern erst gepostet und dann den Kopf eingeschalten -.-
Das mit den while-Schleifen passt schon...obwohl es eine etwas unsaubere 
Methdoe ist, da sich hier dein Controller bei fehlender 
I²C-Kommunikation aufhängt und bis zum St. Nimmerleinstag wartet (sofern 
kein Watchdog oder so interveniert)
Besser wäre es, einen Counter hoch zählen zu lassen und so einen 
"waiting"-Status zu implementieren...


Gruß Jan

von Jonny (Gast)


Lesenswert?

Ja das werde ich tun. Danke.

Ich weiss nun endlich woran es lag, meine Adresse war nicht 0x94 für das 
Device, sondern 0x94h. Wirklich ärgerlich dafür Stunden vergeudet zu 
haben. Aber dieser Fehler wird mir nicht nochmal passieren.

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.