淺談 STM32 硬體I2C的使用 (中斷方式 無DMA 無最高優先順序)

來源:互聯網
上載者:User
引子

STM32的硬體I2C很多人都對它望而卻步。因為很多電工都說,STM32 硬體 I2C有BUG、不穩定、死機等等……最後都使用GPIO類比I2C。

的確,類比I2C好用。但是在我看來在一個72M的Cortex-M3的MCU上這樣做非常不妥。一般來說I2C是一種慢速匯流排,就算工作在400kHz的快速模式上,I2C傳送每個位元組仍需要至少23us——還沒有計算地址、起始訊號和結束訊號的發送。如果使用GPIO類比的I2C,這23us的CPU時間都在空轉中浪費了,而這23us已經可以做不少的事情了,所以在STM32上I2C還是使用硬體為佳——雖然它多多少少有點缺陷。

這篇文章不是給完全沒有接觸過STM32 硬體I2C的新手看的,看這篇文章之前至少先閱讀STM32的參考手冊(RM0008)。

轉載請註明出處 http://racede.me/talk_about_stm32_i2c_peripheral.html

 

概覽

我們先來看一下STM32 I2C硬體的結構

我們可以看見STM32的硬體I2C有兩個和資料有關的寄存器“資料寄存器(Data register)”(DR)和“資料移位寄存器(Data shift register)”(DSR),我們的軟體寫入的是DR, DSR用於I2C資料的移位發送和接收,DR和DSR的資料交換由硬體控制——發送時DSR為空白,DR不為空白時,硬體自動把DR的資料寫進DSR;接收時DR為空白,DSR不為空白,硬體自動把DSR資料寫進DR。連續資料轉送時,這樣兩個寄存器的資料交換使得軟體讀出和寫入DR不會影響I2C匯流排中的資料接收和發送,使I2C的效率更高,這看起來十分美好,但是正是這個特點在某些情況下會變成電工們的噩夢。原因有二。

1、硬體上,DR和DSR的交換器制存在缺陷。

2、軟體上,因為DR和DSR一共能容納兩個位元組的資料,導致接收時候NACK的設定有一定的不可預料性。

 

硬體

硬體I2C上的缺陷,新版英文ErrSheet已經寫得很清楚,就不引用了,這裡只簡單說說要點和一些個人總結。

1、EV7, EV7_1, EV6_1, EV6_3, EV2, EV8 和 EV3 必須在當前位元組傳輸前處理完成,不然,有可能會導致資料出錯。

這幾個事件都涉及到DR和DSR,個人猜測(主要是有個”may be”才敢猜測)可能是讀出或者寫入DR的同時DSR被填滿或清空,導致資料出錯。理想情況下“讀出或者寫入DR的同時DSR被填滿或清空”是不可能發生的,中斷一來臨的時候,CPU馬上處理插斷要求,讀出或者寫入DR資料,這時DSR的資料還是“新鮮滾熱辣”的,可能連一位都沒有接收或發送。但是,在實際使用時,可能有別的中斷優先順序比I2C的事件中斷要高,I2C事件沒有及時處理而出現了上述的情況。所以,ST建議把I2C的事件中斷設定成最高優先順序。

2、產生STOP前DSR必須為空白,不然,會導致DSR裡的資料左移一位。

這個沒什麼好說的,就是一個硬體的BUG,保證發送STOP前DSR沒有資料就可以了。

3、匯流排上,開始條件(S)後沒有進行資料轉送就馬上設定停止條件(P),或者S後忘記P會導致硬體I2C不能再次產生S,必須軟複位I2C。

這個ST解釋成是,STM32嚴格按照了I2C的標準,S之後沒有資料轉送是不能P的。其實這點可以體諒,但是,這點如果沒有處理好,匯流排上的錯誤會導致STM32 I2C陷入癱瘓。

 

軟體

由於DR和DSR的存在,編程上需要一些技巧,新版英文ErrSheet和參考手冊(RM0008)都有相關的操作介紹(Closing the communication),排除硬體上的缺陷,編程的痛點主要在接收時如何可靠地設定NACK上。

在只有DSR的MCU上設定NACK是非常簡單的,在讀出倒數第二個資料前設定一下就可以了,但是個方法在似乎在STM32上行不通,因為STM32有DR和DSR,在倒數第二個資料被接收的時候(RxNE置位),馬上設定NACK,理想情況下沒有任何問題,NACK也被正確的發送,但是如果有其他更高優先順序的中斷打斷了這個過程,NACK就不能及時設定,導致從器件收到的是ACK沒有釋放匯流排……

ST提供的資料上(筆者所見),給電工們的建議。

1、接收2個位元組或1個位元組時,切換GPIO模式為OD,然後軟體下拉SCL引腳,使硬體I2C發生時鐘延展,把下一個位元組開始傳輸的時機延後,設定完NACK後,再把GPIO設定回AFOD,但是這隻能解決小於兩個位元組的接收。

2、大於2個位元組用DMA,DMA可以說是特效藥,“屢試不爽”。不過要注意,接收大於或等於2個位元組時才能使用DMA,不然不能產生EOT-1事件導致NACK不能正確發送。

3、設定I2C事件中斷為最高優先等級。

 

方案

讀到這裡你可能會想,硬體有缺陷,軟體也得這麼“猥瑣”,可以說是寸步難行。真的沒有其他辦法了嗎?其實,我們可以把DR和DSR兩個當一個用,全部判斷BTF,不理會TxE和RxE,用時間來換穩定性,慢點就慢點總比沒得用好。

Important!

發送時:

開始,發送寫地址,器件應答,清ADDR,一位元組資料到寫DR,硬體把DR資料寫入到DSR,當DSR傳輸完畢時,DR也為空白,BTF置位,這時我們再寫一位元組資料到DR,如此迴圈,最後一次BTF置位的時候發送P或者重起始(R)。這樣操作,“硬體把DR資料寫入到DSR”執行的時間是我們可以預料的,不存在上面提及的衝突問題。

接收時:

1、接收一個位元組:按照ST給的方法。開始,發送讀地址,器件應答,清ADDR前軟體下拉SCL,寫完NACK、STOP和DR後軟體再釋放SCL。RxNE時讀DR。

2、接收兩個位元組:也是按照ST的方法。開始,發送讀地址,器件應答,設定POS和ACK,下拉SCL,清ADDR,設定NACK,釋放SCL。BTF時,軟體拉低SCL,發送STOP,讀DR,釋放SCL,再讀DR。

3、接收兩個以上位元組:開始,發送讀地址,器件應答,直接清ADDR。BTF時,讀DR一次。再BTF,再讀DR一次,如此迴圈。倒數第二次BTF時設定NACK(注意DR和DSR各有一位元組的資料),讀DR一次。再等到最後一次BTF時,軟體拉低SCL,發送STOP,讀DR,釋放SCL,再讀DR。

轉載請註明出處 http://racede.me/talk_about_stm32_i2c_peripheral.html

 

幹擾

當匯流排空閑時,無論是SCL的跳變(電平高低高),還是SDA的跳變,都會導致STM32的硬體I2C癱瘓,不能產生下一個S。當匯流排正在傳輸資料時,匯流排上的訊號幹擾對STM32的硬體I2C來說是致命的。

1、空閑時SDA跳變,會產生一個S和一個P,幸好這個P會產生一個中斷,我們可以用一個收到P就軟複位硬體I2C的策略。這樣能避免空閑時SDA跳變帶來的幹擾。

2、空閑時SCL跳變,這是一個I2C的錯誤訊號,但是STM32卻會認為這是一個S,所以SCL跳變會導致BUSY置位,而且不會像SDA跳變那樣會產生一個P中斷。如果在單主的情況下,你可以為I2C的S做一個逾時,逾時了就軟複位I2C就可以,當然最簡單的方法還是空閑時關閉I2C(PE置零)。在多從機的情況下,只能等待別的主機發送的一個P,或者伺機軟複位。

3、傳輸途中因幹擾,產生匯流排錯誤(BERR)。單主接收途中出現BERR,可以在關閉硬體I2C後,連續類比產生9個以上的SCL,在保證SDA為高電平的情況下軟複位I2C。

4、傳輸途中因幹擾,導致仲裁丟失(ARLO)。單主時和BERR的處理方法相同。

 

其他

還有什麼值得注意的?

很多電工們反映,上電也是一個大問題,I2C一上電就馬上BUSY了,第一次的S都不能發送,我是沒有遇上這個問題。Google了一下很多都說是初始化順序的問題。說說我的初始化吧,開啟I2C外設的時鐘、開啟I2C引腳所在的GPIO的時鐘、配置 GPIO_AF_OD、 I2C_DeInit、 I2C_Init、 I2C_Cmd,沒有什麼特別。還有一種可能就是,上電時上電的脈衝幹擾了匯流排,導致某個從設鎖死了匯流排(拉低了SDA)導致的BUSY置位,這個可以用處理BERR的方法,使匯流排恢複正常。(2012 Jun 6)

Important!

匯流排上的P產生後最好不要配置CR1的ACK位。STOP發送後配置ACK位——作為主機接收最後一位元組時需要發送NACK,同時我們需要響應自己的從機地址,這時需要重新設定ACK為”1″——有可能導致下一次作為主機通訊發送地址時,硬體不發送地址而直接發送P——這應該是一個硬體BUG,暫時還沒有看見相關資料——具體表現為EV6死迴圈。推薦的做法是設定P前,軟體下拉SCL,設定P,設定ACK,釋放SCL,這樣匯流排上的P將在釋放SCL後產生。(2012
Jul 3)

 

總結

這些都是我調STM32硬體I2C的一些心得。上文提及到的中斷接收和發送方法,我用TIM自動更新,產生最高佔先優先順序的中斷,並在中斷裡停留70us左右,且重裝載值是一個素數的情況下,STM32F103VET6 400kHz的I2C跑了近一周沒有探索資料錯誤。

至此,STM32 I2C的問題基本解決,歡迎廣大電工們指正、反饋。

轉載請註明出處 http://racede.me/talk_about_stm32_i2c_peripheral.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.