STML151RB I2C-Startbedingung gesendet, aber SB nicht gesetzt

Ich habe ein benutzerdefiniertes Board mit einem STM32L151RB. Ich möchte I2C im Master-Modus mit Standard-Peripheriebibliothek verwenden . Ich habe damit begonnen, Codeblöcke aus dem Demoprojekt zu kopieren.

Das Problem ist, dass die Startbedingung gesendet (mit einem Logikanalysator bestätigt) wird, aber das SB (Startbit) in I2C_SR (Statusregister) nie gesetzt wird.

Ich habe 4k7 Klimmzüge. I2C-Leitungen ändern den Status separat (damit sie nicht kurzgeschlossen sind, GPIOs scheinen in Ordnung konfiguriert zu sein und das I2C-Peripheriegerät die Uhr aktiviert hat):Geben Sie hier die Bildbeschreibung ein

Ich werfe I2C-Register in meine besetzte Warteschleife und erhalte immer (hex):

I2C1->CR1=00000501
I2C1->CR2=00000002
I2C1->SR1=00000000

Dies ist mein Init-Code:

void i2c_init(void){
    //enable clock to I2C peripheral
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    //configure pins in alternate mode (GPIO clock is already enabled in pins_init)
    GPIO_PinAFConfig(GPIOB, GPIO_AF_I2C1, GPIO_Pin_6 | GPIO_Pin_7);

    GPIO_InitTypeDef g;

    //PB6, PB7 - output, open drain, fast
    g.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    g.GPIO_Mode = GPIO_Mode_AF;
    g.GPIO_Speed = GPIO_Speed_2MHz;
    g.GPIO_OType = GPIO_OType_OD;
    g.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &g);

    I2C_InitTypeDef init;

    init.I2C_ClockSpeed = 100000;
    init.I2C_Mode = I2C_Mode_I2C;
    init.I2C_DutyCycle = I2C_DutyCycle_2;
    init.I2C_OwnAddress1 = 0x00;
    init.I2C_Ack = I2C_Ack_Enable;
    init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_Init(I2C1, &init);
    I2C_Cmd(I2C1, ENABLE);
}

Das ist mein Mastercode:

  I2C_ClearFlag(I2C1, I2C_FLAG_AF);
  I2C_AcknowledgeConfig(I2C1, ENABLE);

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

  /*!< Test on I2C1 EV5 and clear it */
  while ((!I2C_GetFlagStatus(I2C1,I2C_FLAG_SB)))  /*!< EV5 */
  {
    debugf("----busy wait----");
    debugf("I2C1->CR1=%08X", (unsigned int)I2C1->CR1);
    debugf("I2C1->CR2=%08X", (unsigned int)I2C1->CR2);
    debugf("I2C1->SR1=%08X", (unsigned int)I2C1->SR1);
    delay_ms(150); //this delay does not change anything (just limits debug terminal speed)
  } //this loop never exits

Warum kann das Startbit im Statusregister nicht gesetzt werden, nachdem die GPIOs erfolgreich eine Startbedingung übermittelt haben?

Antworten (1)

Ich habe herausgefunden, dass es sich um ein GPIO-Konfigurationsproblem handelt. Mit diesem Code stellte sich heraus, dass meine Zeile:

GPIO_PinAFConfig(GPIOB, GPIO_AF_I2C1, GPIO_Pin_6 | GPIO_Pin_7);

Register falsch einstellen. Der richtige Weg zum Einrichten von I2C auf PB6/PB7 ist:

GPIOB->AFR[0] |= ( 1 << 30 ) | ( 1 << 26); // P6/P7 => AF4

Jetzt funktioniert I2C einwandfrei.

AKTUALISIEREN

Ahh .... die Freuden der C-Typ-Sicherheit. Der korrekte Aufruf der ST-Bibliotheksfunktion lautet:

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
  1. GPIO_Pin_6und GPIO_PinSource6sind unterschiedlich definiert
  2. Das Pin-Argument kommt an zweiter Stelle
  3. Das Argument für alternative Funktionen kommt an dritter Stelle
  4. Pins müssen einzeln konfiguriert werden

Lektion gelernt: Verwenden Sie Enums für Ihre eigenen Codeargumente anstelle von magischen Zahlen!