目錄
- 一、I2C總線通信協定
-
- 1.1 I2C介紹
- 1.2 I2C實體層
- 1.3、I2C協定層
- 1.4、軟體IIC和硬體IIC
- 1.5 IIC資料傳送
- 1.6 IIC發送資料
- 1.7 IIC讀資料:
- 二、STM32基于I2C協定的溫濕度傳感器的資料采集
-
- 2.1 題目要求:
- 2.2 前期準備
- 2.3代碼撰寫
- 三、準備工作
-
- 1. 溫濕度采集器引腳一覽表
- 2. 硬體線路連接配接
- 四、編譯成功燒錄後上位機顯示
- 總結
一、I2C總線通信協定
1.1 I2C介紹
IIC(Inter-Integrated Circuit)總線是一種由NXP(原PHILIPS)公司開發的兩線式串行總線,用于連接配接微控制器及其外圍裝置。多用于主要制器和從器件間的主從通信,在小資料量場合使用,傳輸距離短,任意時刻隻能有一個主機等特性。
在CPU與被控IC之間、IC與IC之間進行雙向傳送,高速IIC總線一般可達400kbps 以上。
注意IIC是為了與低速裝置通信而發明的,是以IIC的傳輸速率比不上SPI
I²C最重要的功能包括:
隻需要兩條總線;
沒有嚴格的波特率要求,例如使用RS232,主裝置生成總線時鐘;
所有元件之間都存在簡單的主/從關系,連接配接到總線的每個裝置均可通過唯一位址進行軟體尋址;
I²C是真正的多主裝置總線,可提供仲裁和沖突檢測;
傳輸速度;
标準模式:Standard Mode = 100 Kbps
快速模式:Fast Mode = 400 Kbps
高速模式: High speed mode = 3.4 Mbps
超快速模式: Ultra fast mode = 5 Mbps
最大主裝置數:無限制;
最大從機數:理論上是127。
1.2 I2C實體層
I2C 總線在實體連接配接上非常簡單,分别由SDA(串行資料線)和SCL(串行時鐘線)及上拉電阻組成。通信原理是通過對SCL和SDA線高低電平時序的控制,來産生I2C總線協定所需要的信号進行資料的傳遞。在總線空閑狀态時,SCL和SDA被上拉電阻Rp拉高,使SDA和SCL線都保持高電平。
I2C通信方式為半雙工,隻有一根SDA線,同一時間隻可以單向通信,485也為半雙工,SPI和uart通
信為全雙工。
原理圖:
主機和從機的概念:
主機就是負責整個系統的任務協調與配置設定,從機一般是通過接收主機的指令進而完成某些特定的任務,主機和從機之間通過總線連接配接,進行資料通訊。
釋出主要指令的稱為主機,接受指令的稱為從機
1.3、I2C協定層
原理圖:
I2C 總線在傳送資料過程中共有三種類型信号, 它們分别是:開始信号、結束信号和應答信号。
開始信号SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送資料。
結束信号SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送資料。
應答信号接收資料的 IC 在接收到 8bit 資料後,向發送資料的 IC 發出特定的低電平脈沖,表示已收到資料。CPU 向受控單元發出一個信号後,等待受控單元發出一個應答信号,CPU 接收到應答信号後,根據實際情況作出是否繼續傳遞信号的判斷。若未收到應答信号,由判斷為受控單元出現故障。
這些信号中,起始信号是必需的,結束信号和應答信号,都可以不要。
1.4、軟體IIC和硬體IIC
IIC分為軟體IIC和硬體IIC
軟體IIC 軟體IIC通信指的是用單片機的兩個I/O端口模拟出來的IIC,用軟體控制管腳狀态以模拟I2C通信波形,軟體模拟寄存器的工作方式。
直接使用 CPU 核心按照 I2C 協定的要求控制 GPIO 輸出高低電平,進而模拟I2C。
使用: 需要在控制産生 I2C 的起始信号時,控制作為SCL 線的 GPIO 引腳輸出高電平,然後控制作為 SDA 線的 GPIO 引腳在此期間完成由高電平至低電平的切換,最後再控制SCL線切換為低電平,這樣就輸出了一個标準的 I2C 起始信号。
硬體IIC:一塊硬體電路,硬體I2C對應晶片上的I2C外設,有相應I2C驅動電路,其所使用的I2C管腳也是專用的,硬體(固件)I2C是直接調用内部寄存器進行配置。
直接利用 STM32 晶片中的硬體 I2C 外設。
使用: 隻要配置好對應的寄存器,外設就會産生标準序列槽協定的時序。在初始化好 I2C 外設後,隻需要把某寄存器位置 1,此時外設就會控制對應的 SCL 及 SDA 線自動産生 I2C 起始信号,不需要核心直接控制引腳的電平。
硬體I2C的效率要遠高于軟體的,而軟體I2C由于不受管腳限制,接口比較靈活。
要學習更多關于I2C的介紹,可以參考以下兩篇部落格
[1] IIC原理超詳細講解—值得一看
[2] I2C協定靠這16張圖徹底搞懂(超詳細)
1.5 IIC資料傳送
資料傳送格式
SDA線上的資料在SCL時鐘“高”期間必須是穩定的,隻有當SCL線上的時鐘信号為低時,資料線上的“高”或“低”狀态才可以改變。輸出到SDA線上的每個位元組必須是8位,資料傳送時,先傳送最高位(MSB),每一個被傳送的位元組後面都必須跟随一位應答位(即一幀共有9位)。
當一個位元組按資料位從高位到低位的順序傳輸完後,緊接着從裝置将拉低SDA線,回傳給主裝置一個應答位ACK, 此時才認為一個位元組真正的被傳輸完成 ,如果一段時間内沒有收到從機的應答信号,則自動認為從機已正确接收到資料。
多數從裝置的位址為7位或者10位,一般都用七位。
八位裝置位址=7位從機位址+讀/寫位址,
再給位址添加一個方向位位用來表示接下來資料傳輸的方向,
0表示主裝置向從裝置(write)寫資料,
1表示主裝置向從裝置(read)讀資料
IIC的每一幀資料由9bit組成,
如果是發送資料,則包含 8bit資料+1bit ACK,
如果是裝置位址資料,則8bit包含7bit裝置位址 1bit方向
在起始信号後必須傳送一個從機的位址(7位) 1~7位為7位接收器件位址,第8位為讀寫位,用“0”表示主機發送資料(W),“1”表示主機接收資料 (R), 第9位為ACK應答位,緊接着的為第一個資料位元組,然後是一位應答位,後面繼續第2個資料位元組。
1.6 IIC發送資料
Start: IIC開始信号,表示開始傳輸。
DEVICE_ADDRESS:: 從裝置位址,就是7位從機位址
R/W: W(write)為寫,R(read)為讀
ACK: 應答信号
WORD_ADDRESS : 從機中對應的寄存器位址 比方說通路 OLED中的 某個寄存器
DATA: 發送的資料
STOP: 停止信号。結束IIC
主機要向從機寫資料時:
主機首先産生START信号
然後緊跟着發送一個從機位址,這個位址共有7位,緊接着的第8位是資料方 向位(R/W),0表示主機發送資料(寫),1表示主機接收資料(讀)
主機發送位址時,總線上的每個從機都将這7位位址碼與自己的位址進行比較,若相同,則認為自己正在被主機尋址,根據R/T位将自己确定為發送器和接收器
這時候主機等待從機的應答信号(A)
當主機收到應答信号時,發送要通路從機的那個位址, 繼續等待從機的應答信号
當主機收到應答信号時,發送N個位元組的資料,繼續等待從機的N次應答信号,
主機産生停止信号,結束傳送過程。
1.7 IIC讀資料:
主機要從從機讀資料時
主機首先産生START信号
然後緊跟着發送一個從機位址,注意此時該位址的第8位為0,表明是向從機寫指令,
這時候主機等待從機的應答信号(ACK)
當主機收到應答信号時,發送要通路的位址,繼續等待從機的應答信号,
當主機收到應答信号後,主機要改變通信模式(主機将由發送變為接收,從機将由接收變為發送)是以主機重新發送一個開始start信号,然後緊跟着發送一個從機位址,注意此時該位址的第8位為1,表明将主機設 置成接收模式開始讀取資料,
這時候主機等待從機的應答信号,當主機收到應答信号時,就可以接收1個位元組的資料,當接收完成後,主機發送非應答信号,表示不在接收資料
主機進而産生停止信号,結束傳送過程。
二、STM32基于I2C協定的溫濕度傳感器的資料采集
2.1 題目要求:
每隔2秒鐘采集一次溫濕度資料,并通過序列槽發送到上位機。
2.2 前期準備
溫濕度傳感器AHT20
序列槽調試助手
2.3代碼撰寫
可以根據其他公司提供的示例代碼進行修改與代碼添加。(如正點原子或者野火)
相關的AHT20資料大家可以去官網進行檢視與下載下傳: http://www.aosong.com/class-36.html
AHT20晶片的使用過程read_AHT20_once函數:
void read_AHT20_once(void)
{
delay_ms(10);
reset_AHT20();//重置AHT20晶片
delay_ms(10);
init_AHT20();//初始化AHT20晶片
delay_ms(10);
startMeasure_AHT20();//開始測試AHT20晶片
delay_ms(80);
read_AHT20();//讀取AHT20采集的到的資料
delay_ms(5);
}
AHT20晶片讀取資料 read_AHT20函數:
void read_AHT20(void)
{
uint8_t i;
for(i=0; i<6; i++)
{
readByte[i]=0;
}
I2C_Start();//I2C啟動
I2C_WriteByte(0x71);//I2C寫資料
ack_status = Receive_ACK();//收到的應答資訊
readByte[0]= I2C_ReadByte();//I2C讀取資料
Send_ACK();//發送應答資訊
readByte[1]= I2C_ReadByte();
Send_ACK();
readByte[2]= I2C_ReadByte();
Send_ACK();
readByte[3]= I2C_ReadByte();
Send_ACK();
readByte[4]= I2C_ReadByte();
Send_ACK();
readByte[5]= I2C_ReadByte();
SendNot_Ack();
//Send_ACK();
I2C_Stop();//I2C停止函數
//判斷讀取到的第一個位元組是不是0x08,0x08是該晶片讀取流程中規定的,如果讀取過程沒有問題,就對讀到的資料進行相應的處理
if( (readByte[0] & 0x68) == 0x08 )
{
H1 = readByte[1];
H1 = (H1<<8) | readByte[2];
H1 = (H1<<8) | readByte[3];
H1 = H1>>4;
H1 = (H1*1000)/1024/1024;
T1 = readByte[3];
T1 = T1 & 0x0000000F;
T1 = (T1<<8) | readByte[4];
T1 = (T1<<8) | readByte[5];
T1 = (T1*2000)/1024/1024 - 500;
AHT20_OutData[0] = (H1>>8) & 0x000000FF;
AHT20_OutData[1] = H1 & 0x000000FF;
AHT20_OutData[2] = (T1>>8) & 0x000000FF;
AHT20_OutData[3] = T1 & 0x000000FF;
}
else
{
AHT20_OutData[0] = 0xFF;
AHT20_OutData[1] = 0xFF;
AHT20_OutData[2] = 0xFF;
AHT20_OutData[3] = 0xFF;
printf("讀取失敗!!!");
}
printf("\r\n");
//根據AHT20晶片中,溫度和濕度的計算公式,得到最終的結果,通過序列槽顯示
printf("溫度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
printf("濕度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
printf("\r\n");
}
工程一覽:
完整代碼連結:https://pan.baidu.com/s/1JBKmXwn6v3D5zzXOPT-1OA
提取碼:1902
三、準備工作
1. 溫濕度采集器引腳一覽表
2. 硬體線路連接配接
2.1 usb to ttl ----> STM32F103C8T6核心開發闆
3V3 —> 3V3
GND —> GND
RXD —> A9
TXD —> A10
2.2 STM32F103C8T6核心開發闆 ----> 溫濕度采集器
3V3 —> 引腳1
GND —> 引腳3
PB6 —> SCL
PB7 —> SDA
四、編譯成功燒錄後上位機顯示
編譯:
燒錄:
上位機展示
總結
通過這次實驗,了解了I2C總線通信協定以及通過I2C協定實作溫濕度(AHT20)采集的過程分析,
不斷的在失敗的過程中尋找答案,還是完成了本次實驗,收獲很大。
參考
https://blog.csdn.net/as480133937/article/details/105366932
https://blog.csdn.net/qq_53112972/article/details/127589824?spm=1001.2014.3001.5502
https://blog.csdn.net/qq_46467126/article/details/121436790?spm=1001.2014.3001.5502