该问题由某客户提出,发生在 STM32F103VDT6 器件上。据其工程师讲述:在其产品设计中,使用了 STM32 的一个 I2C 接口与一个 EEPROM 通信。在系统靠性测试中发现,经过长时间运行后,STM32 会出现不能读写 EEPROM 的现象。通过 NRST 管脚对STM32 进行复位,复位后该现象依旧存在。关掉电源,然后重新上电,现象消失。通过进一步测试发现,如果对 STM32 反复做复位操作,会很容易复现这一现象。) e2 `( H2 [2 T0 G7 L! W 问题详细描述以及ST官方解答见文档: |
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)5 O8 d2 N: U* W5 N# O* v. H$ w# b2 ^
{( ~4 O1 x( {0 b- R# i' R b9 ~/ K
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
+ d9 X9 y: W' N+ s5 u9 G0 P
/**I2C1 GPIO Configuration + i# g- i' I$ J) p6 P
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/; ?7 \1 ~1 {( q( b/ _1 y5 h
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;' X4 F1 [9 _+ Q% h2 _
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);& h5 ^* i# c/ @# b O6 x/ v5 b
/* Peripheral clock enable */3 H3 L) n% r4 B( [$ Y
__I2C1_CLK_ENABLE();9 t: e2 j6 u, `' I" O7 Y& ]5 t4 J1 P
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);6 |/ h u- ?1 B$ j! i: F
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */" N2 F" M4 p: p' E
}
}/ u8 x" b2 {( |( Q, z/ A
这时总会处现在发送时就停在了busy这个位置,sda一直为低,后来看用以前的库写的
__I2C1_CLK_ENABLE();是在GPIO设置之前,将它改到之前后就可以发送数据了,但是发现改后如再次用CUBE生成代码,它又回到了以前地方,因此再加个软复位来解决
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
$ A7 m+ A' b$ E' U3 k
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)8 H( c. e* ~4 ?8 W# ?+ ^8 Y7 B
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
, ~2 p: f' [. E* Y5 T) p
/**I2C1 GPIO Configuration , A+ r5 V6 U# X
PB6 ------> I2C1_SCL. C: C6 u8 }3 {
PB7 ------> I2C1_SDA 3 a8 g$ I1 p1 T, v9 w7 H
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
$ I) g6 M) m2 S' Z. R
/* Peripheral clock enable */
__I2C1_CLK_ENABLE();
, p# O1 S0 {3 ]2 H, n7 j
/* Peripheral interrupt init*/6 [/ A# g- I6 }' C. S
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);) s* t- D- c% [# v5 O2 c
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);4 {4 z& [& y2 Z( F7 A8 r
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);, K6 y4 Y }, _# a! [3 }
/* USER CODE BEGIN I2C1_MspInit 1 */, W- m0 z; m' k
SET_BIT(hi2c->Instance->CR1, I2C_CR1_SWRST);
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_SWRST);
/* USER CODE END I2C1_MspInit 1 */( ~( k: f. I4 I* v
}* w( G0 \0 Y1 \/ E! v# C8 X
}
试了一下果然可以解决这个问题,感谢!
RE:【ST MCU实战经验】I2C 接口进入 Busy 状态不能退出
有个问题请教下。
这样真的好了吗?参考一下