
各位大神 我是stm32F103,使用CubeMX FreeRTOS,通过其配置访问24C16,碰到一个非常奇怪的问题: 原生cubeMX生成的代码,在同样一批板子上,有大概10%,在代码第一次读取24C16时,会陷入死循环,停在 stm32f1xx_hal_i2c.c中的 while((__HAL_I2C_GET_FLAG(hi2c, Flag) ? SET : RESET) == Status) 这里。 查了一些资料,对代码做了修改: 就OK了,无论是10%还是90%都可以正常工作。 分享给大家, 在stm32f1xx_hal_msp.c文件中, void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) 函数中,在user code里增加如下两句 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_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Peripheral clock enable */ __HAL_RCC_I2C1_CLK_ENABLE(); /* USER CODE BEGIN I2C1_MspInit 1 */ __HAL_RCC_I2C1_FORCE_RESET(); __HAL_RCC_I2C1_RELEASE_RESET(); /* USER CODE END I2C1_MspInit 1 */ } } 一来有点疑问请教大家: 1、这个原因是为什么?道理是什么? 2、为何STM的HAL库不这样实现?如果是Bug,这个Bug我看存在了很久了,STM不这样修改的原因是什么? 3、这样有什么隐患么? 欢迎讨论。谢谢。 |
STM32启动后,在配置IO管脚过程中,I2C的管脚,有可能会被误产生I2C的启始位,或别的原因导致24C16的I2C总线处于“忙”的状态。
如果MCU的I2C管脚是真正的OC门或者像51单片机那样带弱上拉,这时就不会出现启动时总线的误动作。
也可能是基于这原因吧,NXP的一些MCU的I2C和GPIO复用管脚是OC门,不加上拉的话,是输出不了高状态的。
在I2C协议中是有总线复位操作部分的。好像是把检测到SDA被拉低超过一定时间后,连续发送9或17位时钟信号(时间长了,具体多少位可能不准确),目的就是把原有I2C指令冲掉,这样就算总线复位了。
评分
查看全部评分
评分
查看全部评分
可是我对IO都加了上拉电阻,还是会出现这个问题。
那么现在这种复位,应该不会带来什么隐患把。
没道理这么大的公司这么大的产品,一个硬件I2C还做不好?
评分
查看全部评分
要不拿示波器看一下,最好跟踪,3.3V、SDA、SCL。
我也只是猜想,因为IO的输出寄存器默认是0,如果不修改输出寄存器的话,那么突然由输入或悬空切换到输出的时候,应该会瞬间出现个0才对。
IO是会受影响的,I2C设置的时候对应IO的状态会不会受影响就不清楚了。