1. 程式人生 > >《12.I2C通訊詳解》

《12.I2C通訊詳解》

《12.I2C通訊詳解》

第一部分、章節目錄
1.12.1.什麼是I2C通訊
1.12.2.由I2C學通訊時序
1.12.3.S5PV210的I2C控制器
1.12.4.X210板載gsensor介紹
1.12.5.I2C匯流排的通訊流程
1.12.6.I2C通訊程式碼分析1
1.12.7.I2C通訊程式碼分析2

第二部分、章節介紹
1.12.1.什麼是I2C通訊
本節簡單介紹I2C介面的物理特徵、通訊特徵(序列、同步、非差分、低速率)、主從裝置、匯流排式通訊等概念,希望大家對I2C匯流排通訊有個框架性的瞭解。
1.12.2.由I2C學通訊時序
本節主要講解I2C匯流排的通訊時序,希望借用I2C通訊的時序分析讓大家明白通訊介面究竟是如何工作的。儘管現代SoC都是通過專用控制器來產生時序訊號並不需自己編碼,但是理解這些時序仍然對程式設計有很積極的作用。
1.12.3.S5PV210的I2C控制器
本節介紹S5PV210的I2C控制器,主要講了它的結構框圖、時鐘來源與分頻、主要暫存器及其作用分析等。
1.12.4.X210板載gsensor介紹
本節帶領大家學習X210開發板上自帶的gsensor晶片,主要是通過分析原理圖、資料手冊讓大家對gsensor晶片的I2C介面、讀寫流程圖等有個瞭解,以不影響I2C匯流排通訊的學習。gsensor晶片本身的原理、暫存器列表、程式設計方法等並不是我們本課的重點。
1.12.5.I2C匯流排的通訊流程
本節結合S5PV210的資料手冊,來講解I2C匯流排的工作流程。主要講解主傳送、主接收這兩種流程,同時結合gsensor資料手冊中的操作流程來兩方印證。實際的程式設計就是按照這些流程在寫。
1.12.6.I2C通訊程式碼分析1
本節帶大家分析I2C通訊物理層的程式碼,原始碼來自於linux核心中。主要看了其中幾個I2C傳送接收的函式,通過函式的暫存器操作和上節講的資料手冊中的流程圖相印證,讓大家理解程式碼是怎麼寫出來的。
1.12.7.I2C通訊程式碼分析2
本節分析gsensor驅動,及其與I2C物理層驅動的關聯。通過這種層次結合和呼叫,讓大家對驅動的分層有所理解。
第三部分、隨堂記錄
1.12.1.什麼是I2C通訊
1.12.1.1、物理介面:SCL + SDA
(1)SCL(serial clock):時鐘線,傳輸CLK訊號,一般是I2C主裝置向從裝置提供時鐘的通道。
(2)SDA(serial data): 資料線,通訊資料都通過SDA線傳輸

1.12.1.2、通訊特徵:序列、同步、非差分、低速率
(1)I2C屬於序列通訊,所有的資料以位為單位在SDA線上序列傳輸。
(2)同步通訊就是通訊雙方工作在同一個時鐘下,一般是通訊的A方通過一根CLK訊號線傳輸A自己的時鐘給B,B工作在A傳輸的時鐘下。所以同步通訊的顯著特徵就是:通訊線中有CLK
(3)非差分。因為I2C通訊速率不高,而且通訊雙方距離很近,所以使用電平訊號通訊。
(4)低速率。I2C一般是用在同一個板子上的2個IC之間的通訊,而且用來傳輸的資料量不大,所以本身通訊速率很低(一般幾百KHz,不同的I2C晶片的通訊速率可能不同,具體在程式設計的時候要看自己所使用的裝置允許的I2C通訊最高速率,不能超過這個速率)

1.12.1.3、突出特徵1:主裝置+從裝置
(1)I2C通訊的時候,通訊雙方地位是不對等的,而是分主裝置和從裝置。通訊由主裝置發起,由主裝置主導,從裝置只是按照I2C協議被動的接受主裝置的通訊,並及時響應。
(2)誰是主裝置、誰是從裝置是由通訊雙方來定的(I2C協議並無規定),一般來說一個晶片可以只能做主裝置、也可以只能做從裝置、也可以既能當主裝置又能當從裝置(軟體配置)。

1.12.1.3、突出特徵2:可以多個裝置掛在一條總線上(從裝置地址)
(1)I2C通訊可以一對一(1個主裝置對1個從裝置),也可以一對多(1個主裝置對多個從裝置)。
(2)主裝置來負責排程匯流排,決定某一時間和哪個從裝置通訊。注意:同一時間內,I2C的總線上只能傳輸一對裝置的通訊資訊,所以同一時間只能有一個從裝置和主裝置通訊,其他從裝置處於“冬眠”狀態,不能出來搗亂,否則通訊就亂套了。
(3)每一個I2C從裝置在通訊中都有一個I2C從裝置地址,這個裝置地址是從裝置本身固有的屬性,然後通訊時主裝置需要知道自己將要通訊的那個從裝置的地址,然後在通訊中通過地址來甄別是不是自己要找的那個從裝置。(這個地址是一個電路板上唯一的,不是全球唯一的)

1.12.1.3、主要用途:SoC和周邊外設之間的通訊(典型的如EEPROM、電容觸控IC、各種sensor等)

1.12.2.由I2C學通訊時序
1.12.2.1、什麼是時序?
(1)時序:字面意思,時序就是時間順序,實際上在通訊中時序就是通訊線上按照時間順序發生的電平變化,以及這些變化對通訊的意義就叫時序。

1.12.2.2、I2C的匯流排空閒狀態、起始位、結束位
(1)I2C總線上有1個主裝置,n(n>=1)個從裝置。I2C總線上有2種狀態;空閒態(所有從裝置都未和主裝置通訊,此時匯流排空閒)和忙態(其中一個從裝置在和主裝置通訊,此時匯流排被這一對佔用,其他從裝置必須歇著)。
(2)整個通訊分為一個週期一個週期的,兩個相鄰的通訊週期是空閒態。每一個通訊週期由一個起始位開始,一個結束位結束,中間是本週期的通訊資料。
(3)起始位並不是一個時間點,起始位是一個時間段,在這段時間內匯流排狀態變化情況是:SCL線維持高電平,同時SDA線發生一個從高到低的下降沿。
(4)與起始位相似,結束位也是一個時間段。在這段時間內匯流排狀態變化情況是:SCL線維持高電平,同時SDA線發生一個從低到高的上升沿。

1.12.2.3、I2C資料傳輸格式(資料位&ACK)
(1)每一個通訊週期的發起和結束都是由主裝置來做的,從裝置只有被動的響應主裝置,沒法自己自發的去做任何事情。
(2)主裝置在每個通訊週期會先發8位的從裝置地址(其實8位中只有7位是從裝置地址,還有1位表示主裝置下面要寫入還是讀出)到匯流排(主裝置是以廣播的形式傳送的,只要是總線上的所有從裝置其實都能收到這個資訊)。然後總線上的每個從裝置都能收到這個地址,並且收到地址後和自己的裝置地址比較看是否相等。如果相等說明主裝置本次通訊就是給我說話,如果不想等說明這次通訊與我無關,不用聽了不管了。
(3)傳送方傳送一段資料後,接收方需要回應一個ACK。這個響應本身只有1個bit位,不能攜帶有效資訊,只能表示2個意思(要麼表示收到資料,即有效響應;要麼表示未收到資料,無效響應)
(4)在某一個通訊時刻,主裝置和從裝置只能有一個在發(佔用匯流排,也就是向匯流排寫),另一個在收(從匯流排讀)。如果在某個時間主裝置和從裝置都試圖向匯流排寫那就完蛋了,通訊就亂套了。

1.12.3.4、資料在總線上的傳輸協議
(1)I2C通訊時的基本資料單位也是以位元組為單位的,每次傳輸的有效資料都是1個位元組(8位)。
(2)起始位及其後的8個clk中都是主裝置在傳送(這裝置掌控匯流排),此時從裝置只能讀取匯流排,通過讀匯流排來得知主裝置發給從裝置的資訊;然後到了第9週期,按照協議規定從裝置需要傳送ACK給主裝置,所以此時主裝置必須釋放匯流排(主裝置把匯流排置為高電平然後不要動,其實就類似於匯流排空閒狀態),同時從裝置試圖拉低匯流排發出ACK。如果從裝置拉低匯流排失敗,或者從裝置根本就沒有拉低匯流排,則主裝置看到的現象就是匯流排在第9週期仍然一直保持高,這對主裝置來說,意味著我沒收到ACK,主裝置就認為剛才給從裝置傳送的8位元組不對(接收失敗)

1.12.3.S5PV210的I2C控制器
通訊雙方本質上是通過時序在工作,但是時序會比較複雜不利於SoC軟體完成,於是乎解決方案是SoC內部內建了硬體的控制器來產生通訊時序。這樣我們寫軟體時只需要向控制器的暫存器中寫入配置值即可,控制器會產生適當的時序在通訊線上和對方通訊。
1.12.3.1、結構框圖
(1)時鐘部分,時鐘來源是PCLK_PSYS,經過內部分頻最終得到I2C控制器的CLK,通訊中這個CLK會通過SCL線傳給從裝置。
(2)I2C匯流排控制邏輯(前臺代表是I2CCON、I2CSTAT這兩個暫存器),主要負責產生I2C通訊時序。實際程式設計中要傳送起始位、停止位、接收ACK等都是通過這兩個暫存器(背後所代表的電路模組)實現的。
(3)移位暫存器(shift register),將程式碼中要傳送的位元組資料,通過移位暫存器變成1個位一個位的丟給SDA線上去傳送/接收。學過數位電路的同學應該對移位暫存器不陌生。
(4)地址暫存器+比較器。本I2C控制器做從裝置的時候用。(我沒用過,理論分析)

1.12.3.2、系統分析I2C的時鐘
(1)I2C時鐘源頭來源於PCLK(PCLK_PSYS,等於65MHz),經過了2級分頻後得到的。
(2)第一級分頻是I2CCON的bit6,可以得到一箇中間時鐘I2CCLK(等於PCLK/16或者PCLK/512)
(3)第二級分頻是得到最終I2C控制器工作的時鐘,以I2CCLK這個中間時鐘為來源,分頻係數為[1,16]
(4)最終要得到時鐘是2級分頻後的時鐘,譬如一個可用的設定是:65000KHz/512/4=31KHz

1.12.3.3、主要暫存器I2CCON、I2CSTAT、I2CADD、I2CDS
I2CCON + I2CSTAT:主要用來產生通訊時序和I2C介面配置。
I2CADD:用來寫自己的slave address
I2CDS:傳送/接收的資料都放在這裡

1.12.4.X210板載gsensor介紹
1.12.4.1、原理圖查閱
(1)gsensor的供電由PWMTOUT3引腳控制。當PWMTOUT3輸出低電平時gsensor無電不工作;當輸出高電平時gsensor才會工作。
(2)gsensor的SDA和SCL接的是S5PV210的I2C埠0
(3)將來程式設計時在gsensor_init函式中要去初始化相關的GPIO。要把相應的GPIO設定為正確的模式和輸入輸出值。

1.12.4.2、重力加速度感測器簡介
(1)用在手機、平板、智慧手錶等裝置上,用來感受人的手的移動,獲取一些運動的方向性資訊用來給系統作為輸入參量。
(2)可以用來設計智慧手錶的計步器功能。
(3)重力加速度感測器、地磁感測器、陀螺儀等三個感測器結合起來,都是用來感謝運動的速度、方位等資訊的,所以現在最新的有9軸感測器,就是把三者結合起來,並且用一定的演算法進行綜合得出結論,目的是更加準確。
(4)一般感測器的介面有2種:模擬介面和數字介面。模擬介面是用介面電平變化來作為輸出的(譬如模擬介面的壓力感測器,在壓力不同時輸出電平在0~3.3V範圍內變化,每一個電壓對應一個壓力。),SOC需要用AD介面來對接這種感測器對它輸出的資料進行AD轉換,轉換得到數字電壓值,再用數字電壓值去校準得到壓力值;數字介面是後來發展出來的,數字介面的sensor是在模擬介面的sensor基礎上,內部集成了AD,直接(通過一定的匯流排介面協議,一般是i2C)輸出一個數字值的引數,這樣SoC直接通過匯流排介面初始化、讀取感測器輸出的引數即可(譬如gsensor、電容觸控式螢幕IC)。

1.12.4.3、I2C從裝置的裝置地址
(1)KXTE9的I2C地址固定為0b0001111(0x0f)
(2)I2C從裝置地址本身是7位的,但是在I2C通訊中傳送I2C從裝置地址時實際傳送的是8位,這8位中高7位(bit7-bit1)對應I2C從裝置的7位地址,最低一位(LSB)存放的是R/W資訊(就是說下一個資料是主裝置寫從裝置讀(對應0),還是主裝置讀從裝置寫(對應1))
(3)基於上面講的,對於KXTE9來說,主裝置(SoC)發給gsensor資訊時,SAD應該是:0b00011110(0x1E)
如果是主裝置讀取gsensor資訊時,SAD應該是:0b00011111(0x1F)

1.12.4.4、I2C從裝置的通訊速率
(1)I2C協議本身屬於低速協議,通訊速率不能太高。
(2)實際上通訊的主裝置和從裝置本身都有最高的通訊速率限制(屬於各個晶片本身的引數),實際程式設計時怎麼確定最終的通訊速率?只要小於兩個即可。
(3)一般來說只能做從裝置的sensor晶片本身i2c通訊速率偏低,像KXTE9最高支援400KHz的頻率。

1.12.5.I2C匯流排的通訊流程
1.12.5.1、S5PV210的主傳送流程圖
1.12.5.2、S5PV210的主接收流程圖
1.12.5.3、gsensor的寫暫存器流程圖
1.12.5.4、gsensor的讀暫存器流程圖

1.12.6.I2C通訊程式碼分析1
1.12.6.1、I2C控制器初始化:s3c24xx_i2c_init
(1)初始化做的事情:初始化GPIO,設定IRQEN和ACKEN,初始化I2C時鐘
1.12.6.2、I2C控制器主模式開始一次讀寫:s3c24xx_i2c_message_start

1.12.6.3、I2C控制器主模式結束一次讀寫:s3c24xx_i2c_stop

1.12.7.I2C通訊程式碼分析2
框架分析:我們最終目的是通過讀寫gsensor晶片的內部暫存器來得到一些資訊。為了完成這個目的,我們需要能夠讀寫gsensor的暫存器,根據gsensor的規定我們需要按照一定的操作流程來讀寫gsensor的內部暫存器,這是一個層次(姑且叫做傳輸層、協議層、應用層);我們要按照操作流程去讀寫暫存器,就需要考慮I2C介面協議(這就是所謂的物理層,本質就是那些時序)。此時主機SoC有或者沒有控制器,有控制器時考慮控制器的暫存器,沒控制器時要自己軟體模擬時序。
協議層的程式碼主要取決於gsensor晶片;物理層程式碼主要取決於主機SoC。

1.12.7.1、gsensor寫暫存器:gsensor_i2c_write_reg
1.12.7.2、gsensor讀暫存器:gsensor_i2c_read_reg
1.12.7.3、gsensor程式設計:gsensor_initial等