最近在BMS,电压采样芯片用的是TI的bq76940,监测9-15路电压,可进行充、放电控制,数据通信采用IIC模式,我MCU采用的是STM32F103RCT6。
ST采用HAL库,因为之前搞过HAL库的429,比较熟悉,网上又有里程,就直接copy使用了。关于ST的硬件IIC网上绝大部分的文章再说bug太大,都不建议使用,但是同时也有人分享一些使用成功的解决方案,我决定自己摸索一下,顺便挑战一下自己(现在觉得真有病)。
写好代码准备调试,
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_I2C2_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; //IIC2
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;//GPIO_MODE_AF_OD; GPIO_MODE_OUTPUT_PP GPIO_MODE_AF_PP
GPIO_InitStruct.Pull = GPIO_NOPULL; //自加nsj
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;//GPIO_SPEED_FREQ_HIGH; GPIO_SPEED_HIGH
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
结果发现程序死在
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG) != HAL_OK) ,
这就是网上说的busy死锁问题,我也终究是逃不过去。经过
最近在BMS,电压采样芯片用的是TI的bq76940,监测9-15路电压,可进行充、放电控制,数据通信采用IIC模式,我MCU采用的是STM32F103RCT6。
ST采用HAL库,因为之前搞过HAL库的429,比较熟悉,网上又有里程,就直接copy使用了。关于ST的硬件IIC网上绝大部分的文章再说bug太大,都不建议使用,但是同时也有人分享一些使用成功的解决方案,我决定自己摸索一下,顺便挑战一下自己(现在觉得真有病)。
写好配置代码准备调试,
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_I2C2_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; //IIC2
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;//手册中要求配置成开漏模式
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
结果发现程序死在
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG) != HAL_OK)
这就是网上说的busy死锁问题,我也终究是逃不过去。经过查看IIC的SR2寄存器发现只要把GPIO初始化为IIC,busy标志位就会置位。于是我尝试了使用大家普遍的解决方案,在初始化前先对CR1的SWRST复位,如下,发现于事无补。
I2C2->CR1 |= 0x8000;
I2C2->CR1 &= ~0x8000;
后来认为应该在IIC初始化之后再对SWRST进行复位,这样才能彻底清除busy位。经过尝试仍然不行。查阅手册发现
只要是监测有低电平该位就会置1,我把IO设置成了开漏输出,IO口肯定不能输出高电平,接着我又查阅了bq76940的推荐电路(原理图按照推荐电路设计)
我发现也没有上拉电阻,我靠,我马上查阅了bq76940芯片是否有内部上拉,然而并没有。没办法,只能刮开电路板,在铜线上焊出了一个上拉电阻,结果发现真的跳过了busy的坑!注意初始化IO之后还是需要复位SWRST的。
先小小高兴了一下,继续调试,发现还是不能进行通信,经过串口打印发现在地址发送之后居然返回的是HAL_ERROR,这说明地址发送未成功。经过查阅手册发现这是与bq76940没有“握手成功”。原因可能有
首先排查第1点,直接更换了2套全新的板子,发现故障依旧。接着是第二点,检查了连线和焊盘,都没问题。就剩下第三条地址不对了。我查阅资料发现
我的IIC配置也是7位的地址
我自认为设置并没有问题,但查阅ST的底层发现,我里个去。。。想骂人的心都有
底层中并没有把设备的地址左移,而是直接把最低位改为“0”或“1”!这真实欺负我们这些不看底层的人啊,于是自己把器件地址偷偷的左移了一位。
但是发现仍然不行。我已经快顶不住了,身心俱疲,忽然想到我们还有协议分析仪,一下子激动起来,立刻接上去试验。发现发送的地址、读写位是正确的,跟随的ACK也是有的,但是接下来发送的数据解读出来确认红色的ERROR。
我发现ACK之后的高电平仅有2us左右,而且后面没有出现start信号,于是把IIC的频率从100k降低到50k。哈哈,协议分析仪的数据终于正常了,读写的值也是没有问题的。紧接着用串口打印出读取的数据,与分析仪一对比发现完全不一样(全是0),顿时头大,继续查吧。查来查去,发现自己在进行CRC校验的时候又把地址偷偷的左移了一位
CRCInput[0] = (I2CSlaveAddress << 1) + 1;
CRCInput[1] = ReadData[0];
这导致了最终的CRC校验错误,读取的数值没有传输到相应的寄存器中。果断把左移去掉,发现打印的数据终于正确了,长长的舒了一口气。
调试到现在通讯终于正常了,但据说后面还有好多的坑,比如中断、意外断电。好在现在找到了坑的边缘,可以一点一点慢慢向上爬了。