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

1

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

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

Tengo 4k7 pullups. Las líneas I2C cambian de estado por separado (por lo que no están en cortocircuito a nada, los GPIO parecen estar bien configurados y el periférico I2C tiene el reloj habilitado):

VuelvolosregistrosI2Cenmiciclodeesperaocupadoysiempreobtengo(hex):

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

Esteesmicódigodeinicio:

voidi2c_init(void){//enableclocktoI2CperipheralRCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//configurepinsinalternatemode(GPIOclockisalreadyenabledinpins_init)GPIO_PinAFConfig(GPIOB,GPIO_AF_I2C1,GPIO_Pin_6|GPIO_Pin_7);GPIO_InitTypeDefg;//PB6,PB7-output,opendrain,fastg.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_InitTypeDefinit;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);}

Esteesmicódigomaestro:

I2C_ClearFlag(I2C1,I2C_FLAG_AF);I2C_AcknowledgeConfig(I2C1,ENABLE);/*!<SendI2C1STARTcondition*/I2C_GenerateSTART(I2C1,ENABLE);/*!<TestonI2C1EV5andclearit*/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 establecer el bit de inicio en el registro de estado después de que los GPIO hayan transmitido correctamente una condición de inicio?

    
pregunta filo

1 respuesta

1

Descubrí que se trata de un problema de configuración de GPIO. Al usar 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 del tipo C de seguridad. 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_6 y GPIO_PinSource6 son diferentes definiciones
  2. El argumento del pin viene en segundo lugar
  3. El argumento de las funciones alternativas es tercero
  4. Los pines deben configurarse uno por uno

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

    
respondido por el filo

Lea otras preguntas en las etiquetas