自學STM32 - I2C通信接口

2024年2月6日 26点热度 0人点赞

作者:junziyang


(註:如非特別聲明,以下筆記內容均針對STM32F103ZET6而言。不同型號,細節可能存在差別。)

一、I2C接口簡介

I2C是Inter-Integrated Circuit的簡稱,也簡寫為IIC。顧名思義,這是一種集成電路之間通信的總線協議或接口。具體到STM32中,I2C是連通微控制器與串行I2C總線之間的接口。I2C總線協議是由Philips公司開發的,它隻需要2根線(1根數據線SAD、1根時鐘線SCL)即可與連接到總線上的器件之間實現雙向同步串行通信。I2C總線接口集成在芯片內部,不需要特殊的接口電路,而且總線接口帶有模擬濾波器,可濾掉總線數據上的毛刺,有利於簡化硬件電路的PCB佈線,降低系統成本,提高系統可靠性。

I2C是一種非常靈活的多主機總線:如果兩個或以上主機同時發起數據傳輸,利用其沖突檢測和仲裁功能,可以防止數據被破壞;連接到總線上的IC器件都有唯一的地址,數據傳輸和地址設置均由軟件控制;每個器件都可以作為主機,也可以作為從機,但同一時刻隻能有一個主機;總線上的器件增刪,不影響其他器件的正常工作。

STM32中的I2C支持兩種速度模式:標準模式(Sm,高達100kHz)和快速模式(Fm,高達400kHz)。I2C可用於多種目的,包括CRC生成和校驗,系統控制總線SMBus(System Management Buss)和電源管理總線PMBus(Power Management Bus)管理等。有的MCU中還為I2C配備了DMA功能,以減輕數據傳輸過程中CPU的負擔。

除了用於收發數據,I2C接口還可在串行和並行數據傳輸間進行直接切換。相關中斷可以由軟件進行開關。

二、I2C工作原理

I2C相關的寄存器共有9個,功能位與復位值表如圖1所示。I2C的功能就是通過配置這些寄存器來實現的。學習過程中參照這個表,有利於對所述內容的理解

圖1. I2C寄存器與復位值表

2.1 原理框圖

I2C的原理框圖如圖2所示。可以看到,其內部包含了兩個相對獨立的模塊:數據處理模塊和邏輯控制模塊。通過左側的3個引腳與外界交互,SDA是數據引腳,SCL是時鐘引腳,SMBA是一個可選的信號引腳。

圖2. I2C接口原理框圖

2.2 I2C工作模式

I2C接口支持如下4種模式:

  • 從發送器模式
  • 從接收器模式
  • 主發送器模式
  • 主接收器模式

默認處於從模式,收到起始條件時切換為主模式,出現仲裁丟失或產生STOP時,切換回從模式。I2C支持多主機模式。

通信流程說明如下:

處於主模式的I2C接口負責發起數據傳輸並產生時鐘信號。I2C為串行通信,必須以“起始條件”(START condition)開始,以“停止條件”(STOP condition)結束。所謂起始條件和終止條件,是SDA和SCL線上的一組電平信號。如圖3所示,

圖3. I2C協議時序圖

  • 起始條件:SCL高電平期間,SDA由高電平切換到低電平。
  • 停止條件:SCL高電平期間,SDA由低電平切換到高電平。

處於從模式的I2C接口可以識別自身地址(7-bit或10-bit)和廣播呼叫地址。其中,廣播地址檢測功能是可選功能,可由軟件啟用或關閉。

數據和地址都是以8-bit、MSB優先格式傳送。起始條件後的第1或2個字節為(從機)地址信息(7-bit地址用1字節,10-bit地址用2字節)。地址始終由主模式發送,從機收到地址後與自己的地址進行比對,若匹配則進行應答。

每個字節需要8個時鐘脈沖來傳輸數據位,外加1個確認脈沖。在第9個脈沖期間,接收器必須向發送器回送應答位(ACK,acknowledgment,把SDA拉低)。

2.3 I2C從模式

I2C默認工作於從模式,要切換到主模式,需要主動產生一個起始條件。為了產生正確的時序,程序中必須通過配置I2C_CR2寄存器來設定I2C的輸入時鐘。輸入時鐘頻率要求如下:

  • 標準模式,不低於2MHz
  • 快速模式,不低於4MHz

檢測到起始條件後,I2C立即開始從SDA線上接收地址並送入移位寄存器(參見圖2)。然後將之與自身地址OAR1和OAR2(若ENDUAL=1)或廣播呼叫地址(若ENGC=1)進行比對。地址為10-bit模式時,會對地址頭(11110xx0)一起進行比對,其中xx是地址的兩個最高有效位(其餘8位從地址單獨占1個字節)。比較後可能的結果如下:

  • 地址頭或地址不匹配:I2C接口忽略該地址並等待下一個起始條件。
  • 地址頭匹配(10-bit模式):如果ACK=1,I2C接口會產生ACK脈沖並等待8位從地址。
  • 地址匹配:I2C接口執行如下步驟:
  • 若ACK=1,產生一個應答脈沖
  • 硬件置ADDR=1(address matched),如果ITEVFEN=1,會產生中斷
  • 如果ENDUAL=1,軟件必須讀DUALF位,來檢查應答的從地址

10-bit模式下,接收到地址序列後,從機會一直處於接收器模式。隻有在收到地址位匹配且末位為1的地址頭(11110xx1)後,再次收到起始條件才會進入發送器模式。TRA位用來指示從機當前是否處於發送器模式。以下是不同從模式下的工作時序:

1. 從發送器模式(TRA=1)

圖4. 從發送器工作流程示意圖

從發送器工作流程示意圖如圖4所示。收到起始條件後,先接收地址。接收到地址並清除ADDR位後,從機經內部的移位寄存器,將數據從DR寄存器送到SDA線上。在待發送數據載入DR和ADDR位被清除之前,從機會將SCL時鐘信號引腳拉低(對應圖4中的EV1和EV3事件,事件變化和清除方法見圖下方),這會迫使主機進入等待狀態。從機準備好以後,釋放SCL(恢復高電平),數據開始傳輸。每次傳輸可以發送的字節數不受限制,但發送到SDA線上的數據必須為8bit(即1字節),每個字節後必須跟一個應答位

每個字節發送完畢,收到應答脈沖後,通過軟件將TxE(Tx data register Empty)位置1。如果設置了ITEVFEN和ITBUFEN位,此時會產生中斷。

如果TxE被置1,在下一個數據發送結束前,沒有新數據寫入到I2C_DR寄存器,BTF(Byte Transfer Finished)位會被置1。在清除BTF位之前,SCL保持低電平。

要清除BTF位需要讀一次I2C_SR1,然後寫一次I2C_DR。

2. 從接收器(TRA=0)

從接收器工作流程示意圖如圖5所示。

圖5. 從接收器工作流程示意圖

在接收到地址並清除ADDR後,從接收器通過內部移位寄存器將從SDA線接收到的字節存入DR寄存器。接收所有字節後,I2C會執行如下步驟:

  • 如果ACK=1,發回一個應答脈沖
  • RXNE位被硬件置1,如果使能了事件中斷使能位ITEVFEN和緩存中斷使能位ITBUFEN,會產生中斷。

如果RXNE被置1,在下一個數據接收完成前,DR寄存器未被讀取,BTF位會被置1。在清除BTF位之前,SCL保持低電平。清除BTF的步驟同前。

3. 關閉從機

傳輸完最後一個字節後,主設備產生一個停止狀態,I2C檢測到這一狀態時:

  • 設置STOPF=1,如果事件中斷使能位ITEVFEN=1,則會產生中斷。

要清除STOPF位需要讀一次SR1寄存器,然後寫一次CR1寄存器。

2.4 I2C主模式

I2C處於主模式時,負責發起數據傳輸並產生時鐘信號。數據的串行傳輸總是以起始條件開始,以停止條件結束。通過設置I2C_CR1寄存器中的START=1,在總線上產生一個起始條件,I2C接口即可進入主模式。以下是進入主模式的一些必要操作步驟:

  • 配置I2C_CR2寄存器的FREQ[5:0]位,以產生正確的時序。輸入時鐘頻率必須滿足:SM模式下,不小於2MHz;Fm模式下,不小於4MHz
  • 配置I2C_CCR寄存器,設置時鐘模式、占空比、速度
  • 配置上升時間寄存器I2C_TRISE
  • 設置I2C_CR1寄存器的PE位,使能I2C
  • 設置I2C_CR1寄存器的START位,產生起始條件

主模式也可以分別工作於發送器和接收器狀態。時序圖分別如圖6和圖7所示。

圖6. 主發送器工作流程示意圖

圖7. 主接收器工作流程示意圖

1. 產生SCL主時鐘

SCL時鐘通過I2C_CCR寄存器進行配置:F/S位選擇I2C的速度模式;DUTY位設置占空比;CCR[11:0]位設置預分頻系數,通過對PCLK1進行分頻來得到SCL時鐘高/低電平的持續時長(分別以上升沿和下降沿作為參考起點)。

由於從機可能會拉低SCL線,主機在產生上升沿後,會延遲TRISE位中設置的時間,再去檢查來自總線上的SCL輸入。根據檢查結果:

  • 如果SCL線為低電平,表明從機正在拉低總線,高電平計數器會停止,直至SCL線上檢測到高電平。這種機制可以確保SCL時鐘參數具有最小的HIGH周期。
  • 如果SCL線為高電平,高電平計數器保持計數。

即使沒有從機拉低時鐘線,從主機產生SCL上升沿,到其檢測到SCL上出現上升沿,這個反饋過程也需要一定的時間。這個反饋時長與如下因素有關:SCL上升時間(影響SCL VIH數據檢測),噪聲過濾器帶來的時延,內部SCL輸入與APB時鐘的同步造成的時延。反饋回路所需的最大時延量可以在TRISE位進行設置(主機保持上升沿等待的時間),這樣無論SCL上升時間多長,都可以保持SCL頻率的穩定。

2. 起始條件

當BUSY=0時,設置I2C_CR1寄存器中的START=1,I2C接口會產生一個起始條件,並切換到主模式(MSL位被置1)。如果I2C已經處於主模式,設置START=1會使其在當前字節傳輸完成後,產生一個重開始條件(Restart condition)。

發出起始條件後,硬件會設置SB=1(起始位),如果ITEVFEN=1,則會產生中斷。然後,主機開始等待一個讀SR1寄存器、接著將從機地址寫入DR寄存器的動作。這兩個連續動作會同時清除SB位(參加圖6和圖7中的EV5事件)。

3. 從地址發送

從機地址被載入DR寄存器後,會被內部的移位寄存器發送到SDA線上。

(1) 10-bit地址模式,發送地址頭序列會引發如下事件:

  • ADD10位被置1,如果設置了ITEVFEN=1,則會產生中斷。然後,主機開始等待一個讀SR1寄存器、接著將第2個地址字節寫入DR寄存器的動作(圖6和圖7中的EV9)。
  • 硬件設置ADDR=1,如果設置了ITEVFEN=1,則會產生中斷。然後,主機開始等待一個讀SR1寄存器、接著讀SR2的動作(圖6/7中的EV6)。

(2) 7-bit地址模式,唯一的地址字節被發送。地址發送後,

  • 硬件設置ADDR=1,如果設置了ITEVFEN=1,則會產生中斷。然後,主機開始等待一個讀SR1寄存器、接著讀SR2的動作(圖6/7中的EV6)。

主機根據所發送從地址的最低位,決定進入發送器模式還是接收器模式。

(1) 7-bit地址模式下,如果

  • 主機發送的從地址最低位為0,則進入發送器模式。
  • 主機發送的從地址最低位為1,則進入接收器模式。

(2) 10-bit地址模式下,如果

  • 主機依次發送:地址頭11110xx0 ,從地址,則進入發送器模式。
  • 主機依次發送:地址頭11110xx0,從地址,重復起始條件,地址頭11110xx1,則進入接收器模式。

TRA位指示主設備所處狀態:1-發送器模式;0-接收器模式。

4. 主發送器

在發送完地址並清除ADDR位以後,主機通過內部的移位寄存器按字節將數據發送到SDA線上。主機等待第一個數據被寫入I2C_DR(圖6中的EV8_1)。當收到應答脈沖時,TXE位被硬件置1,如果設置了ITEVFEN和ITBUFEN位,則會產生中斷。

如果TxE=1且在上一個數據傳輸完成之前沒有新數據字節寫入DR寄存器,則硬件將BTF(Byte transfer finished)置1。I2C接口將SCL拉低,直至BTF位被清除(讀I2C_SR1,然後寫I2C_DR)。

5. 關閉通信

將最後1個字節寫入DR寄存器後,軟件設置STOP=1,產生一個停止條件(圖6中的EV8_2)。I2C接口自動回到從模式(MSL=0)。註意,應該在EV8_2期間,當TXE=1或BTF=1時,產生停止條件。

6. 主接收器

在發送完地址並清除ADDR位以後,I2C接口進入主發送器模式。在該模式下,I2C接口通過內部的移位寄存器從SAD線上接收字節,並將其存入DR寄存器。接收每個字節後,I2C執行如下步驟:

  • 如果ACK=1,發回應答脈沖。
  • 設置RXNE=1,如果設置了ITEVFEN和ITBUFEN,則產生中斷。

如果RXNE=1且在上一個數據接收完成之前DR寄存器未被讀取,則硬件將BTF置1。I2C接口將SCL拉低,直至BTF位被清除(讀I2C_SR1,然後寫I2C_DR)。

7. 關閉通信

(1)方法1:適用於I2C開啟中斷且中斷優先級最高的情況

主機收到從機發送的最後一個字節後,發送NACK(Non-acknowledge)。從機收到NACK後,釋放SCL和SDA線,使得主機能夠發送停止/重啟條件。

  • 為了在收到最後一個字節後產生NACK脈沖,在讀取倒數第二個字節(倒數第二個RxNe事件後)後必須清除ACK位。
  • 為了產生停止/重啟條件,在讀取倒數第二個字節後軟件必須將STOP/START置1。
  • 隻接收1個字節時,在EV6之後(EV6_1,ADDR剛被清除後)要關閉應對和產生停止條件。

產生停止條件後,I2C接口自動回到默認的從模式(MSL位被清除)。

(2)方法2:適用於I2C開啟中斷,但中斷優先級不是最高,或者I2C以輪詢方式工作的情況

此方法的時序示意圖如圖8所示。DR寄存器收到DataN-2後不讀取,這樣在DataN-1被接收進移位寄存器後,通信被掛起(RxNE和BTF同時被置1)。EV7_2期間完成如下操作:在讀取DR中的DataN-2之前,先清除ACK位,這樣才能確保在DataN的應答脈沖之前ACK=0。讀取DataN-2後,馬上設置STOP/START位並讀取DataN-1。待RxNE被置位後,再讀取DataN。

圖8. 主接收器關閉通信方法2時序圖(N>2)

在剩3個待讀取數據時,後續流程如下:

  • RXNE=1,無動作(DataN-2存在DR,不讀)
  • DataN-1被接收(存在移位寄存器中)
  • 因為DR和移位寄存器均非空,所以BTF=1。SCL被拉低,禁止總線上新數據的接收
  • ACK=0
  • 讀DR中的DataN-2。DataN-1被移入DR,騰出移位寄存器準備接收DataN
  • 收到DataN和一個NACK
  • 設置START/STOP位
  • 讀DataN-1
  • RxNE=1
  • 讀DataN

以上是N>2的情況,如果隻接收1個或2個數據時,要按如下方法進行特殊處理:

N=1的情況:

  • 在ADDR時間中,清除ACK
  • 清除ADDR
  • 設置START/STOP位
  • 待RXNE=1後,讀最後一個字節

上述過程時序如圖9所示。

圖 9. 主接收器關閉通信方法2時序圖(N=1)

N=2的情況:

  • 將POS(Acknowledge Position)和ACK置1
  • 等待ADDR被置1
  • 清除ADDR
  • 清除ACK
  • 等待BTF被置1
  • 設置STOP
  • 讀DR寄存器兩次

上述過程時序如圖10所示。

圖10. 主接收器關閉通信方法2時序圖(N=2)

2.5 錯誤處理

以下是幾種可能會導致通信失敗的錯誤:

1. 總線錯誤(BERR)

在數據或地址傳輸期間,當I2C接口檢測到外部Stop或Start條件時,會出現這種錯誤。這種情況下:

  • BERR位被置1,如果設置了ITERREN,會產生中斷。
  • 在從模式下,數據被丟棄,通信連線被硬件釋放。如果是誤啟動,從機將之視為重啟並等待地址或Stop條件;如果是誤停止,從機將之視為Stop條件,通信線路被硬件釋放。
  • 在主模式下:通信連線不會被硬件釋放,當前傳輸狀態不受影響,是否終止當前傳輸交由軟件決定。

2. 應答失敗(AF)

當I2C接口檢測到“無應答”位時,會出現這種錯誤。這種情況下:

  • AF位被置1,如果設置了ITERREN位,會產生中斷。
  • 收到NACK時,發送器必須將通信復位。若為從機,通信線路被硬件釋放;若為主機,軟件必須生成一個停止或重復起始條件。

3. 仲裁丟失(ARLO)

當I2C接口檢測到仲裁丟失情況時,會出現這種錯誤。這種情況下:

  • ARLO位被置1,如果設置了ITERREN位,會產生中斷。
  • I2C接口自動回到從模式(MSL位被清除)。丟失仲裁後,I2C無法在同一傳輸中響應它的從地址。在贏得總線的主機發送重復的起始條件後才會恢復響應。
  • 通信線路被硬件釋放。

4. 過載/欠載錯誤(OVR/UDR)

過載錯誤OVR是指,I2C接收到下一字節時,DR中已接收的字節未被讀取。在從模式下,當時鐘延長被禁止且I2C正在接收數據時,可能會出現這種錯誤。此時,

  • DR中上一次接收的數據因被覆蓋而丟失。
  • 如果出現OVR,軟件應該清除RXNE位,發送器應重新發送上一個字節。

欠載錯誤UDR是指,下一字節的時鐘到來前,I2C接口沒有將下一字節更新到DR寄存器,TxE仍等於1。在從模式下,當時鐘延長被禁止且I2C正在發送數據時,可能會出現這種錯誤。此時,

  • DR中的同一字節會被再次發送。
  • 用戶應該在接收端確定UDR期間重復發送的字節並將之丟棄。發送端會在I2C總線標準規定的時鐘低電平期間寫入下一個字節。

至於第一個待發送字節,則必須在ADDR被清除之後且第一個SCL上升沿到來前寫入DR寄存器。如果做不到這一點,接收器必須丟棄第一個數據。

2.6 SDA/SCL線控制

1. 如果使能了時鐘延長

  • 發送器模式:若TxE=1且BTF=1,傳輸前I2C接口會保持時鐘線處於低電平,等待微處理器讀SR1後將數據寫入DR(緩存和移位寄存器均為空)。
  • 接收器模式:若RxNE=1且BTF=1,接收到數據後I2C接口會保持時鐘線處於低電平,等待微處理器讀SR1後讀取DR中的數據(緩存和移位寄存器均為空)。

2. 如果在從模式禁用了時鐘延長

  • 在下一字節被接收前,如果RxNE=1且DR未被讀取,會出現過載錯誤。上一字節丟失。
  • 在下一字節被發送前,如果TxE=1且DR未被寫入,會出現欠載錯誤。同一字節會被再次發送。
  • 寫沖突不受管理。

2.7 系統管理總線SMBus

最簡單的I2C通信隻需1條線數據線SDA和1條時鐘線SCL。從圖2可以看出,I2C模塊通常還有一個SMBA引腳,這個引腳是用來實現SMBus(系統管理總線)接口的。SMBus接口是一個雙線接口,通過它,各種設備相互之間、以及設備與系統其他部分之間可以通信。SMBus為系統和電源管理相關任務提供一條控制總線。系統可以使用SMBus在設備之間傳遞消息,而不必切換控制線。

系統管理總線標準涉及三類設備,

  • 從設備slave,即接收或響應指令的設備。
  • 主設備master,即發起命令、產生時鐘和終止傳輸的設備。
  • 服務機host,即提供與系統CPU主接口的特定主設備。服務機必須同時局部master和slave功能,並且必須支持SMBus提醒協議。一個系統中,隻允許有一個服務機。

1. SMBus與I2C的相似之處

  • 2線總線協議(1時鐘線,1數據線) 可選的SMBus提醒線
  • 主-從通信,主機提供時鐘
  • 多主機功能
  • SMBus數據格式與I2C 7-bit地址格式相似(見圖4)

2. SMBus與I2C的不同之處

二者區別見下表:

SMBus

I2C

最高速度100kHz

最高速度400kHz

最低時鐘速度10kHz

35ms時鐘低超時

邏輯電平固定

邏輯電平由VDD決定

多種地址類型(保留的、動態的等)

7-bit,10-bit和廣播呼叫從地址類型

多種總線協議(快速命令、處理呼叫等)

無總線協議

3. SMBus在應用中的主要用途

利用SMBus,設備可以提供制造商信息,告訴系統其型號/序列號,為暫停事件保存狀態,報告不同類型的錯誤,接收控制參數,返回自身狀態。SMBus為系統和電源管理相關的任務提供了一個控制總線。

4. 設備識別

SMBus總線上作為從機的每個設備都有一個唯一的地址,稱為從地址。SMBus規范中預留了一些地址,詳情請到http://smbus.org/specs下載並查閱最新的規范(V3.1 @2022)。

5. 總線協議

SMBus技術規范支持多達9個總線協議。詳情請查閱前述SMBus規范。這些協議需要由用戶在軟件來實現。

6. 地址解析協議(ARP)

為了解決SMBus從地址沖突問題,可以動態分配新的唯一地址給每個從設備。地址解析協議(Address Resolution Protocal,ARP)就是為這一目的服務的。ARP具有如下特性:

  • 使用標準SMBus物理層仲裁機制進行地址分配。
  • 設備保持供電期間,分配的地址不變;也可以設備斷電後保留其地址。
  • 分配地址後,無額外的SMBus打包開銷。也就是說,後續訪問分配地址的從機與訪問固定地址設備的開銷是一樣的。
  • 每個SMBus主設備都可以遍歷總線。

7. 唯一設備標識符(UDID)

UDID(Unique device identifier)是一種用來區分各個器件的機制,即為每個設備必須要有一個唯一的標識符,這樣才便於分配地址。

關於在ARP上128-bitUDID的詳細形象,請查閱前述SMBus規范。

8. SMBus提醒模式

SMBus是一個帶中斷線的可選信號,適用於希望用主控能力換取一個引腳的設備。SMBALERT和SCL、SDA信號一樣,是一種“線與”信號。SMBA要與SMBus廣播呼叫地址一起使用。使用SMBus調用的消息長度為兩字節。

一個隻具備從功能的設備,可以通過設置I2C_CR1寄存器中的ALERT位,經SMBA示意服務機它需要通信。服務機在處理該中斷的同時,會通過Alert Response Address(ARA,值介於0001-100X之間)訪問所有SMBA設備,但隻有拉低SMBA的設備才會回應ARA。這種狀態有I2C_SR1寄存器的SMBALERT標志位來標識。服務機執行一個修改接收字節的操作。從發送設備提供的7位地址被置於該字節的7個最高位。第8位可以為0或1。

如果拉低SMBA的設備不止一個,具有最高優先級(最小地址)的設備,將會在從地址傳輸期間,通過標準仲裁贏得通信權利。在確認從地址後,此設備必須釋放SMBA拉低。當信息傳輸完成後,如果服務器仍看到有SMBA低,它會再次去讀ARA。

沒有執行SMBA信號的服務機,會周期性的訪問ARA。關於SMBus提醒模式的更多詳情,請查閱前述SMBus規范。

9. 超時錯誤

I2C和SMBus的時序標準有許多不同。SMBus定義了一個時鐘低超時TIMEOUT,最大值為35ms。它包括兩部分,其中TLOW:SEXT為從設備累積時鐘低持續時間(25ms),TLOW:MEXT為主設備累積時鐘低持續時間(10ms)。關於超時相關的更多詳情,請查閱前述SMBus規范。

發生TIMEOUT或TLOW錯誤時,I2C_SR1寄存器中的TIMEOUT位會被置1。

10. 如何啟用SMBus模式

要將I2C模式切換到SMBus模式,需要執行如下步驟:

  • 設置I2C_CR1中的SMBUS=1
  • 按應用要求,配置I2C_CR1寄存器中的SMBTYPE(設備/服務機)和ENARP位
  • SMBus模式下,將設備設為主/從機的方法與I2C模式下的方法一致。參見前述15.3.3或15.3.4小節。

2.8 DMA請求

STM32的I2C支持DMA。DMA請求使能後,僅用於數據傳輸。發送時DR寄存器已空或接收時DR寄存器非空,均會產生DMA請求。I2C傳輸數據前,必須先完成DMA初始化化和使能。通常在ADDR事件(地址發送或成功接收)前,必須將I2C_CR2中的DMAEN位置1。在使能了時鐘拉伸的主/從模式中,也可以在ADDR事件期間(清除ADDR位前)設置DMAEN=1。DMA請求必須在當前字節傳輸結束前送達。在達到了為相應DMA通道設置的數據傳輸數量時,DMA控制器向I2C接口發送結束傳輸信號EOT(End of Transfer),如果TCIE=1(DMA_CCRx寄存器)則會產生一個傳輸完成中斷:

  • 主發送器:在EOT中斷後的中斷服務程序中,關閉DMA請求,等待BTF事件,最後設置停止條件。
  • 主接收器:剩餘待接收字節數≥2時,DMA控制器發送一個硬件信號EOT_1(對應於倒數第2個數據字節)。如果I2C_CR2寄存器中的LAST=1,在EOT_1後I2C自動發送一個NACK。開啟中斷的情況下,用戶可以在DMA傳輸完成中斷中產生一個停止條件。

1. 用DMA發送

將I2C_CR2寄存器中的DMAEN位置1,即可使能DMA模式來進行發送。每次TxE被置1時,數據都會從配置DMA時指定的內存加載到DR寄存器。按如下步驟將DMA通道x映射到I2C發送:

  • 在DMA_CPARx寄存器中,寫入I2C_DR寄存器的地址。每次發生TxE事件後,數據將從內存移入此地址。
  • 在DMA_CMARx寄存器中,寫入存儲數據的內存地址。每次發生TxE事件後,數據將由此加載到DR。
  • 在DMA_CNDTRx寄存器中,設置傳輸的總字節數。每次發生TxE事件後,此值會遞減。
  • 在DMA_CCRx寄存器中,通過PL[1:0]位設置DMA通道優先級。
  • 在DMA_CCRx寄存器中,設置DIR=1(內存到外設),根據需要設置TCIE或HTIE位開啟傳輸完成或半傳輸中斷。
  • 在DMA_CCRx寄存器中,設置EN=1,激活DMA通道。

當達到了所設定的數據數量時,DMA控制器發送EOT/EOT_1信號給I2C接口。如果在DMA通道中斷向量上使能了中斷,此時會產生相應的中斷。

采用DMA發送時,不要使能I2C_CR2寄存器中的ITBUFEN位。因為這個位會開啟TxE中斷,DMA傳輸時完全沒有必要。

2. 用DMA接收

使用DMA模式進行接收的方法與上述用DMA來發送的方法類似,隻是DMA工作時存、讀數據的方向反向而已。每次接收到數據,DMA都會將其從DR加載到配置DMA時指定的內存中。按如下步驟將DMA通道x映射到I2C接收:

  • 在DMA_CPARx寄存器中,寫入I2C_DR寄存器的地址。每次發生RxNE事件後,數據將由此被移動到內存。
  • 在DMA_CMARx寄存器中,寫入存儲數據的內存地址。每次發生RxNE事件後,數據將由此DR加載到此內存。
  • 在DMA_CNDTRx寄存器中,設置傳輸的總字節數。每次發生RxNE事件後,此值會遞減。
  • 在DMA_CCRx寄存器中,通過PL[1:0]位設置DMA通道優先級。
  • 在DMA_CCRx寄存器中,設置DIR=0(外設到內存),根據需要設置TCIE或HTIE位開啟傳輸完成或半傳輸中斷。
  • 在DMA_CCRx寄存器中,設置EN=1,激活DMA通道。

當達到了所設定的數據數量時,DMA控制器發送EOT/EOT_1信號給I2C接口。如果在DMA通道中斷向量上使能了中斷,此時會產生相應的中斷。

2.9 數據包錯誤檢查

為了提高通信的可靠性,I2C中設置了一個PEC計算器。使用CRC-8多項式C(x)=x8 x2 x 1對每個數據位串行計算來得到PEC:

使能PEC計算:設置I2C_CR1寄存器中的ENPEC=1。PEC使用CRC-8多項式對所有信息字節(包括地址和R/W位)進行計算。

  • 發送時:在最後一個字節的TxE事件後,設置PEC=1。這樣,最後一個字節發送完成後,PEC會被發送出去。
  • 接收時:在最後一個字節的RxNE事件後,設置PEC=1。這樣,接收器將會把下一個收到的字節與內部計算出的PEC進行比較。如果不相等,接收器會發回一個NACK。如果是主接收器,無論校對結果如何,PEC後都必須發送一個NACK。必須在接收當前字節的ACK脈沖之前將PEC置1。

在I2C_SR1寄存器中還有一個PECERR標志位,用來標識是否出現了PEC錯誤。如果同時開啟了PEC和DMA:

  • 發送時:當I2C接口收到來自DMA控制器的EOT信號時,它自動在最後一個字節後發送PEC。
  • 接收時:當I2C接口收到來自DMA控制器的EOT_1信號時,它自動將下一個字節當作PEC並對其進行校對。收到PEC後會產生一個DMA請求。

為了在最後一個字節後允許發送PEC,I2C_CR2寄存器中有一個控制位LAST,用來判斷當前是否是最一次DMA傳輸。如果是主發送器的最後一次DMA請求,在收到最後一個字節後會自動發送NACK。

仲裁丟失時PEC計算被破壞。

2.10 I2C的中斷

I2C用三個中斷使能位來管理中斷事件。相關中斷事件、標志位和中斷使能位如下表所示:

中斷事件

事件標志位

中斷使能位

Start bit sent (Master)

SB

ITEVFEN

Address sent (Master) or Address matched (Slave)

ADDR

10-bit header sent (Master)

ADD10

Stop received (Slave)

STOPF

Data byte transfer finished

BTF

Receive buffer not empty

RxNE

ITEVFEN & ITBUFEN

Bus error

BERR

ITERREN

Arbitration loss (Master)

ARLO

Acknowledge failure

AF

Overrun/Underrun

OVR

PEC error

PECERR

Timeout/Tlow error

TIMEOUT

SMBus Alert

SMBALERT

ITEVFEN和ITERREN分別占一條中斷線,同一條線上的不同事件是邏輯“或”的關系。如圖11所示。

圖11. I2C中斷線映射關系示意圖

三、I2C寄存器

STM32F103ZET6中與I2C相關的寄存器共有9個,地址映射與復位值表如圖1所示。這些寄存器必須按按半字(16 bits)或全字(32 bits)訪問。

3.1 I2C控制寄存器1 (I2C_CR1)

位置

名稱

功能說明

15

SWRST

Software reset

0: I2C模塊不處於復位狀態

1: I2C模塊處於復位狀態

在復位該位前確保I2C的引腳被釋放,總線是空的。

註:該位看用於錯誤或鎖定狀態後重新初始化I2C。例如由於總線故障而導致BUSY=1且被鎖定,可用此位來退出。

13

ALERT

SMBus alert

0:釋放SMBA引腳。提醒響應地址頭緊跟在NACK信號後面;

1:拉低SMBA引腳。提醒響應地址頭緊跟在ACK信號後面。

軟件可以設置或清除該位;當PE=0時,由硬件清除。

12

PEC

Packet error checking

0:不傳輸PEC

1:傳輸PEC(在發送或接收模式)

軟件可以設置或清除該位;當傳送PEC後,或起始或停止條件時,或當PE=0時硬件將其清除。

註: 仲裁丟失時, PEC的計算失效。

11

POS

Acknowledge/PEC Position for Reception

0:ACK控制當前移位寄存器內正接收字節的(N)ACK。 PEC表明移位寄存器內的字節是PEC;

1: ACK控制下一個字節的(N)ACK。PEC表明下一個字節是PEC。

軟件可以設置或清除該位,或當PE=0時,由硬件清除。

註: POS位隻能用在2字節的接收配置中,必須在接收數據之前配置。為了NACK第2個字節,必須在清除ADDR為之後清除ACK位。為了檢測第2個字節的PEC,必須在配置了POS位之後,拉伸ADDR事件時設置PEC位。

10

ACK

Acknowledge enable

0:無應答返回

1:接收一個字節後返回應答(匹配的地址或數據)

該位有軟件設置和清除。當PE=0時,由硬件清除。

9

STOP

Stop generation

主模式下:

0:無停止條件產生

1:在當前字節傳輸或在當前起始條件發出後產生停止條件。

從模式下:

0:無停止條件產生

1:在當前字節傳輸或釋放SCL和SDA線。

軟件可以設置或清除該位;或當檢測到停止條件時,由硬件清除;當檢測到超時錯誤時,硬件將其置位。

8

START

Start generation

主模式:

0: 無起始條件產生

1:重復產生起始條件

從模式:

0:無起始條件產生

1:當總線空閑時,產生起始條件

該位可由軟件設置或清除,或當起始條件發出後或PE=0時,由硬件清除。

7

NOSTRETCH

Clock stretching disable

0:允許時鐘延長

1:禁止時鐘延長

該位用於當ADDR或BTF標志被置位,在從模式下禁止時鐘延,直到它被軟件復位。

6

ENGC

General call enable

0:禁用廣播呼叫。對地址00h無應答

1:啟用廣播呼叫。對地址00h進行應答

5

ENPEC

PEC enable

0:禁止PEC計算;

1:開啟PEC計算。

4

ENARP

ARP enable

0:禁止ARP

1:使能ARP

如果SMBTYPE=0,使用SMBus設備的默認地址。

如果SMBTYPE=1,使用SMBus的主地址。

2

SMBTYPE

SMBus type

0:SMBus設備

1:SMBus服務機

1

SMBUS

SMBus mode

0:I2C模式

1:SMBus模式

0

PE

Peripheral enable

0:禁用I2C模塊

1:啟用I2C模塊

註: 如果清除該位時通訊正在進行,在當前通訊結束後, I2C模塊被禁用並返回空閑狀態。

由於在通訊結束後發生PE=0,所有的位被清除。

在主模式下,通訊結束之前,絕不能清除該位。

3.2 I2C控制寄存器2 (I2C_CR2)

位置

名稱

功能說明

12

LAST

DMA last transfer

0:下一次DMA的EOT不是最後的傳輸

1:下一次DMA的EOT是最後的傳輸

註:該位在主接收模式使用,使得在最後一次接收數據時可以產生一個NACK。

11

DMAEN

DMA requests enable

0:禁止DMA請求

1:當TxE=1或RxNE =1時,允許DMA請求

10

ITBUFEN

Buffer interrupt enable

0:當TxE=1或RxNE=1時,不產生任何中斷

1:當TxE=1或RxNE=1時,產生事件中斷(不管DMAEN是何種狀態)

9

ITEVTEN

Event interrupt enable

0:禁止事件中斷

1:允許事件中斷

在下列條件下,將產生該中斷:

SB=1 (主);ADDR=1 (主/從)

ADD10=1 (主);STOPF=1 (從)

BTF=1,但無TxE或RxNE事件;

如果ITBUFEN=1,TxE事件為1;

如果ITBUFEN=1,RxNE事件為1

8

ITERREN

Error interrupt enable

0:禁止出錯中斷;

1:允許出錯中斷。

在下列條件下,將產生該中斷:

– BERR = 1;

– ARLO = 1;

– AF = 1;

– OVR = 1;

– PECERR = 1;

– TIMEOUT = 1;

– SMBAlert = 1。

5:0

FREQ

Peripheral clock frequenc

0b000000-不允許

0b000001-不允許

0b000010-2MHz

...

0b110010-50MHz

>0b101010-不允許

I2C1&2掛載與APB1總線,該位必須參考APB1時鐘頻率配置。I2C基於該字段生成符合I2C規范的時鐘。最小頻率為2MHz,最大頻率受APB頻率限制且不能超過50MHz(I2C最高本征頻率).

3.3 I2C地址寄存器1(I2C_OAR1)

位置

名稱

功能說明

15

ADDMODE

Addressing mode (slave mode)

0:7位從地址(不響應10位地址)

1:10位從地址(不響應7位地址)

14:10

保留

必須保持1

9:8

ADD[9:8]

Interface address

7位地址模式時不用關心。

10位地址模式時為地址的9~8位。

7:1

ADD[7:1]

Interface address

地址的7~1位

0

ADD0

Interface address

7位地址模式時不用關心。

10位地址模式時為地址第0位。

3.4 I2C地址寄存器2 (I2C_OAR2)

位置

名稱

功能說明

7:0

ADD2[7:0]

Interface address

在雙地址模式下地址的7~1位。

3.5 I2C數據寄存器(I2C_DR)

位置

名稱

功能說明

7:0

ADD2[7:0]

8-bit data register

從總線收到或待發送的字節

發送器模式:當寫一個字節至DR時,自動啟動數據傳輸。一旦傳輸開始(TxE=1),如果能及時把下一個待傳輸的數據寫入DR, I2C模塊將保持連續的數據流。

接收器模式:接收到的字節被拷貝到DR(RxNE=1)。如果能在接收到下一個字節(RxNE=1)之前讀取DR,即可實現連續的數據傳送。

註:在從模式下,地址不會被拷貝進數據寄存器DR;硬件不管理寫沖突(如果TxE=0,仍能寫入DR);如果在處理ACK脈沖時發生ARLO事件,接收到的字節不會被拷貝入DR,因此不能讀取。

3.6 I2C狀態寄存器1 (I2C_SR1)

位置

名稱

功能說明

15

SMBALERT

SMBus alert

在SMBus主機模式下:

0:無SMBus提醒;

1:在引腳上產生SMBAlert提醒事件。

在SMBus從機模式下:

0:沒有SMBAlert響應地址頭序列;

1:收到SMBAlert響應地址頭序列至SMBAlert變低。

– 該位由軟件寫’0’清除,或在PE=0時由硬件清除

14

TIMEOUT

Timeout or Tlow error

0:無超時錯誤

1:SCL處於低已達到25ms(超時);或者主機低電平累積時鐘擴展時間超過10ms(Tlow:mext);或從設備低電平累積時鐘擴展時間超過25ms(Tlow:sext)。

– 當在從模式下設置該位:從設備復位通訊,硬件釋放總線。

– 當在主模式下設置該位:硬件發出停止條件。

– 該位由軟件寫’0’清除,或在PE=0時由硬件清除。

12

PECERR

PEC Error in reception

0: 無PEC錯誤:接收到PEC後接收器返回ACK(如果ACK=1);

1: 有PEC錯誤:接收到PEC後接收器返回NACK(不管ACK是什麼值)。

– 該位由軟件寫’0’清除,或在PE=0時由硬件清除。

11

OVR

Overrun/Underrun

0: 無過載/欠載;

1: 出現過載/欠載。

– 當NOSTRETCH=1時,在從模式下該位被硬件置位,同時:

– 在接收模式中當收到一個新的字節時(包括ACK應答脈沖),數據寄存器裡的內容還未被讀出,則新接收的字節將丟失。

– 在發送模式中當要發送一個新的字節時,卻沒有新的數據寫入數據寄存器,同樣的字節將被發送兩次。

– 該位由軟件寫’0’清除,或在PE=0時由硬件清除。。

註:如果數據寄存器的寫操作發生時間非常接近SCL的上升沿,發送的數據是不確定的,並發生保持時間錯誤。

10

AF

Acknowledge failure

0:沒有應答失敗;

1:應答失敗。

– 當沒有返回應答時,硬件將置該位為1。

– 該位由軟件寫0清除,或在PE=0時由硬件清除。。

9

ARLO

Arbitration lost (master mode)

0:沒有檢測到仲裁丟失

1:檢測到仲裁丟失

當接口失去對總線的控制給另一個主機時,硬件將該位置1。

該位由軟件寫0清除,或在PE=0時由硬件清除。

在ARLO事件之後,I2C接口自動切換回從模式(M/SL=0)。

註:在SMBus模式下,在從模式下對數據的仲裁僅僅發生在數據階段,或應答傳輸區間(不包括地址的應答)。

8

BERR

Bus error

0:無起始或停止條件出錯

1:起始或停止條件出錯

– 當接口檢測到錯誤的起始或停止條件,硬件將該位置1。

– 該位由軟件寫0清除,或在PE=0時由硬件清除。

7

TxE

Transmitter date register empty

0:DR非空

1:DR已空

發送數據時,DR為空時該位置1;發送地址時不設置該位。

軟件寫數據到DR可清除該位;或在起始或停止條件後,或當PE=0時由硬件清除。

若收到NACK,或要發送的下個字節是PEC(PEC=1),該位不被置位。

註:寫入第1個數據後,或BTF=1時寫入數據,都不能清除TxE,因DR仍為空。

6

RxNE

Receiver data register not empty

0:DR已空

1:DR非空

在接收地址階段,該位不被置位。

軟件對DR的讀寫操作清除該位,或當PE=0時由硬件清除。

在發生ARLO事件時,RxNE不被置位。

註:當設置了BTF時,讀取數據不能清除RxNE位,因為數據寄存器仍然是滿的。

4

STOPF

Stop detection (slave mode)

0:沒有檢測到停止條件

1:檢測到停止條件

在應答之後(如果ACK=1),當從設備在總線上檢測到停止條件時,硬件將該位置1。

軟件讀取SR1寄存器後,接著寫入CR1將清除該位,或當PE=0時,硬件清除。

註:在收到NACK後,STOPF位不被置位。

3

ADD10

10-bit header sent (Master mode)

0:沒有ADD10事件發生;

1:主設備已經將第一個地址字節發送出去。

在10位地址模式下,當主設備已經將第一個字節發送出去時,硬件將該位置1。

軟件讀取SR1寄存器後,將第2個地址寫入DR將清除該位,或當PE=0時,硬件清除該位。

註:收到NACK後,ADD10位不被置位。

2

BTF

Byte transfer finished

0:未結束

1:已結束

當NOSTRETCH=0時,下列情況下硬件將該位置1:

– 接收時,收到新字節(包括ACK脈沖)且DR還未被讀取(RxNE=1)。

– 發送時,待發送數據還未寫入DR(TxE=1)。

– 軟件讀取SR1後,接著對DR讀或寫將清除該位;或在發送起始或停止條件後,或當PE=0時,由硬件清除該位。

註:在收到NACK後,BTF位不會被置位。

1

ADDR

Address sent (master) / matched(slave)

0:地址發送未結束 | 未收到或不匹配

1:地址發送已技術 | 收到的地址匹配

在軟件讀取SR1寄存器後,對SR2寄存器的讀操作將清除該位,或當PE=0時,由硬件清除該位。

註: 在收到NACK後, ADDR位不會被置位。

0

SB

Start bit (Master mode)

0:未發送起始條件

1:起始條件已發送

– 當發送出起始條件時該位被置1。

– 軟件讀取SR1寄存器後,接著寫DR將清除該位,或當PE=0時,硬件清除該位。

3.7 I2C狀態寄存器1 (I2C_SR2)

位置

名稱

功能說明

15:8

PEC[7:0]

SMBus alert

在SMBus主機模式下:

0:無SMBus提醒;

1:在引腳上產生SMBAlert提醒事件。

在SMBus從機模式下:

0:沒有SMBAlert響應地址頭序列;

1:收到SMBAlert響應地址頭序列至SMBAlert變低。

– 該位由軟件寫’0’清除,或在PE=0時由硬件清除

7

DUALF

Dual flag (Slave mode)

0:收到的地址與OAR1匹配

1:收到的地址與OAR2匹配

由硬件復位。復位條件:收到Stop條件或重復的Start條件或PE=0

6

SMBHOST

SMBus host header (Slave mode)

0:未收到SMBus服務機的地址;

1:當SMBTYPE=1且ENARP=1時,收到SMBus服務機地址。

– 在產生停止條件或重復的起始條件時,或PE=0時,硬件將該位清除。

5

SMBDEFAUL

SMBus device default address (Slave)

0:未收到SMBus設備的默認地址;

1:當ENARP=1時,收到SMBus設備的默認地址。

– 在產生一個停止條件或一個重復的起始條件時,或PE=0時,硬件將該位清除。

4

GENCALL

General call address (Slave)

0:未收到廣播呼叫地址;

1:當ENGC=1時,收到廣播呼叫的地址。

– 在產生一個停止條件或一個重復的起始條件時,或PE=0時,硬件將該位清除。

2

TRA

Transmitter/receiver

0:接收器

1:發送器

該位在接收到全地址後,依據地址的R/W為來設置。

在檢測到停止條件(STOPF=1),重復的起始條件,總線仲裁丟失(ARLO=1)或PE=0時,由硬件清除。

1

BUSY

Bus busy

0:在總線上無數據通訊;

1:在總線上正在進行數據通訊。

– 在檢測到SDA或SCl為低電平時,硬件將該位置1;

– 當檢測到一個停止條件時,硬件將該位清除。

該位指示當前正在進行的總線通訊,當接口被禁用(PE=0)時該信息仍然被更新。

0

MSL

Master/slave

0:從模式;

1:主模式。

– 當接口處於主模式(SB=1)時,硬件將該位置位;

– 當總線上檢測到一個停止條件、仲裁丟失(ARLO=1時)、或當PE=0時,硬件清除該位。

3.8 I2C時鐘控制寄存器1 (I2C_CCR)

位置

名稱

功能說明

15

F/S

I2C master speed mode selection

0:標準模式

1:快速模式

14

DUTY

Fm mode duty cycle

0:快速模式下 Tlow/Thigh = 2;

1: 快速模式下Tlow/Thigh = 16/9(見CCR)。

11:0

CCR[11:0]

Clock control register in Fm/Sm mode

CCR[11:0]位設置預分頻系數,通過對PCLK1進行分頻來得到SCL時鐘高/低電平的持續時長(分別以上升沿和下降沿作為參考起點)

3.9 I2C上升事件寄存器1 (I2C_TRISE)

位置

名稱

功能說明

5:0

TRISE

Max rise time in Fm/Sm mode

這些位必須設置為I2C總線規范裡給出的最大的SCL上升時間 1。

例如:標準模式中最大允許SCL上升時間為1000ns。如果在I2C_CR2寄存器中FREQ[5:0]中的值等於0x08且TPCLK1=125ns,故TRISE[5:0]中必須寫入09h(1000ns/125 ns = 8 1)。

濾波器的值也可以加到TRISE[5:0]內。

如果結果不是一個整數,則將整數部分寫入TRISE[5:0]以確保tHIGH參數。

註:隻有當I2C被禁用(PE=0)時,才能設置TRISE[5:0]。

四、HAL庫I2C相關函數

HAL庫中I2C相關的常規庫函數有49個,在stm32f1xx_hal_i2c.h中聲明,stm32f1xx_hal_i2c.c中定義。如果基於STM32CubeIDE編程,大多函數都可以自動生成。隻需適當添加代碼和編寫所需的*Callback即可。僅將函數名稱羅列如下,大多可以從名稱看出功能。

/* Initialization and de-initialization functions******************************/
HAL_I2C_Init();
HAL_I2C_DeInit();
HAL_I2C_MspInit();
HAL_I2C_MspDeInit();
/* IO operation functions  ****************************************************/
/******* Blocking mode: Polling */
HAL_I2C_Master_Transmit();
HAL_I2C_Master_Receive();
HAL_I2C_Slave_Transmit();
HAL_I2C_Slave_Receive();
HAL_I2C_Mem_Write();
HAL_I2C_Mem_Read();
HAL_I2C_IsDeviceReady();
/******* Non-Blocking mode: Interrupt */
HAL_I2C_Master_Transmit_IT();
HAL_I2C_Master_Receive_IT();
HAL_I2C_Slave_Transmit_IT();
HAL_I2C_Slave_Receive_IT();
HAL_I2C_Mem_Write_IT();
HAL_I2C_Mem_Read_IT();
HAL_I2C_Master_Seq_Transmit_IT();
HAL_I2C_Master_Seq_Receive_IT();
HAL_I2C_Slave_Seq_Transmit_IT();
HAL_I2C_Slave_Seq_Receive_IT();
HAL_I2C_EnableListen_IT();
HAL_I2C_DisableListen_IT();
HAL_I2C_Master_Abort_IT();
/******* Non-Blocking mode: DMA */
HAL_I2C_Master_Transmit_DMA();
HAL_I2C_Master_Receive_DMA();
HAL_I2C_Slave_Transmit_DMA();
HAL_I2C_Slave_Receive_DMA();
HAL_I2C_Mem_Write_DMA();
HAL_I2C_Mem_Read_DMA();
HAL_I2C_Master_Seq_Transmit_DMA();
HAL_I2C_Master_Seq_Receive_DMA();
HAL_I2C_Slave_Seq_Transmit_DMA();
HAL_I2C_Slave_Seq_Receive_DMA();
/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */
HAL_I2C_EV_IRQHandler();
HAL_I2C_ER_IRQHandler();
HAL_I2C_MasterTxCpltCallback();
HAL_I2C_MasterRxCpltCallback();
HAL_I2C_SlaveTxCpltCallback();
HAL_I2C_SlaveRxCpltCallback();
HAL_I2C_AddrCallback();
HAL_I2C_ListenCpltCallback();
HAL_I2C_MemTxCpltCallback();
HAL_I2C_MemRxCpltCallback();
HAL_I2C_ErrorCallback();
HAL_I2C_AbortCpltCallback();
/* Peripheral StateMode and Error functions  *********************************/
HAL_I2C_StateTypeDef HAL_I2C_GetState();
HAL_I2C_GetMode();
HAL_I2C_GetError();

#文章首發挑戰賽##精品長文創作季#