Para la referencia: el mismo problema se describe allí, pero la solución del autor no me funciona - I2C bandera ocupada extraño comportamiento
Utilicé STM32CubeMX para generar una plantilla de proyecto con la inicialización de periféricos I2C. Desafortunadamente, funciona de alguna manera extraña: después de invocar HAL_I2C_MspInit(I2C1)
, el bus se considera permanentemente ocupado.
Si trato de aplicar
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(1000);
__HAL_RCC_I2C1_RELEASE_RESET();
Eso resuelve el problema con el indicador BUSY
, pero causa el problema - el bit SB
no se configura después de que se genera el START
. De acuerdo con el depurador, los registros I2C se borran completamente después del reinicio; sospecho que este es el problema con ese método.
También confimé una caída de voltaje corta en la línea SDA durante el inicio, esa es probablemente la causa del problema. Eché un vistazo más de cerca al código de inicialización de pines SDA / SCL generado por CubeMX:
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
Lo cambié para poner el reloj habilitado antes de invocar HAL_GPIO_Init()
y ahora funcionan mis comunicaciones I2C (al menos no noté nada extraño todavía).
Finalmente, mi pregunta es: ¿hay alguna solución mejor para esto? CubeMX coloca el código de habilitación del reloj después de la invocación del método de inicio GPIO. Puedo quedarme con dos invocaciones de __HAL_RCC_I2C1_CLK_ENABLE()
, pero en mi opinión eso es bastante feo, así que estoy buscando una solución mejor, ya sea software o hardware.
El dispositivo es STM32F100RB en la placa de descubrimiento STM32VLD (con STLink v1), en caso de que sea importante.