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):
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?
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);
GPIO_Pin_6
und GPIO_PinSource6
sind unterschiedlich definiertLektion gelernt: Verwenden Sie Enums für Ihre eigenen Codeargumente anstelle von magischen Zahlen!