找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 2697|回復(fù): 4
收起左側(cè)

關(guān)于OLED IIC鎖死問題

[復(fù)制鏈接]
ID:922355 發(fā)表于 2021-8-7 16:22 | 顯示全部樓層 |閱讀模式
        近日在做項目的時候,遇到了一個問題讓我百思不得其解。為了盡可能復(fù)現(xiàn)問題,我說的盡量詳細(xì)一些,并附上一些嘗試。
        IIC協(xié)議是一種很常用的通信協(xié)議,一般分為硬件IIC和軟件IIC兩種實現(xiàn)方式。在實際使用過程中可能會出現(xiàn)IIC鎖死[1]的問題。其具體表現(xiàn)為:SCL始終為高,SDA始終為低。但這種現(xiàn)象往往出現(xiàn)在硬件IIC,軟件IIC并不會出現(xiàn)。但我在使用過程中卻意外發(fā)現(xiàn)了,軟件IIC也會出現(xiàn)IIC死鎖的現(xiàn)象。

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

         NVIC分組為2bits搶占2bits響應(yīng)
        串口:①USART1用于紅外,串口波特率為9600,使用DMA接受數(shù)據(jù)。②USART2用于語音芯片,波特率9600,使用DMA發(fā)送數(shù)據(jù)。③USART3用于陀螺儀模塊,波特率為57600,陀螺儀的采樣率為50Hz,采用中斷處理數(shù)據(jù),搶占2,響應(yīng)0。④UART4、UART5用于兩個激光測距模塊,波特率為115200,采樣率100Hz,采用中斷處理數(shù)據(jù),搶占2響應(yīng)2.
       定時器:①TIM4,CH1-CH4均用于PWM輸出驅(qū)動電機。②TIM2、TIM3采用了編碼器模式,用于采集電機編碼器的值 ③TIM6為搶占0響應(yīng)1的10ms中斷,用于處理當(dāng)前電機的編碼器的值通過PID運算得出PWM輸出值作用于TIM4   ④TIM7為搶占1響應(yīng)0的中斷,用于刷新處理陀螺儀的數(shù)據(jù)。
       主函數(shù):①硬件初始化,初始化OLED以及上述定時器串口。OLED采用軟件IIC,運用延時函數(shù)delay_us處理IIC時序。 ②死循環(huán)里是:
  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();
復(fù)制代碼
       即跑馬燈和OLED數(shù)據(jù)更新。由于OLED刷新需要一定時間,雖然沒有delay但可以看到燈是在閃的。

       問題描述:當(dāng)系統(tǒng)運行一段時間后,會出現(xiàn)OLED數(shù)據(jù)不更新,燈不再閃爍,SCL為高,SDA為低的現(xiàn)象。可以判定為是IIC死鎖的問題。但經(jīng)過查閱資料,IIC死鎖只會在硬件IIC出現(xiàn),軟件IIC不出現(xiàn)。

        一些嘗試:
        ①注釋掉UART4, UART5初始化后運行五分鐘,測試三次均未出現(xiàn)死鎖問題。 ②注釋掉定時器6的初始化,運行五分鐘,三次測試均不出現(xiàn)死鎖。  ③不注釋任何代碼,系統(tǒng)運行7s后IIC死鎖,燈不再閃爍,OLED不更新。 ④注釋掉UART4,UART5后,修改與陀螺儀的波特率為115200,運行數(shù)十秒后死鎖。⑤注釋掉陀螺儀的初始化代碼,運行約3min后出現(xiàn)死鎖問題。

        猜測:高波特率的中斷會打斷IIC時序使主機不能收到IIC的Ack信號。

        想過的解決方案:
        ①采用輸入捕獲和定時器對SCL進行檢測,當(dāng)長時間為高電平時再給SCL一個脈沖。實測可以解決但在此系統(tǒng)不能實裝。因為TIM6要進行PID運算,如果有比他優(yōu)先級更高的中斷會導(dǎo)致PID更新不穩(wěn)定,電機轉(zhuǎn)動不順暢。②目前臨時辦法是不使用OLED,或者不使用激光測距模塊。不知道論壇的大神有沒有遇到過類似的問題,希望能有所指點。


[1] I2C死鎖原因及解決方法_fengel_cs的專欄-CSDN博客_i2c死鎖
回復(fù)

使用道具 舉報

ID:401564 發(fā)表于 2021-8-7 17:03 | 顯示全部樓層
外界干擾或者電源波動或者是其它中斷沖突什么之類的,都會影響IIC的應(yīng)答
但問題并不是像描述那樣復(fù)雜,看半天都不知道在說什么
while((SDA==1)&&(k<1000))
                {
                k++;
                Delay();
                }
檢測1000次,不應(yīng)答就退出,覺得不夠就1萬次
可以重新寫入
也可以設(shè)定一個IIC寫入完成標(biāo)志位,通過檢測標(biāo)志位來處理
回復(fù)

使用道具 舉報

ID:959346 發(fā)表于 2021-8-7 17:33 | 顯示全部樓層
IIC從設(shè)備鎖住后,你判斷總線異�;蛘逜CK異常后,復(fù)位一下IIC總線:不管之前處于什么狀態(tài),先給一個STOP信號,然后將SDA和SCL都拉低,延時10ms(這個時間根據(jù)芯片調(diào)整)以上,然后在正常初始化。
回復(fù)

使用道具 舉報

ID:959346 發(fā)表于 2021-8-7 17:39 | 顯示全部樓層
換行的時候老是按成了發(fā)送了。
上面是我們之前的處理方式,大部分都有用。但是你最好還是模擬一下,在IIC鎖住時,強行這樣測試一下,看看是否有效。
如果不行,測試一下你鏈接里的那個方案,發(fā)一整BYTE數(shù)據(jù)看看。
不過,這個是鎖住后的處理,還是要測試一下,IIC最大延時能到多少,修改一下中斷,保證時間小于這個延時,才是解決根本。
回復(fù)

使用道具 舉報

ID:922355 發(fā)表于 2021-8-9 15:28 | 顯示全部樓層
Jiang_YY 發(fā)表于 2021-8-7 17:39
換行的時候老是按成了發(fā)送了。
上面是我們之前的處理方式,大部分都有用。但是你最好還是模擬一下,在IIC ...

感謝,我再試試
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表