博客專欄

        EEPW首頁 > 博客 > 一文搞懂I2C總線通信

        一文搞懂I2C總線通信

        發布人:美男子玩編程 時間:2022-06-22 來源:工程師 發布文章

        本來不打算寫這篇文章,因為網上關于I2C總線通信的資料很多很全。但是最近剛換工作,主要做驅動開發,第一個驅動就是I2C通信,想了想還是結合網上的資料再整理下思路,方便今后的查閱和溫習。



        1


        簡介


        I2C(集成電路總線),由Philips公司(2006年遷移到NXP)在1980年代初開發的一種簡單、雙線雙向的同步串行總線,它利用一根時鐘線和一根數據線在連接總線的兩個器件之間進行信息的傳遞,為設備之間數據交換提供了一種簡單高效的方法。每個連接到總線上的器件都有唯一的地址,任何器件既可以作為主機也可以作為從機,但同一時刻只允許有一個主機。


        I2C 標準是一個具有沖突檢測機制和仲裁機制的真正意義上的多主機總線,它能在多個主機同時請求控制總線時利用仲裁機制避免數據沖突并保護數據。作為嵌入式開發者,使用I2C總線通信的場景有很多,例如驅動FRAM、E2PROM、傳感器等。


        圖片


        總結來說,I2C總線具有以下特點:

        • 只需要SDA、SCL兩條總線;

        • 沒有嚴格的波特率要求;

        • 所有組件之間都存在簡單的主/從關系,連接到總線的每個設備均可通過唯一地址進行軟件尋址;

        • I2C是真正的多主設備總線,可提供仲裁和沖突檢測;

        • 傳輸速度分為四種模式:

        1. 標準模式(Standard Mode):100 Kbps

        2. 快速模式(Fast Mode):400 Kbps

        3. 高速模式(High speed mode):3.4 Mbps

        4. 超快速模式(Ultra fast mode):5 Mbps

        • 最大主設備數:

          無限制;

        • 最大從機數:

          理論上是127。



        2


        物理特性


        I2C 總線使用連接設備的"SDA"(串行數據總線)和"SCL"(串行時鐘總線)來傳送信息。


        圖片

        圖片


        I2C 總線內部使用漏極開路輸出驅動器,因此SDA和SCL可以被拉低為低電平,但是不能被驅動為高電平,所以每條線上都要使用一個上拉電阻,默認情況下將其保持在高電平。


        圖片

        I2C 總線上拉電阻阻值取決于系統應用,TI 官方手冊推薦使用以下公式來計算上拉電阻值:


        圖片
        圖片

        根據上表,這里不難發現需要在做電阻選擇需要滿足幾個條件:

        • 灌電流最大值為3mA;

        • 低電平輸出電壓設置了最大值為0.4V。


        所以根據上述公式可以計算,對于5V的電源,每個上拉電阻阻值至少1.53kΩ,而對于3.3V的電源,每個電阻阻值至少967Ω。


        如果覺得計算電阻值比較麻煩,也可以使用典型值 4.7kΩ。若各位想了解更多可直接參見手冊說明。



        3


        通訊時序



        通常情況下,一個完整的I2C通信過程包括以下 4 部分:

        • 開始條件

        • 地址傳送

        • 數據傳送

        • 停止條件


        主機在 SCL 線上輸出串行時鐘信號,數據在 SDA 線上進行傳輸,每傳輸一個字節(最高位 MSB 開始傳輸)后面跟隨一個應答位,一個 SCL 時鐘脈沖傳輸一個數據位。


        標準的I2C時序如下圖所示:


        圖片

        3.1、開始和停止條件


        當總線上的主機都不驅動總線,總線進入空閑狀態,SCL 和 SDA 都為高電平。總線空閑狀態下總線上設備都可以通過發送開始條件啟動通信。


        當 SCL 線為高時,SDA 線上出現由高到低的信號,表明總線上產生了起始信號。SDA 線上出現由低到高的信號,表明總線上產生了停止信號,如下圖所示:


        圖片

        當兩個起始信號之間沒有停止信號時,即產生了重復起始信號。主機采用這種方法與另一個從機或相同的從機以不同傳輸方向進行通信(例如:從寫入設備到從設備讀出)而不釋放總線。如下圖所示:


        圖片


        3.2、地址傳送


        開始條件或者重新開始條件后面的幀是地址幀(一個字節),用于指定主機通信的對象地址,在發送停止條件之前,指定的從機一直有效。


        I2C通訊支持:7 位尋址和10 位尋址兩種模式。


        7 位尋址模式,地址幀(8bit)的高 7 位為從機地址,地址幀第 8 位來決定數據幀傳送的方向:7 位從機地址 + 1位讀/寫位,讀/寫位控制從機的數據傳輸方向(0:寫;1:讀)。幀格式如下所示:


        圖片


        10 位尋址模式,主機發送幀,第一幀發送頭序列(11110XX0,其中 XX 表示 10 位地址的高兩位),然后第二幀發送低八位從機地址。主機接收幀,第一幀發送頭序列(11110XX0,其中 XX 表示 10 位地址的高兩位),然后第二幀發送低八位從機地址。接下來會發送一個重新開始條件,然后再發送一幀頭序列(11110XX1,其中 XX 表示 10 位地址的高兩位)幀格式如下所示:


        圖片


        解析如下:

        • S :表示開始條件;

        • SLA :表示從機地址;

        • R/W#:表示發送和接收的方向。當 R/W# 為“1” 時,將數據從從機發送到主機;當 R/W#為“0” 時,將數據從主機發送到從機;

        • Sr :表示重新開始條件;

        • DATA :表示發送和接收的數據;

        • P :表示停止條件。


        3.3、數據傳送


        地址匹配一致后,總線上的主機根據 R/W 定義的方向一幀一幀的傳送數據。所有的地址幀后傳送的數據都視為數據幀。即使是 10 位地址格式的低 8 位地址也視為數據幀。


        數據幀的長度是 8 位。SCL 的低電平 SDA 變化,SCL 的高電平 SDA 保持,每個時鐘周期發送一位數據。數據幀后的第 9 個時鐘是應答位,是接收方向發送方傳送的握手信號。


        圖片

        如果總線上從機接收數據,在第 9 個時鐘周期不響應主機,從機必須發送 NACK。如果總線上主機接收數據,第 9 個周期發送 NACK,從機接收到 NACK,從機停止發送數據。


        無論主機還是從機發送了 NACK,數據傳送終止。主機可以做下列任一動作:

        • 發送停止條件釋放總線 ;

        • 發送重新開始條件開始一個新的通信。


        以華大MCU(HC3F4A0系列)為例,在主機接收模式中,主機輸出 SCL 時鐘,接收從機數據并返回應答。主機接收數據的運行時序例如下圖所示:


        圖片

        7 位地址格式的主機發送數據時序圖


        在主機接收模式中,主機輸出 SCL 時鐘,接收從機數據并返回應答。主機接收數據的運行時序例如下圖所示:


        圖片

        7 位地址格式的主機接收數據的時序圖


        在從機發送模式中,接收來自主機的 SCL 時鐘,本產品為從機發送數據,并且接收主機返回應答。從機發送數據的運行時序例如下圖所示:


        圖片

        7 位地址格式的從機發送模式時序圖


        在從機接收模式中,接收來自主機的 SCL 時鐘和數據,接收完數據后返回應答。從機接收數據的運行時序例如下圖所示:


        圖片

        7 位地址格式從機接收模式時序圖


        3.4、總線應答


        每傳輸一個字節,后面跟隨一個應答位。通過將 SDA 線拉低,來允許接收端回應發送端。ACK 為一個低電平信號,當時鐘信號為高時,SDA 保持低電平則表明接收端已成功接收到發送端的數據。


        當主機作為發送器件時,如果從機上產生無響應信號(NACK),主機可以產生停止信號來退出數據傳輸,或者產生重復起始信號開始新一輪的數據傳輸。當主機作為接收器件時,發生無響應信號(NACK),從機釋放 SDA 線,使主機產生停止信號或重復起始信號。


        圖片

        I2C 總線上應答信號


        3.5、總線仲裁


        I2C 總線上的仲裁分為兩個部分:SCL 線上的同步和 SDA 線上的仲裁。


        • SCL 線上的同步(時鐘同步)


        由于 I2C 總線具有線“與”的邏輯功能,SCL 線上只要有一個節點發送低電平,總線上就表現低電平。當所有的節點都發送高電平時,總線才能表現為高電平。所以,時鐘低電平的時間由時鐘電平期最長的器件決定,而時鐘的高電平時間由時鐘高電平期最短的器件決定。


        由于 I2C 這種特性,當多個主機同時發送時鐘信號時,在總線上表示的是統一的時鐘信號。如果從機希望主機降低傳送速度可以通過將 SCL 主動拉低延長其低電平時間來通知主機,當主機在準備下一次傳送時發現 SCL 的電平被拉低時進行等待,直到從機完成操作并釋放 SCL 線的控制權。


        • SDA 線上的仲裁


        SDA 線上的仲裁也是由于 I2C 總線具有線“與”的邏輯功能。主機在發送數據后,通過比較總線上的數據來決定是否退出競爭。丟失仲裁的主機立即切換到未被尋址的從機狀態,以確保自身能被仲裁勝利的主機尋址到。仲裁失敗的主機繼續輸出時鐘脈沖(在 SCL 上),直到發送完當前的串行字節。通過這種原理可以保證 I2C 總線在多個主機企圖控制總線時保證數據的不丟失。


        圖片

        I2C 總線上的仲裁


        解析如下:

        (1)另一器件發送串行數據;

        (2)另一器件通過拉低 SDA 先撤消了該 I2C 主機發送的一個邏輯 1(虛線)。仲裁丟失,I2C 進入從接收模式;

        (3)此時 I2C 處于從接收模式,但仍產生時鐘脈沖,直至發送完當前字節。I2C 將不為下個字節的傳輸產生時鐘脈沖。一旦贏得仲裁,SDA 上的數據傳輸由新的主機來啟動。



        4


        工作過程


        最后整體敘述一下I2C通訊過程,本小節內容整理來源于:微信公眾號:小麥大叔,作者菜刀和小麥。


        第1步:起始條件


        主設備通過將SDA線從高電平切換到低電平,再將SCL線從高電平切換到低電平,來向每個連接的從機發送啟動條件,如下圖所示:


        圖片

        第2步:發送從設備地址


        主設備向每個從機發送要與之通信的從機的7位或10位地址,以及相應的讀/寫位,如下圖所示:


        圖片

        第3步:接收應答


        每個從設備將主設備發送的地址與其自己的地址進行比較。如果地址匹配,則從設備通過將SDA線拉低一位以表示返回一個ACK位。


        如果來自主設備的地址與從機自身的地址不匹配,則從設備將SDA線拉高,表示返回一個NACK位。


        圖片


        第4步:收發數據


        主設備發送或接收數據到從設備,如下圖所示:


        圖片


        第5步:接收應答


        在傳輸完每個數據幀后,接收設備將另一個ACK位返回給發送方,以確認已成功接收到該幀,如下圖所示:


        圖片

        第6步:停止通信


        為了停止數據傳輸,主設備將SCL切換為高電平,然后再將SDA切換為高電平,從而向從機發送停止條件,如下圖所示:


        圖片


        4.1、單個主設備連接多個從機


        I2C總線上的主設備使用7位地址對從設備進行尋址,可以使用128(2的7次方)個從機地址,如下圖所示:


        圖片


        4.2、多個主設備連接多個從機 


        多個主設備可以連接到一個或多個從機。


        當兩個主設備試圖通過SDA線路同時發送或接收數據時,同一系統中的多個主設備就會出現問題。


        為了解決這個問題,每個主設備都需要在發送消息之前檢測SDA線是低電平還是高電平:

        • 如果SDA線為低電平,則意味著另一個主設備可以控制總線,并且主設備應等待發送消息;

        • 如果SDA線為高電平,則可以安全地發送消息。


        圖片


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。

        LCD顯示屏相關文章:lcd顯示屏原理


        模數轉換器相關文章:模數轉換器工作原理


        塵埃粒子計數器相關文章:塵埃粒子計數器原理
        lcd相關文章:lcd原理


        關鍵詞: I2C

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 南开区| 靖安县| 凤冈县| 南部县| 项城市| 达拉特旗| 金湖县| 房产| 江陵县| 正定县| 石首市| 东兰县| 东丽区| 伊宁县| 阿瓦提县| 保德县| 修水县| 武强县| 镇沅| 皋兰县| 平谷区| 石阡县| 拉孜县| 宜良县| 阳朔县| 阜阳市| 翁牛特旗| 阿城市| 弥渡县| 北碚区| 宿迁市| 林芝县| 新密市| 桐梓县| 金堂县| 长子县| 宣城市| 比如县| 宣武区| 南部县| 泾源县|