單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網(wǎng)單片機
W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內置MAC以及PHY,擁有獨立的32KB以太網(wǎng)收發(fā)緩存,可供8個獨立硬件socket使用。如此配置,真正實現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN68和QFN100。
W55MH32Q采用QFN68封裝版本,尺寸為8x8mm,它擁有36個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、3個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN以及1個USB2.0。在保持與同系列其他版本一致的核心性能基礎上,僅減少了部分GPIO以及SDIO接口,其他參數(shù)保持一致,性價比優(yōu)勢顯著,尤其適合網(wǎng)關模組等對空間布局要求較高的場景。緊湊的尺寸和精簡化外設配置,使其能夠在有限空間內實現(xiàn)高效的網(wǎng)絡連接與數(shù)據(jù)交互,成為物聯(lián)網(wǎng)網(wǎng)關、邊緣計算節(jié)點等緊湊型設備的理想選擇。 同系列還有QFN100封裝的W55MH32L版本,該版本擁有更豐富的外設資源,適用于需要多接口擴展的復雜工控場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網(wǎng)站或者私信獲取。
此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及MQTT SSL等,為網(wǎng)絡通信安全再添保障。
為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32Q這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實現(xiàn)調試、下載以及串口打印日志等功能。開發(fā)板將所有外設全部引出,拓展功能也大幅提升,便于開發(fā)者全面評估芯片性能。
若您想獲取芯片和開發(fā)板的更多詳細信息,包括產(chǎn)品特性、技術參數(shù)以及價格等,歡迎訪問官方網(wǎng)頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。

第十六章 I2C
1 I2C簡介
I2C(Inter-Integrated Circuit)總線是一種由 PHILIPS 公司開發(fā)的兩線式串行總線,用于連接微控制器以及其外圍設備。它是由數(shù)據(jù)線 SDA 和時鐘線 SCL 構成的串行總線,可發(fā)送和接收數(shù)據(jù),在 CPU 與被控 IC 之間、IC 與 IC 之間進行雙向傳送。
I2C 總線有如下特點:
?總線由數(shù)據(jù)線 SDA 和時鐘線 SCL 構成的串行總線,數(shù)據(jù)線用來傳輸數(shù)據(jù),時鐘線用來同步數(shù)據(jù)收發(fā)。
?總線上每一個器件都有一個唯一的地址識別,所以我們只需要知道器件的地址,根據(jù)時序就可以實現(xiàn)微控制器與器件之間的通信。
?數(shù)據(jù)線 SDA 和時鐘線 SCL 都是雙向線路,都通過一個電流源或上拉電阻連接到正的電壓,所以當總線空閑的時候,這兩條線路都是高電平。
?總線上數(shù)據(jù)的傳輸速率在標準模式下可達 100kbit/s 在快速模式下可達 400kbit/s 在高速模式下可達 3.4Mbit/s。
總線支持設備連接。在使用 I2C 通信總線時,可以有多個具備 I2C 通信能力的設備掛載在上面,同時支持多個主機和多個從機,連接到總線的接口數(shù)量只由總線電容 400pF 的限制決定。I2C 總線掛載多個器件的示意圖,如下圖所示:

I2C 總線掛載多個器件
下面來學習I2C 總線協(xié)議,I2C 總線時序圖如下所示:

I2C 總線時序圖
為了便于大家更好的了解 I2C 協(xié)議,我們從起始信號、停止信號、應答信號、數(shù)據(jù)有效性、數(shù)據(jù)傳輸以及空閑狀態(tài)等 6 個方面講解。
① 起始信號
當 SCL 為高電平期間,SDA 由高到低的跳變。起始信號是一種電平跳變時序信號,而不是一個電平信號。該信號由主機發(fā)出,在起始信號產(chǎn)生后,總線就處于被占用狀態(tài),準備數(shù)據(jù)傳輸。
② 停止信號
當 SCL 為高電平期間,SDA 由低到高的跳變。停止信號也是一種電平跳變時序信號,而不是一個電平信號。該信號由主機發(fā)出,在停止信號發(fā)出后,總線就處于空閑狀態(tài)。
③ 應答信號
發(fā)送器每發(fā)送一個字節(jié),就在時鐘脈沖 9 期間釋放數(shù)據(jù)線,由接收器反饋一個應答信號。應答信號為低電平時,規(guī)定為有效應答位(ACK 簡稱應答位),表示接收器已經(jīng)成功地接收了該字節(jié);應答信號為高電平時,規(guī)定為非應答位(NACK),一般表示接收器接收該字節(jié)沒有成功。
觀察上圖標號③就可以發(fā)現(xiàn),有效應答的要求是從機在第 9 個時鐘脈沖之前的低電平期間將 SDA 線拉低,并且確保在該時鐘的高電平期間為穩(wěn)定的低電平。如果接收器是主機,則在它收到最后一個字節(jié)后,發(fā)送一個 NACK 信號,以通知被控發(fā)送器結束數(shù)據(jù)發(fā)送,并釋放SDA 線,以便主機接收器發(fā)送一個停止信號。
④ 數(shù)據(jù)有效性
I2C 總線進行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。數(shù)據(jù)在 SCL的上升沿到來之前就需準備好。并在下降沿到來之前必須穩(wěn)定。
⑤ 數(shù)據(jù)傳輸
在 I2C 總線上傳送的每一位數(shù)據(jù)都有一個時鐘脈沖相對應(或同步控制),即在 SCL 串行時鐘的配合下,在 SDA 上逐位地串行傳送每一位數(shù)據(jù)。數(shù)據(jù)位的傳輸是邊沿觸發(fā)。
⑥ 空閑狀態(tài)
I2C 總線的 SDA 和 SCL 兩條信號線同時處于高電平時,規(guī)定為總線的空閑狀態(tài)。此時各個器件的輸出級場效應管均處在截止狀態(tài),即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。
了解前面的知識后,下面介紹一下 I2C 的基本的讀寫通訊過程,包括主機寫數(shù)據(jù)到從機即寫操作,主機到從機讀取數(shù)據(jù)即讀操作。下面先看一下寫操作通訊過程圖。

寫操作通訊過程
主機首先在 I2C 總線上發(fā)送起始信號,那么這時總線上的從機都會等待接收由主機發(fā)出的數(shù)據(jù)。主機接著發(fā)送從機地址+0(寫操作)組成的 8bit 數(shù)據(jù),所有從機接收到該 8bit 數(shù)據(jù)后,自行檢驗是否是自己的設備的地址,假如是自己的設備地址,那么從機就會發(fā)出應答信號。
主機在總線上接收到有應答信號后,才能繼續(xù)向從機發(fā)送數(shù)據(jù)。
注意:I2C 總線上傳送的數(shù)據(jù)信號是廣義的,既包括地址信號,又包括真正的數(shù)據(jù)信號。
接著講解一下 I2C 總線的讀操作過程,先看一下讀操作通訊過程圖。

讀操作通訊過程圖
主機向從機讀取數(shù)據(jù)的操作,一開始的操作與寫操作有點相似,觀察兩個圖也可以發(fā)現(xiàn),都是由主機發(fā)出起始信號,接著發(fā)送從機地址+1(讀操作)組成的 8bit 數(shù)據(jù),從機接收到數(shù)據(jù)驗證是否是自身的地址。 那么在驗證是自己的設備地址后,從機就會發(fā)出應答信號,并向主機返回 8bit 數(shù)據(jù),發(fā)送完之后從機就會等待主機的應答信號。假如主機一直返回應答信號,那么從機可以一直發(fā)送數(shù)據(jù),也就是圖中的(n byte + 應答信號)情況,直到主機發(fā)出非應答信號,從機才會停止發(fā)送數(shù)據(jù)。
2 I2C從模式
默認情況下,I2C 接口總是工作在從模式。從從模式切換到主模式,需要產(chǎn)生一個起始條件。為了產(chǎn)生正確的時序,必須在 I2C_CR2 寄存器中設定該模塊的輸入時鐘。輸入時鐘的頻率必須至少是:
標準模式下為:2MHz
快速模式下為:4MHz
一旦檢測到起始條件,在 SDA線上接收到的地址被送到移位寄存器。然后與芯片自己的地址 OAR1和 OAR2(當 ENDUAL=1)或者廣播呼叫地址(如果 ENGC=1)相比較。
注:在 10 位地址模式時,比較包括頭段序列(11110xx0),其中的 xx 是地址的兩個最高有效位。頭段或地址不匹配:I2C 接口將其忽略并等待另一個起始條件。
頭段匹配(僅 10 位模式):如果 ACK 位被置'1',I2C 接口產(chǎn)生一個應答脈沖并等待 8 位從地址。地址匹配:I2C 接口產(chǎn)生以下時序:
如果 ACK 被置'1',則產(chǎn)生一個應答脈沖硬件設置 ADDR 位;如果設置了 ITEVFEN 位,則產(chǎn)生一個中斷如果 ENDUAL=1,軟件必須讀 DUALF 位,以確認響應了哪個從地址。在 10 位模式,接收到地址序列后,從設備總是處于接收器模式。在收到與地址匹配的頭序列并且最低位為'1'(即 11110xx1)后,當接收到重復的起始條件時,將進入發(fā)送器模式。在從模式下 TRA 位指示當前是處于接收器模式還是發(fā)送器模式。
從發(fā)送器
在接收到地址和清除 ADDR 位后,從發(fā)送器將字節(jié)從 DR 寄存器經(jīng)由內部移位寄存器發(fā)送到 SDA 線上。
從設備保持 SCL 為低電平,直到 ADDR 位被清除并且待發(fā)送數(shù)據(jù)已寫入 DR 寄存器。(見下圖中的EV1 和 EV3)。當收到應答脈沖時:TxE 位被硬件置位,如果設置了 ITEVFEN 和 ITBUFEN 位,則產(chǎn)生一個中斷。
如果 TxE 位被置位,但在下一個數(shù)據(jù)發(fā)送結束之前沒有新數(shù)據(jù)寫入到 I2C_DR 寄存器,則 BTF 位被置位,在清除 BTF 之前 I2C 接口將保持 SCL 為低電平;讀出 I2C_SR1 之后再寫入 I2C_DR 寄存器將清除 BTF 位。

從發(fā)送器的傳送序列圖
說明:S=Start(起始條件),S,=重復的起始條件,P=Stop(停止條件),A=應,NA=非響應 EVx=事件(ITEVFEN=1 時產(chǎn)生中斷)
EV1:ADDR=1,讀 SR1 然后讀 SR2 將清除該事件。
EV3-1:TxE=1,移位寄存器空,數(shù)據(jù)寄存器空,寫 DR。
EV3:TxE=1,移位寄存器非空,數(shù)據(jù)寄存空,寫 DR 將清除該事件。
EV3-2:AF=1,在 SR1 寄存器的 AF 位寫'0'可清除 AF 位。
注:
1-EV1 和 EV3 1 事件拉長 SCL 低的時間,直到對應的軟件序列結束。
2-EV3 的軟件序列必須在當前字節(jié)傳輸結束之前完成。
從接收器
在接收到地址并清除 ADDR 后,從接收器將通過內部移位寄存器從 SDA 線接收到的字節(jié)存進 DR 寄存器。I2C 接口在接收到每個字節(jié)后都執(zhí)行下列操作:
如果設置了 ACK 位,則產(chǎn)生一個應答脈沖硬件設置 RxNE=1。如果設置了 ITEVFEN 和 ITBUFEN 位,則產(chǎn)生一個中斷。
如果 RxNE 被置位,并且在接收新的數(shù)據(jù)結束之前 DR 寄存器未被讀出,BTF 位被置位,在清除BTF 之前 I2C 接口將保持 SCL 為低電平;讀出 I2C_SR1 之后再寫入 I2C_DR 寄存器將清除 BTF 位。

從接收器的傳送序列圖
說明:S=Start(起始條件),S,=重復的起始條件,P=Stop(停止條件),A=響應,NA=非響應,EVx=事件(ITEVFEN=1 時產(chǎn)生中斷)
EV1:ADDR=1,讀 SR1 然后讀 SR2 將清除該事件。
EV2:RxNE=1,讀 DR 將消除該事件。
EV4:STOPF=1,讀 SR1 然后寫 CR1 寄存器將清除該事件。
注:
1.EV1 事件拉長 SCL 低的時間,直到對應的軟件序列結束。
2.EV2 的軟件序列必須在當前字節(jié)傳輸結束之前完成。關閉從通信在傳輸完最后一個數(shù)據(jù)字節(jié)后,主設備產(chǎn)生一個停止條件,I2C 接口檢測到這一條件時:
?設置 STOPF=1,如果設置了 ITEVFEN 位,則產(chǎn)生一個中斷。然后 I2C 接口等待讀 SR1 寄存器,再寫 CR1 寄存器。
3 I2C主模式
在主模式時,I2C 接口啟動數(shù)據(jù)傳輸并產(chǎn)生時鐘信號。串行數(shù)據(jù)傳輸總是以起始條件開始并以停止條件結束。當通過 START 位在總線上產(chǎn)生了起始條件,設備就進入了主模式。
以下是主模式所要求的操作順序:
1.在 I2C_CR2 寄存器中設定該模塊的輸入時鐘以產(chǎn)生正確的時序
2.配置時鐘控制寄存器
3.配置上升時間寄存器
4.編程 I2C_CR1 寄存器啟動外設
5.置 I2C_CR1 寄存器中的 START 位為 1,產(chǎn)生起始條件
6.I2C 模塊的輸入時鐘頻率必須至少是:
7.標準模式下為:2MHz
8.快速模式下為:4MHz
9.起始條件
當 BUSY=0 時,設置 START=1,I2C 接口將產(chǎn)生一個開始條件并切換至主模式(M/SL 位置位)。
注:在主模式下,設置 START 位將在當前字節(jié)傳輸完后由硬件產(chǎn)生一個重開始條件。一旦發(fā)出開始條件:
SB 位被硬件置位,如果設置了 ITEVFEN 位,則會產(chǎn)生一個中斷。然后主設備等待讀 SR1 寄存器,緊跟著將從地址寫入 DR 寄存器。
從地址的發(fā)送
從地址通過內部移位寄存器被送到 SDA 線上。
?在 10 位地址模式時,發(fā)送一個頭段序列產(chǎn)生以下事件:
······ADD10 位被硬件置位,如果設置了 ITEVFEN 位,則產(chǎn)生一個中斷。然后主設備等待讀 SR1 寄存器,再將第二個地址字節(jié)寫入 DR 寄存器。
ADDR 位被硬件置位,如果設置了 ITEVFEN 位,則產(chǎn)生一個中斷。隨后主設備等待一次讀 SR1 寄存器,跟著讀 SR2 寄存器。
?在 7 位地址模式時,只需送出一個地址字節(jié)。
······一旦該地址字節(jié)被送出:
? ADDR 位被硬件置位,如果設置了 ITEVFEN 位,則產(chǎn)生一個中斷。
隨后主設備等待一次讀 SR1 寄存器,跟著讀 SR2 寄存器。根據(jù)送出從地址的最低位,主設備決定進入發(fā)送器模式還是進入接收器模式。
?在 7 位地址模式時
······? 要進入發(fā)送器模式,主設備發(fā)送從地址時置最低位為'0'。
······? 要進入接收器模式,主設備發(fā)送從地址時置最低位為'1'。
?在 10 位地址模式時
? 要進入發(fā)送器模式,主設備先送頭字節(jié)(11110xx0),然后送最低位為'0'的從地址。(這里 xx代表 10 位地址中的最高 2 位。)
? 要進入接收器模式,主設備先送頭字節(jié)(11110xx0),然后送最低位為'1'的從地址。然后再重新發(fā)送一個開始條件,后面跟著頭字節(jié)(11110xx1)(這里 xx 代表 10 位地址中的最高 2位。)
TRA 位指示主設備是在接收器模式還是發(fā)送器模式。
主發(fā)送器
在發(fā)送了地址和清除了 ADDR 位后,主設備通過內部移位寄存器將字節(jié)從 DR 寄存器發(fā)送到 SDA 線上。
主設備等待,直到 TxE 被清除。當收到應答脈沖時:
TxE 位被硬件置位,如果設置了 INEVFEN 和 ITBUFEN 位,則產(chǎn)生一個中斷。如果 TxE 被置位并且在上一次數(shù)據(jù)發(fā)送結束之前沒有寫新的數(shù)據(jù)字節(jié)到 DR 寄存器,則 BTF 被硬件置位,在清除 BTF 之前 I2C 接口將保持 SCL 為低電平;讀出 I2C_SR1 之后再寫入 I2C_DR 寄存器將清除 BTF 位。
關閉通信
在 DR 寄存器中寫入最后一個字節(jié)后,通過設置 STOP 位產(chǎn)生一個停止條件,然后 I2C 接口將自動回到從模式(M/S 位清除)。
注: 當 TxE 或 BTF 位置位時,停止條件應安排在出現(xiàn) EV8_2 事件時。

主發(fā)送器傳送序列圖
說明:S=Star(起始條件),S;=重復的起始條件,P=Stop(停止條件),A=響應,NA=非響應,EVx=事件(ITEVFEN=1 時產(chǎn)生中斷)。
EV5:SB=1,讀 SR1 然后將地址寫入 DR 寄存器將清除該事件。
EV6:ADDR=1,讀 SR1 然后讀 SR2 將清除該事件。
EV8 1:TxE=1,移位寄存器空,數(shù)據(jù)寄存器空,寫 DR 寄存器。
EV8:TxE=1,移位寄存器非空,數(shù)據(jù)寄存器空,寫入 DR 寄存器將清除該事件。
EV8 2:TxE=1,BTF=1,請求設置停止位。TxE 和 BTF 位由硬件在產(chǎn)生停止條件時清除。
EV9:ADDR10=1,讀 SR1 然后寫入 DR 寄存將清除該事件。
注:1-EV5、EV6、EV9、EV8 1 和 EV8 2 事件拉長 SCL 低的時間,直到對應的軟件序列結束。
主接收器
在發(fā)送地址和清除 ADDR 之后,I2C 接口進入主接收器模式。在此模式下,I2C 接口從 SDA 線接收數(shù)據(jù)字節(jié),并通過內部移位寄存器送至 DR 寄存器。在每個字節(jié)后,I2C 接口依次執(zhí)行以下操作:
如果 ACK 位被置位,發(fā)出一個應答脈沖。
硬設置 RxNE=1, 如果設置了 INEVFEN 和 ITBUFEN 位,則會產(chǎn)生一個中斷。
如果 RxNE 位被置位,并且在接收新數(shù)據(jù)結束前,DR 寄存器中的數(shù)據(jù)沒有被讀走,硬件將設置BTF=1,在清除 BTF 之前 I2C 接口將保持 SCL 為低電平;讀出 I2C_SR1 之后再讀出 I2C_DR 寄存器將清除 BTF 位。
關閉通信
主設備在從從設備接收到最后一個字節(jié)后發(fā)送一個 NACK。接收到 NACK 后,從設備釋放對 SCL 和SDA 線的控制;主設備就可以發(fā)送一個停止/重起始條件。為了在收到最后一個字節(jié)后產(chǎn)生一個 NACK 脈沖,在讀倒數(shù)第二個數(shù)據(jù)字節(jié)之后(在倒數(shù)第二個 RxNE 事件之后)必須清除 ACK 位。為了產(chǎn)生一個停止/重起始條件,軟件必須在讀倒數(shù)第二個數(shù)據(jù)字節(jié)之后(在倒數(shù)第二個 RxNE事件之后)設置 STOP/START 位。只接收一個字節(jié)時,剛好在 EV6 之后(EV6_1 時,清除 ADDR 之后)要關閉應答和停止條件的產(chǎn)生位。在產(chǎn)生了停止條件后,I2C 接口自動回到從模式(M/SL 位被清除)。

主接收器傳送序列圖
說明:S=Start(起始條件),S:=重復的起始條件,P=Stop(停止條件),A=響應,NA=非響應,EVx=事件(ITEVFEN=1 時產(chǎn)生中斷)EV5:SB=1,讀 SR1 然后將地址寫入 DR 寄存器將除該事件。EV6:ADDR=1,讀 SR1 然后讀 SR2 將清除該事件。在 10位主接收模式下,該事件后應設置 CR2的 START=1.EV6 1:沒有對應的事件標志,只適于接收 1 個字節(jié)的情況。恰好在 EV6 之后(即清除了 ADDR 之后),要潔除響應和停止條件的產(chǎn)生。
EV7:RxNE=1,讀 DR 寄存器清除該事件。
EV7 1:RXNE=1,讀 DR 寄存器清除該事件。設置 ACK=0 和 STOP 請求。
EV9:ADDR10=1,讀 SR1 然后寫入 DR 寄存將清除該事件。
1. 如果收到一個單獨的字節(jié),則是 NA。
2. EV5、EV6 和 E事件拉長 SCL 低電平,直到對應的軟件序列結束。
3. EV7 的軟件序列必須在當前字節(jié)傳輸結束前完成。
EV6_1 或 EV7_1 的軟件序列必須在當前傳輸字節(jié)的 ACK 脈沖之前完成。
4 SDA/SCL線控制
如果允許時鐘延長:
?發(fā)送器模式:如果 TxE=1 且 BTF=1:I2C 接口在傳輸前保持時鐘線為低,以等待軟件讀取SR1,然后把數(shù)據(jù)寫進數(shù)據(jù)寄存器(緩沖器和移位寄存器都是空的)。
?接收器模式:如果 RxNE=1 且 BTF=1:I2C 接口在接收到數(shù)據(jù)字節(jié)后保持時鐘線為低,以等待軟件讀 SR1,然后讀數(shù)據(jù)寄存器 DR(緩沖器和移位寄存器都是滿的)。
?如果在從模式中禁止時鐘延長:
?如果 RxNE=1,在接收到下個字節(jié)前 DR 還沒有被讀出,則發(fā)生過載錯。接收到的最后一個字節(jié)丟失。
?如果 TxE=1,在必須發(fā)送下個字節(jié)之前卻沒有新數(shù)據(jù)寫進 DR,則發(fā)生欠載錯。相同的字節(jié)將被重復發(fā)出。
不控制重復寫沖突。
5 I2C中斷請求
下圖列出了所有的 I2C 中斷請求:
中斷事件 | 事件標志 | 開啟控制位 |
起始位已發(fā)送 (主) | SB | ITEVFEN |
地址已發(fā)送 (主) 或地址匹配 (從) | ADDR | ITEVFEN |
10 位頭段已發(fā)送 (主) | ADD10 | ITEVFEN |
已收到停止 (從) | STOPF | ITEVFEN |
數(shù)據(jù)字節(jié)傳輸完成 | BTF | ITEVFEN |
接收緩沖區(qū)非空 | RxNE | ITEVFEN 和 ITBUFEN |
發(fā)送緩沖區(qū)空 | TxE | ITEVFEN 和 ITBUFEN |
總線錯誤 | BERR | ITERREN |
仲裁丟失 (主) | ARLO | ITERREN |
響應失敗 | AF | ITERREN |
過載 / 欠載 | OVR | ITERREN |
PEC 錯誤 | PECERR | ITERREN |
超時 / Tlow 錯誤 | TIMEOUT | ITERREN |
SMBus 提醒 | SMBALERT | - |
注:
1.SB、ADDR、ADD10、STOPF、BTF、RxNE 和 TxE 通過邏輯或匯到同一個中斷通道中。
2.BERR、ARLO、AF、OVR、PECERR、TIMEOUT 和 SMBALERT 通過邏輯或匯到同一個中斷通道中。

I2C 中斷映射圖
6 例程設計
6.1 IIC_IntTransmit例程
1.UART 模塊:配置 USART1,將printf輸出重定向到該串口,用于與用戶交互和輸出調試信息。
2.I2C 配置模塊:使能 GPIOB 和 I2C1 時鐘,配置引腳,初始化 I2C1,設置工作模式、時鐘速度等參數(shù)。
void IIC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Enable internal pull-up function
GPIO_ForcePuPdCmd(GPIOB, ENABLE);
GPIO_ForcePullUpConfig(GPIOB, GPIO_Pin_6);
GPIO_ForcePullUpConfig(GPIOB, GPIO_Pin_7);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_OwnAddress1 = 0xA0;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
3.主設備測試模塊:填充發(fā)送緩沖區(qū),生成 I2C 起始信號,發(fā)送從設備地址和數(shù)據(jù),最后生成停止信號。
void IIC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Enable internal pull-up function
GPIO_ForcePuPdCmd(GPIOB, ENABLE);
GPIO_ForcePullUpConfig(GPIOB, GPIO_Pin_6);
GPIO_ForcePullUpConfig(GPIOB, GPIO_Pin_7);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_OwnAddress1 = 0xA0;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
4.從設備測試模塊:使能 I2C 中斷,進入循環(huán)等待接收數(shù)據(jù)。若接收完成,打印數(shù)據(jù)并比較是否與發(fā)送數(shù)據(jù)一致。
void IIC_SlaveTest(void)
{
FillData();
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
while (1)
{
if (RecvFlag == 1)
{
DataPrintf(RecvBuff, BUFF_SIZE);
if (memcmp(RecvBuff, SendBuff, BUFF_SIZE) == 0)
{
printf("IIC slave int receive data successn");
}
memset(RecvBuff, 0, BUFF_SIZE);
RecvFlag = 0;
}
}
}
5.NVIC 配置模塊:配置 I2C1 的事件和錯誤中斷優(yōu)先級,使能相應中斷通道。
6.數(shù)據(jù)處理模塊:包含數(shù)據(jù)填充、打印和獲取命令等功能。
6.2 IIC_Software例程
該例程通過軟件模擬I2C協(xié)議與EEPROM芯片通信,驗證I2C驅動的正確性。程序首先初始化系統(tǒng)時鐘并通過串口輸出SYSCLK/HCLK/PCLK1/PCLK2/ADCCLK頻率信息,隨后配置I2C所需GPIO引腳(SCL/SDA),調用`ee_Test()`執(zhí)行EEPROM測試:向指定地址寫入256字節(jié)數(shù)據(jù)塊,讀取數(shù)據(jù)并校驗正確性,同時測試多字節(jié)讀寫及錯誤處理以驗證通信穩(wěn)定性。主循環(huán)保持程序運行,確保測試持續(xù)進行。工作流程如下:
1.初始化系統(tǒng):配置串口(波特率 115200)輸出系統(tǒng)時鐘頻率(SYSCLK/HCLK/PCLK1/PCLK2/ADCCLK)。
2.I2C 配置:通過i2c_CfgGpio()初始化 I2C 所需 GPIO 引腳(如 SCL/SDA)。
// main函數(shù)中的I2C GPIO配置調用
int main(void)
{
// ...(初始化代碼略)...
i2c_CfgGpio(); // 初始化I2C所需的GPIO引腳(如SCL/SDA)
ee_Test(); // 執(zhí)行EEPROM測試
while (1);
}
// 假設i2c_CfgGpio()函數(shù)實現(xiàn)(示例,實際在bsp_i2c_gpio.h中)
void i2c_CfgGpio(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 假設I2C使用GPIOB引腳
// 配置SCL和SDA引腳為開漏輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // 假設SCL=PB6,SDA=PB7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 開漏輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 上拉電阻使能(根據(jù)硬件設計選擇)
GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);
}
3.EEPROM 測試:調用ee_Test()執(zhí)行軟件 I2C 與 EEPROM 的通信測試(可能包括讀寫驗證)。
// main函數(shù)中的EEPROM測試調用
int main(void)
{
// ...(初始化代碼略)...
ee_Test(); // 執(zhí)行EEPROM讀寫測試
while (1);
}
// 假設ee_Test()函數(shù)實現(xiàn)(示例,實際在bsp_i2c_ee.h中)
void ee_Test(void)
{
uint8_t write_buf[BUFF_SIZE] = {0};
uint8_t read_buf[BUFF_SIZE] = {0};
uint16_t i;
// 初始化數(shù)據(jù)緩沖區(qū)
for (i = 0; i < BUFF_SIZE; i++)
{
write_buf[i] = i % 256; // 寫入測試數(shù)據(jù)(0~255循環(huán))
}
// 通過I2C寫入EEPROM
i2c_WriteBytes(EEPROM_ADDR, 0x00, write_buf, BUFF_SIZE);
// 延時等待寫入完成(EEPROM寫入需要時間)
delay_ms(10);
// 通過I2C讀取EEPROM數(shù)據(jù)
i2c_ReadBytes(EEPROM_ADDR, 0x00, read_buf, BUFF_SIZE);
// 驗證數(shù)據(jù)一致性(示例:打印前10字節(jié))
printf("EEPROM Test: ");
for (i = 0; i < 10; i++)
{
printf("%02X ", read_buf[i]);
}
printf("n");
}
4.主循環(huán):保持程序運行,維持測試狀態(tài)。
7 下載驗證
7.1 IIC_IntTransmit例程
程序啟動
?串口輸出系統(tǒng)時鐘頻率信息,可確認時鐘配置是否正確。
?顯示測試提示,告知用戶可通過輸入 m 或 r 選擇主設備發(fā)送或從設備接收測試模式。
主設備發(fā)送測試(輸入 m)
?串口輸出確認信息。
?顯示即將發(fā)送的十六進制數(shù)據(jù)。
程序控制 I2C 總線完成起始信號、地址及數(shù)據(jù)發(fā)送,最后發(fā)送停止信號。
從設備接收測試(輸入 r)
?串口輸出確認信息。
?使能 I2C 中斷并進入等待。
?接收到 256 字節(jié)數(shù)據(jù)后,顯示接收到的十六進制數(shù)據(jù)。
?比較接收和發(fā)送數(shù)據(jù),若一致則輸出成功信息,清空接收緩沖區(qū)并重置標志位。
7.2 IIC_Software例程
程序運行后,先完成延時與串口初始化,接著通過串口輸出系統(tǒng)時鐘頻率信息,包括SYSCLK、HCLK、PCLK1、PCLK2和ADCCLK頻率,并提示進行IIC軟件測試。隨后進行I2C所需GPIO引腳初始化,調用函數(shù)執(zhí)行與EEPROM的通信測試,可能包含向指定地址寫入數(shù)據(jù)塊、讀取數(shù)據(jù)并校驗以及測試通信穩(wěn)定性等操作。若測試正常,可認為I2C驅動功能正確;若有異常,可能會在后續(xù)測試流程中體現(xiàn)出來。最后程序進入無限循環(huán),維持當前運行狀態(tài):

WIZnet 是一家無晶圓廠半導體公司,成立于 1998 年。產(chǎn)品包括互聯(lián)網(wǎng)處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU? 面向各種應用中的嵌入式互聯(lián)網(wǎng)設備。
WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產(chǎn)品營銷。
香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
審核編輯 黃宇
-
單片機
+關注
關注
6061文章
44910瀏覽量
646510 -
I2C
+關注
關注
28文章
1533瀏覽量
126945 -
SDA
+關注
關注
0文章
125瀏覽量
28685 -
SCL
+關注
關注
1文章
243瀏覽量
17451
發(fā)布評論請先 登錄
I2C讀寫時序分析和實現(xiàn)思路

視頻詳解:上海尤老師verilog入門到實戰(zhàn)第十六課
I2C Guid I2C指南
單片機c語言教程第十六章--C51指針的使用

模擬電路網(wǎng)絡課件 第十六節(jié):多級放大電路

一文看懂I2C協(xié)議

硬件I2C與模擬I2C

一文看懂I2C協(xié)議

評論