找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1836|回复: 4
打印 上一主题 下一主题
收起左侧

关于OLED IIC锁死问题

[复制链接]
跳转到指定楼层
楼主
ID:922355 发表于 2021-8-7 16:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        近日在做项目的时候,遇到了一个问题让我百思不得其解。为了尽可能复现问题,我说的尽量详细一些,并附上一些尝试。
        IIC协议是一种很常用的通信协议,一般分为硬件IIC和软件IIC两种实现方式。在实际使用过程中可能会出现IIC锁死[1]的问题。其具体表现为:SCL始终为高,SDA始终为低。但这种现象往往出现在硬件IIC,软件IIC并不会出现。但我在使用过程中却意外发现了,软件IIC也会出现IIC死锁的现象。

我使用的板子是STM32F103RCT6。资源配置如下:

         NVIC分组为2bits抢占2bits响应
        串口:①USART1用于红外,串口波特率为9600,使用DMA接受数据。②USART2用于语音芯片,波特率9600,使用DMA发送数据。③USART3用于陀螺仪模块,波特率为57600,陀螺仪的采样率为50Hz,采用中断处理数据,抢占2,响应0。④UART4、UART5用于两个激光测距模块,波特率为115200,采样率100Hz,采用中断处理数据,抢占2响应2.
       定时器:①TIM4,CH1-CH4均用于PWM输出驱动电机。②TIM2、TIM3采用了编码器模式,用于采集电机编码器的值 ③TIM6为抢占0响应1的10ms中断,用于处理当前电机的编码器的值通过PID运算得出PWM输出值作用于TIM4   ④TIM7为抢占1响应0的中断,用于刷新处理陀螺仪的数据。
       主函数:①硬件初始化,初始化OLED以及上述定时器串口。OLED采用软件IIC,运用延时函数delay_us处理IIC时序。 ②死循环里是:
  1. LED1 = ~LED1;
  2.                
  3.                 OLED_ShowNum(0,18,flag_water_cd,8,12);
  4.                 OLED_FloatShow(0,36,speed_L,12);        
  5.                 OLED_FloatShow(0,52,speed_R,12);
  6.                 OLED_Refresh_Gram();
复制代码
       即跑马灯和OLED数据更新。由于OLED刷新需要一定时间,虽然没有delay但可以看到灯是在闪的。

       问题描述:当系统运行一段时间后,会出现OLED数据不更新,灯不再闪烁,SCL为高,SDA为低的现象。可以判定为是IIC死锁的问题。但经过查阅资料,IIC死锁只会在硬件IIC出现,软件IIC不出现。

        一些尝试:
        ①注释掉UART4, UART5初始化后运行五分钟,测试三次均未出现死锁问题。 ②注释掉定时器6的初始化,运行五分钟,三次测试均不出现死锁。  ③不注释任何代码,系统运行7s后IIC死锁,灯不再闪烁,OLED不更新。 ④注释掉UART4,UART5后,修改与陀螺仪的波特率为115200,运行数十秒后死锁。⑤注释掉陀螺仪的初始化代码,运行约3min后出现死锁问题。

        猜测:高波特率的中断会打断IIC时序使主机不能收到IIC的Ack信号。

        想过的解决方案:
        ①采用输入捕获和定时器对SCL进行检测,当长时间为高电平时再给SCL一个脉冲。实测可以解决但在此系统不能实装。因为TIM6要进行PID运算,如果有比他优先级更高的中断会导致PID更新不稳定,电机转动不顺畅。②目前临时办法是不使用OLED,或者不使用激光测距模块。不知道论坛的大神有没有遇到过类似的问题,希望能有所指点。


[1] I2C死锁原因及解决方法_fengel_cs的专栏-CSDN博客_i2c死锁
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:401564 发表于 2021-8-7 17:03 | 只看该作者
外界干扰或者电源波动或者是其它中断冲突什么之类的,都会影响IIC的应答
但问题并不是像描述那样复杂,看半天都不知道在说什么
while((SDA==1)&&(k<1000))
                {
                k++;
                Delay();
                }
检测1000次,不应答就退出,觉得不够就1万次
可以重新写入
也可以设定一个IIC写入完成标志位,通过检测标志位来处理
回复

使用道具 举报

板凳
ID:959346 发表于 2021-8-7 17:33 | 只看该作者
IIC从设备锁住后,你判断总线异常或者ACK异常后,复位一下IIC总线:不管之前处于什么状态,先给一个STOP信号,然后将SDA和SCL都拉低,延时10ms(这个时间根据芯片调整)以上,然后在正常初始化。
回复

使用道具 举报

地板
ID:959346 发表于 2021-8-7 17:39 | 只看该作者
换行的时候老是按成了发送了。
上面是我们之前的处理方式,大部分都有用。但是你最好还是模拟一下,在IIC锁住时,强行这样测试一下,看看是否有效。
如果不行,测试一下你链接里的那个方案,发一整BYTE数据看看。
不过,这个是锁住后的处理,还是要测试一下,IIC最大延时能到多少,修改一下中断,保证时间小于这个延时,才是解决根本。
回复

使用道具 举报

5#
ID:922355 发表于 2021-8-9 15:28 | 只看该作者
Jiang_YY 发表于 2021-8-7 17:39
换行的时候老是按成了发送了。
上面是我们之前的处理方式,大部分都有用。但是你最好还是模拟一下,在IIC ...

感谢,我再试试
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表