STM32F10x_硬件I2C主從通信(輪詢發(fā)送,中斷接收)
Ⅰ、寫在前面
關(guān)注我分享文章的朋友應(yīng)該知道我在前面講述過(軟件、硬件)I2C主機(jī)控制從機(jī)EEPROM的例子。在I2C通信主機(jī)控制程序是比較常見的一種,可以說在實(shí)際項(xiàng)目中,很多應(yīng)用都會(huì)使用到I2C通信。但在實(shí)際項(xiàng)目中作為I2C從機(jī)的應(yīng)用相對要少的多,本文主要講述關(guān)于【STM32F10x_硬件I2C主從通信】中STM32作為從機(jī)的例子。
在學(xué)習(xí)本問內(nèi)容之前,如果對I2C協(xié)議還不太了解的朋友請先去了解一下I2C協(xié)議,或看我之前關(guān)于I2C通信的文章(我微信公眾號(hào)和博客都有)。
關(guān)于STM32硬件I2C作為從機(jī)的文章網(wǎng)上很少(我在寫本文之前也在百度、谷歌等網(wǎng)站上搜索了解過),我猜測大概的原因主要是兩點(diǎn):1.使用該功能的人比較少; 2.說STM32硬件I2C存在BUG。
“使用該功能的人比較少”這個(gè)可以理解。其實(shí)我不能理解的是,普遍說這個(gè)有BUG的現(xiàn)象。我只覺得,你選擇了使用這個(gè)芯片來作為開發(fā),你選擇之前應(yīng)該是認(rèn)可它的,什么東西都不可能盡善盡美,一點(diǎn)小的瑕疵,只要可以避免就行。就像Windos系統(tǒng)一樣,偶爾死機(jī)、藍(lán)屏,但是你還是依然會(huì)選擇使用它。
關(guān)于STM32硬件I2C自身BUG也不否認(rèn),但官方給出了解決的辦法,作為程序員,解決一項(xiàng)BUG,也是對自身能力的一種提升。所以,遇到困難,勇于面對才是正確的做法。
實(shí)例實(shí)驗(yàn):
本文提供兩個(gè)實(shí)例:一個(gè)主機(jī)發(fā)送(硬件I2C輪詢發(fā)送數(shù)據(jù))、一個(gè)從機(jī)接收并打印接收數(shù)據(jù)(硬件I2C中斷接收數(shù)據(jù))。
主機(jī)間隔500ms發(fā)送10字節(jié),從機(jī)接收10字節(jié)檢測到I2C停止,將收到的數(shù)據(jù)通過串口打印出來?!景l(fā)送的數(shù)據(jù)及長度可修改,從機(jī)自動(dòng)檢測停止條件,也就是可以檢測得到主機(jī)發(fā)送了多少字節(jié)數(shù)據(jù)】
關(guān)于本文的更多詳情請往下看。
Ⅱ、實(shí)例工程下載
筆者針對于初學(xué)者提供的例程都是去掉了許多不必要的功能,精簡了官方的代碼,對初學(xué)者一看就明白,以簡單明了的工程供大家學(xué)習(xí)。
筆者提供的實(shí)例工程都是在板子上經(jīng)過多次測試并沒有問題才上傳至360云盤,歡迎下載測試、參照學(xué)習(xí)。
提供下載的軟件工程是基于Keil(MDK-ARM)V5版本、STM32F103ZE芯片,但F1其他型號(hào)也適用(適用F1其他型號(hào): 關(guān)注微信,回復(fù)“修改型號(hào)”)。
STM32F10x_硬件I2C主機(jī)(發(fā)送數(shù)據(jù)-輪詢方式)實(shí)例源代碼工程:
https://yunpan.cn/cMKS6muF6643V訪問密碼
STM32F10x_硬件I2C從機(jī)(接收數(shù)據(jù)-中斷方式)實(shí)例源代碼工程:
https://yunpan.cn/cMKSMCkcn8tKv訪問密碼
STM32F1資料:
https://yunpan.cn/crBUdUGdYKam2訪問密碼ca90
Ⅲ、關(guān)于I2C協(xié)議
這里再次提示一下I2C協(xié)議重要的幾點(diǎn):
1.開始和停止條件
SCL時(shí)鐘電平為高:
SDA數(shù)據(jù)線由高 -> 低 為總線開始條件;
SDA數(shù)據(jù)線由低 -> 高 為總線結(jié)束條件;
(IO模擬I2C時(shí)注意:開始之后將SCL變?yōu)榈碗娖?,防止誤操作SDA使其通信停止)
時(shí)序圖:
2.數(shù)據(jù)位傳輸
SCL時(shí)鐘電平為低, 可以改換SDA數(shù)據(jù)線的電平,在SCL上升沿的過程將SDA數(shù)據(jù)發(fā)送出去。
(IO模擬I2C時(shí)切記:請先將SCL變?yōu)榈碗娖?,再改變SDA電平狀態(tài))
時(shí)序圖:
3.數(shù)據(jù)傳輸
I2C是以字節(jié)(8位)的方式進(jìn)行傳輸,總線上每傳輸完1字節(jié)之后會(huì)有一個(gè)應(yīng)答信號(hào),主器件(主機(jī))需要產(chǎn)生對應(yīng)的一個(gè)額外時(shí)鐘。
傳輸格式:8位數(shù)據(jù) + 1位應(yīng)答
數(shù)據(jù)傳輸必須帶響應(yīng),相關(guān)的響應(yīng)時(shí)鐘脈沖由主機(jī)產(chǎn)生,在響應(yīng)的時(shí)鐘脈沖期間,發(fā)送器釋放 SDA 線(高)。
在響應(yīng)的時(shí)鐘脈沖期間 接收器必須將 SDA 線拉低,使它在這個(gè)時(shí)鐘脈沖的高電平期間保持穩(wěn)定的低電平。
應(yīng)答位的產(chǎn)生及接收:
1.在(主機(jī))寫數(shù)據(jù)的時(shí)候是從機(jī)應(yīng)答(給主機(jī)),主機(jī)檢測;
2.在(主機(jī))讀數(shù)據(jù)的時(shí)候是主機(jī)應(yīng)答(給從機(jī)),從機(jī)檢測;
(這里可以借助I2C讀寫函數(shù)一起理解)
1.時(shí)序圖(主機(jī)寫,從機(jī)應(yīng)答,主機(jī)讀取應(yīng)答):
2.時(shí)序圖(主機(jī)讀,主機(jī)產(chǎn)生應(yīng)答):
更多關(guān)于I2C協(xié)議的文檔可以網(wǎng)上查詢,也可以參看我下面下載鏈接的文檔(周立功翻譯的版本):https://yunpan.cn/cMJxKJzpWFtHE訪問密碼 82f3
Ⅳ、硬件I2C主機(jī)發(fā)送數(shù)據(jù)
硬件I2C主機(jī)的配置其實(shí)很簡單,和前面讀寫EEPROM的(主機(jī))配置一樣。
可參考我之前的文章:STM32F10x_模擬I2C讀寫EEPROM
這里就不再描述。主要講述一下主機(jī)發(fā)送數(shù)據(jù)這一塊的代碼。
我封裝的發(fā)送數(shù)據(jù)函數(shù):
I2C_Master_BufferWrite(uint8_t* pBuffer, uint32_t NumByteToWrite, uint8_t SlaveAddress)
主要就是3個(gè)參數(shù):數(shù)據(jù)BUF、數(shù)據(jù)長度、從設(shè)備地址
看過我前面主機(jī)讀寫EEPEOM代碼的人應(yīng)該很清楚,這里很相似。讀寫EEPROM比這里多了一個(gè)步驟,那就是多了寫數(shù)據(jù)地址的步驟。
必須要有的三大步驟:
1.開始
2.設(shè)備地址/寫
3.停止
主程序間隔500ms調(diào)用一次該函數(shù),發(fā)送一串(我們定義10字節(jié)),從機(jī)也是間隔500ms收到一串?dāng)?shù)據(jù)并打印出來。
Ⅴ、硬件I2C從機(jī)中斷接收數(shù)據(jù)
硬件I2C的從機(jī)接收數(shù)據(jù)一般分為三類:中斷接收、DMA接收和輪詢接收;
在實(shí)際項(xiàng)目中中斷接收和DMA接收比較常見,因?yàn)椴挥谜紦?jù)CPU資源,有數(shù)據(jù)來了才響應(yīng)接收【需要CPU具有硬件I2C功能】。
而輪詢接收數(shù)據(jù)很占用CPU資源,一般是CPU沒有硬件I2C資源,處理的數(shù)據(jù)不多的情況下。
硬件I2C從機(jī)配置I2C這一塊比較簡單,和上面主機(jī)類似,請參看源代碼或參考我之前文章的講述。
可參考我之前的文章:STM32F10x_模擬I2C讀寫EEPROM
提醒:配置中注意關(guān)于I2C事件中斷這一塊(請看源代碼)。
中斷接收函數(shù)源代碼如下:
位于stm32f10x_it.c文件下。
進(jìn)入I2C事件中斷,判斷是I2C從機(jī)事件,此時(shí),作為從機(jī)接收數(shù)據(jù)需要檢測三個(gè)標(biāo)示:
1.檢測主機(jī)已發(fā)生地址(ADDR = 1);
2.檢測有接收數(shù)據(jù)(RXNE = 1);
3.檢測到停止條件(STOPF =1)。
硬件I2C通信中,起始條件由硬件判斷完成,我們檢測的就需要這幾步就能完成基本的接收數(shù)據(jù)功能。
Ⅵ、說明
理解本文之前請先理解I2C協(xié)議。
更多關(guān)于硬件I2C主從通信的例子(如:DMA發(fā)送、DMA接收等)就不再單獨(dú)寫文章講述了,可以在微信公眾號(hào)聯(lián)系我。
以上總結(jié)僅供參考,若有不對之處,敬請諒解。