STM32F103硬件IIC在HAL库下入坑指南

        最近在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. 引脚连接错误或者虚焊
  3. IIC的地址引脚不对。

首先排查第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校验错误,读取的数值没有传输到相应的寄存器中。果断把左移去掉,发现打印的数据终于正确了,长长的舒了一口气。

 

调试到现在通讯终于正常了,但据说后面还有好多的坑,比如中断、意外断电。好在现在找到了坑的边缘,可以一点一点慢慢向上爬了。

 

 

 

  • 35
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,它具有丰富的外设资源,包括IICI2C)总线接口。HAL库是ST公司提供的一种高级硬件抽象层,可以简化硬件操作,方便用户进行开发。 在使用STM32F103C8T6和HAL库进行6050的IIC读取时,需要先初始化IIC总线,并配置6050的设备地址和寄存器地址。 首先,我们需要包含必要的头文件: ```c #include "stm32f1xx_hal.h" #include "i2c.h" ``` 然后,在主函数中进行IIC的初始化: ```c HAL_Init(); MX_I2C1_Init(); // 初始化IIC总线 ``` 接下来,我们需要定义6050的设备地址和寄存器地址: ```c #define MPU6050_ADDR 0xD0 // 6050的设备地址 #define ACCEL_XOUT_H 0x3B // 加速度计X轴高位寄存器地址 ``` 然后,我们可以编写读取6050的函数来实现具体的读取操作: ```c void MPU6050_ReadAccel(int16_t* accelData) { uint8_t buffer[6]; HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H, 1, buffer, 6, HAL_MAX_DELAY); accelData[0] = (buffer[0] << 8) | buffer[1]; accelData[1] = (buffer[2] << 8) | buffer[3]; accelData[2] = (buffer[4] << 8) | buffer[5]; } ``` 在函数中,我们首先定义一个缓冲区用于存储读取的数据,然后使用HAL库提供的函数`HAL_I2C_Mem_Read`来进行6050寄存器的读取操作。读取到的数据存储在缓冲区中。最后,我们通过移位运算和位或运算将高位和低位数据组合成16位的加速度数据。 最后,我们可以在主函数中调用`MPU6050_ReadAccel`函数来读取6050的加速度数据: ```c int16_t accelData[3]; MPU6050_ReadAccel(accelData); // 使用读取到的加速度数据进行后续处理 ``` 以上是使用STM32F103C8T6和HAL库进行6050的IIC读取的简要示例代码。具体的实现细节可能会根据具体的需求和引脚配置有所不同,需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值