概述
I2C(Inter-Integrated Circuit)總線是由PHILipS公司開發的兩線式串行總線,用于連接微控制器及其外圍設備。是微電子通信控制領域廣泛采用的一種總線標準。具有接口線少,控制方式簡單,器件封裝形式小,通信速率較高等優點。
I2C 總線通過串行數據(SDA)線和串行時鐘(SCL)線在連接到總線的器件間傳遞信息。每個器件都有一個唯一的地址識別(無論是微控制器——MCU、LCD驅動器、存儲器或鍵盤接口),而且都可以作為一個發送器或接收器(由器件的功能決定)。
I2C有四種工作模式:
1.主機發送
2.主機接收
3.從機發送
4.從機接收
以我們的S5PC100來說,我們主要討論的主機發送模式。
在傳輸數據的時候,串行數據線(SDA)必須在時鐘的高電平周期保持穩定,串行數據線(SDA)的高或低電平的狀態只有在串行時鐘線(SCL)的時鐘信號是低電平時才能改變。這是由于當處于時鐘的高電平周期時,串行數據線的電平變化具有特殊的含義。
串行時鐘線(SCL)是高電平時,串行數據線(SDA)從高電平向低電平切換,這種情況表示起始條件。
串行時鐘線(SCL)是高電平時,串行數據線(SDA)從低電平向高電平切換,這種情況表示停止條件。
在數據傳輸時,發送到SDA線上的每個字節必須是8位,每次數據可以發送的字節數量不受限制。并且每個字節后必須跟一個響應位。
在linux內核中定義了I2C驅動體系結構。我們通過一個圖來說明:
在Linux系統中,I2C驅動由三部分構成,即I2C核心、I2C總線驅動和I2C設備驅動。
I2C核心用于聯系I2C設備驅動與I2C控制驅動的紐帶。實現了一組和硬件無關的函數。
I2C總線驅動用于在I2C總線上產生相應的時序。
I2C設備驅動調用I2C core中的函數來完成I2C設備驅動的注冊以及I2C消息的封裝。這也是我們主要關心的部分。
在I2C子系統中實現I2C通用設備驅動,我們可以使用這個通過驅動來實現對I2C設備的控制,但是I2C消息就必須由用戶程序自己封裝,這絕對是不可行的。所以我們推薦自己實現對應的I2C特定驅動,從中封裝I2C消息。使用戶程序不需關心內部的細節。
但是我們還是首先需要了解一下如何使用這個通用的I2C驅動。
首先我們需要配置內核來添加I2C總線驅動。修改內容為:
首先修改配置文件,添加S5PC100的支持。然后執行make menuconfig來添加總線設備驅動和通過設備驅動。
之后編譯內核,運行內核后我們會發現在/dev/下多了兩個設備節點i2c-0和i2c-1.這是證明我們的通用設備驅動已經加載成功。
我們直接訪問這個設備文件就可以控制I2C設備。如何操作呢?
在應用程序中:
1.打開i2c設備文件。
2.構建消息
3.執行ioctl操作
打開i2c設備文件不用多說。構建什么消息呢?
我們首先需要來看兩個數據結構
i2c_rdwr_ioctl_data 用于給ioctl操作傳遞參數。當中有兩個成員。
第一個參數為msgs。即要傳遞的消息。它是一個指針,由于保存一個消息的首地址或者一組消息的數組首地址。
第二個參數為消息的個數。
接下來我們來看i2c_msg
該結構體用于封裝一個消息。
addr:即從設備的地址
flags:標志,下面定義了很多標志。0代表寫。1代表讀
len: 數據的長度
buf: 用于發送或者接收數據的緩沖區。
知道構建消息相關的兩個結構體了,那么接下來我們應該如何構建消息呢?這就需要查看對應要訪問的i2c設備的芯片手冊了。
打開lm75的芯片手冊。
首先我們需要找到lm75的從機地址。
i2c設備地址有7位構成高4位是固定的,低3位由設備的三個地址引腳來決定。
通過這里我們得知lm75溫度傳感器的i2c地址的高4位。低三位我們通過查看原理圖可以得知都為0.所以lm75的i2c地址為0x48.
我們通過一個圖可以得知lm75溫度傳感器的內部寄存器的操作過程:
首先我們可以看到一個pointer 寄存器,它用于選擇到底要訪問哪個寄存器。
剩下四個寄存器分別有不同的功能。我們當前就是讀取溫度值,所以直接操作溫度寄存器即可。
如何操作我們需要查看lm75的訪問時序圖。
通過查看lm75的溫度寄存器可以得知溫度寄存器有16位,高8位表示對應的整數的溫度,第7位值為1,表示在高8位的溫度的基礎上加0.5攝氏度。并且如果最高位為1的話表示當前讀到的數值是一個負數的補碼。即零
下多少度。
所以如果想要讀取溫度的話我們至少需要讀取兩個字節的數據。
接下來我們來看時序圖。
根據時序圖我們就可以構建消息了。
首先我們需要設置pointer寄存器,指向lm75的溫度寄存器。
之后再構建一個消息用于讀取溫度的值
消息構建好后就可以執行ioctl操作了:
我們測試一下。。。
那么如何是我們自己編寫特定的i2c驅動怎么做呢?
首先我們需要在平臺代碼中加入lm75的設備信息。
type代表設備類型,addr:從設備號,platform_data平臺數據。irq中斷號。
添加設備信息后,在內核啟動后,會將數組中的所有設備全部注冊到內核中。
接下來我們來看如何編寫一個特定的i2c設備驅動:
1.構建i2c設備驅動結構體(i2c_driver)
1.PRobe/remove 對應之前的加載函數與卸載函數
2.driver成員。通用驅動屬性,我們需要設置name成員但不是用于匹配設備,那如何匹配設備呢?
3.id_table成員用于設置當前i2c_driver所支持的設備類型。
i2c_device_id結構體中有兩個成員name用于配置設備,driver_data驅動的私有數據,我們基本不會用,直接傳遞0即可。
并且要求,在設置完支持的設備后,需要在后面添加一個空成員用于結束標志
2.實現字符設備驅動模型(之前的加載函數用于probe,卸載函數用于remove)
3.實現讀操作用于讀取溫度。當中構建消息,發送消息:
i2c_transfer(適配器, 消息首地址, 數量);
適配器從何而來,當我們的i2c設備與驅動匹配后執行probe函數,第一個參數為client。它當中就包含了適配器,所以我們在probe函數中,將client的首地址保存起來,用于傳輸消息。
3.加載函數中注冊i2c設備驅動i2c_add_driver
4.卸載函數中注銷i2c設備驅動i2c_del_driver
文章來源:華清遠見嵌入式學院,原文地址:http://www.embedu.org/Column/Column853.htm
更多相關嵌入式免費資料查看華清遠見講師博文>>
新聞熱點
疑難解答