I2C 簡介
I2C(Inter Integrated Circuit)總線是 PHILIPS 公司開發的一種半雙工、雙向二線制同步串行總線。I2C 總線傳輸數據時只需兩根信號線,一根是雙向數據線 SDA(serial data),另一根是雙向時鐘線 SCL(serial clock)。SPI 總線有兩根線分別用于主從設備之間接收數據和發送數據,而 I2C 總線只使用一根線進行數據收發。
I2C 和 SPI 一樣以主從的方式工作,不同于 SPI 一主多從的結構,它允許同時有多個主設備存在,每個連接到總線上的器件都有唯一的地址,主設備啟動數據傳輸并產生時鐘信號,從設備被主設備尋址,同一時刻只允許有一個主設備。如下圖所示:
I2C 總線主從設備連接方式
如下圖所示為 I2C 總線主要的數據傳輸格式:
I2C 總線數據傳輸格式
當總線空閑時,SDA 和 SCL 都處于高電平狀態,當主機要和某個從機通訊時,會先發送一個開始信號,然后發送從機地址和讀寫控制位,接下來傳輸數據(主機發送或者接收數據),數據傳輸結束時主機會發送結束信號。傳輸的每個字節為8位,高位在前,低位在后。數據傳輸過程中的不同名詞詳解如下所示:
開始條件:SCL 為高電平時,主機將 SDA 拉低,表示數據傳輸即將開始。
從機地址:主機發送的第一個字節為從機地址,高 7 位為地址,最低位為 R/W 讀寫控制位,1 表示讀操作,0 表示寫操作。一般從機地址有 7 位地址模式和 10 位地址模式兩種,如果是 10 位地址模式,第一個字節的頭 7 位 是 11110XX 的組合,其中最后兩位(XX)是 10 位地址的兩個最高位,第二個字節為 10 位從機地址的剩下8位,如下圖所示:
7 位地址和 10 位地址格式
應答信號:每傳輸完成一個字節的數據,接收方就需要回復一個 ACK(acknowledge)。寫數據時由從機發送 ACK,讀數據時由主機發送 ACK。當主機讀到最后一個字節數據時,可發送 NACK(Negative Acknowledgement)然后跟停止條件。
數據:地址幀發送完后可能會發送一些指令,依從機而定,然后開始傳輸數據,由主機或者從機發送,每個數據為 8 位,數據的字節數沒有限制。
重復開始條件:在一次通信過程中,主機可能需要和不同的從機傳輸數據或者需要切換讀寫操作時,主機可以再發送一個開始條件。
停止條件:在 SDA 為低電平時,主機將 SCL 拉高并保持高電平,然后在將 SDA 拉高,表示傳輸結束。
訪問 I2C 總線設備
一般情況下 MCU 的 I2C 器件都是作為主機和從機通訊,在 RT-Thread 中將 I2C 主機虛擬為 I2C總線設備,I2C 從機通過 I2C 設備接口和 I2C 總線通訊,相關接口如下所示:
查找 I2C 總線設備
在使用 I2C 總線設備前需要根據 I2C 總線設備名稱獲取設備句柄,進而才可以操作 I2C 總線設備,查找設備函數如下所示,
1rt_device_trt_device_find(constchar*name);
1#defineAHT10_I2C_BUS_NAME"i2c1"/*傳感器連接的I2C總線設備名稱*/2structrt_i2c_bus_device*i2c_bus;/*I2C總線設備句柄*/34/*查找I2C總線設備,獲取I2C總線設備句柄*/5i2c_bus=(structrt_i2c_bus_device*)rt_device_find(name);一般情況下,注冊到系統的 I2C 設備名稱為 i2c0 ,i2c1等,使用示例如下所示:
數據傳輸
獲取到 I2C 總線設備句柄就可以使用 rt_i2c_transfer() 進行數據傳輸。函數原型如下所示:
1rt_size_trt_i2c_transfer(structrt_i2c_bus_device*bus,2structrt_i2c_msgmsgs[],3rt_uint32_tnum);
和 SPI 總線的自定義傳輸接口一樣,I2C 總線的自定義傳輸接口傳輸的數據也是以一個消息為單位。參數 msgs[] 指向待傳輸的消息數組,用戶可以自定義每條消息的內容,實現 I2C 總線所支持的 2 種不同的數據傳輸模式。如果主設備需要發送重復開始信號,則需要發送 2 個消息。
I2C 消息數據結構原型如下:
1structrt_i2c_msg2{3rt_uint16_taddr;/*從機地址*/4rt_uint16_tflags;/*讀、寫標志等*/5rt_uint16_tlen;/*讀寫數據字節數*/6rt_uint8_t*buf;/*讀寫數據緩沖區指針*/7}
從機地址 addr:支持 7 位和 10 位二進制地址,需查看不同設備的數據手冊 。RT-Thread I2C 設備接口使用的從機地址均為不包含讀寫位的地址,讀寫位控制需修改標志 flags。
標志 flags 可取值為以下宏定義,根據需要可以與其他宏使用位運算 “|” 組合起來使用。
1#defineRT_I2C_WR0x0000/*寫標志*/2#defineRT_I2C_RD(1u<0)??????/*?讀標志?*/3#define?RT_I2C_ADDR_10BIT??????(1u?<2)??????/*?10?位地址模式?*/4#define?RT_I2C_NO_START????????(1u?<4)??????/*?無開始條件?*/5#define?RT_I2C_IGNORE_NACK?????(1u?<5)??????/*?忽視?NACK?*/6#define?RT_I2C_NO_READ_ACK?????(1u?<6)?????/*?讀的時候不發送?ACK?*/
使用示例如下所示:
1#defineAHT10_I2C_BUS_NAME"i2c1"/*傳感器連接的I2C總線設備名稱*/ 2#defineAHT10_ADDR0x38/*從機地址*/ 3structrt_i2c_bus_device*i2c_bus;/*I2C總線設備句柄*/ 4 5/*查找I2C總線設備,獲取I2C總線設備句柄*/ 6i2c_bus=(structrt_i2c_bus_device*)rt_device_find(name); 7 8/*讀傳感器寄存器數據*/ 9staticrt_err_tread_regs(structrt_i2c_bus_device*bus,rt_uint8_tlen,rt_uint8_t*buf)10{11structrt_i2c_msgmsgs;1213msgs.addr=AHT10_ADDR;/*從機地址*/14msgs.flags=RT_I2C_RD;/*讀標志*/15msgs.buf=buf;/*讀寫數據緩沖區指針*/16msgs.len=len;/*讀寫數據字節數*/1718/*調用I2C設備接口傳輸數據*/19if(rt_i2c_transfer(bus,&msgs,1)==1)20{21returnRT_EOK;22}23else24{25return-RT_ERROR;26}27}
I2C 總線設備使用示例
I2C 設備的具體使用方式可以參考如下示例代碼,示例代碼的主要步驟如下:
首先根據 I2C 設備名稱查找 I2C 名稱,獲取設備句柄,然后初始化 aht10 傳感器。
控制傳感器的 2 的函數為寫傳感器寄存器 write_reg() 和讀傳感器寄存器 read_regs(),這兩個函數分別調用了 rt_i2c_transfer() 傳輸數據。讀取溫濕度信息的函數 read_temp_humi() 則是調用這兩個函數完成功能。
1/* 2*程序清單:這是一個I2C設備使用例程 3*例程導出了i2c_aht10_sample命令到控制終端 4*命令調用格式:i2c_aht10_samplei2c1 5*命令解釋:命令第二個參數是要使用的I2C總線設備名稱,為空則使用默認的I2C總線設備 6*程序功能:通過I2C設備讀取溫濕度傳感器aht10的溫濕度數據并打印 7*/ 8 9#include
-
SPI
+關注
關注
17文章
1701瀏覽量
91336 -
總線
+關注
關注
10文章
2868瀏覽量
87995 -
I2C
+關注
關注
28文章
1481瀏覽量
123325
原文標題:RT-Thread設備框架使用指南——I2C 總線設備
文章出處:【微信號:RTThread,微信公眾號:RTThread物聯網操作系統】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論