STML151RB I2C condición de inicio enviada pero SB no establecida

Tengo una placa personalizada con un STM32L151RB. Quiero usar I2C en modo maestro con biblioteca periférica estándar . Comencé copiando fragmentos de código del proyecto de demostración.

El problema es que se envía la condición de inicio (confirmada con un analizador lógico), pero el SB (bit de inicio) en I2C_SR (registro de estado) nunca se establece.

Tengo dominadas 4k7. Las líneas I2C cambian de estado por separado (por lo que no se acortan a nada, los GPIO parecen estar configurados bien y el periférico I2C tiene el reloj habilitado):ingrese la descripción de la imagen aquí

Descargo registros I2C en mi ciclo de espera ocupado y siempre obtengo (hexadecimal):

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

Este es mi código de inicio:

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);
}

Este es mi código maestro:

  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

¿Por qué no se puede configurar el bit de inicio en el registro de estado después de que los GPIO hayan transmitido con éxito una condición de inicio?

Respuestas (1)

Descubrí que es un problema de configuración de GPIO. Usando este código resultó que mi línea:

GPIO_PinAFConfig(GPIOB, GPIO_AF_I2C1, GPIO_Pin_6 | GPIO_Pin_7);

Establecer registros incorrectamente. La forma correcta de configurar I2C en PB6/PB7 es:

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

Ahora I2C funciona bien.

ACTUALIZAR

Ahh.... las alegrías de la seguridad tipo C. La invocación adecuada de la función de biblioteca ST es:

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
  1. GPIO_Pin_6y GPIO_PinSource6son diferentes define
  2. El argumento del pin viene en segundo lugar
  3. El argumento de funciones alternativas viene en tercer lugar
  4. Los pines deben configurarse uno por uno

Lección aprendida: ¡ use enumeraciones para sus propios argumentos de código en lugar de números mágicos!