Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 驅動(二) IIC簡介

Android 驅動(二) IIC簡介

編輯:關於Android編程

一、 I2C簡介


I2C(Inter-Integrated Circuit)總線是一種由 Philips 公司開發的兩線式串行總線,用於連接微控制器及其外圍設備。I2C 總線最主要的優點就是簡單性和有效性,簡單體現在接線簡單,只有兩根線數據線(SCL)和時鐘線(SDA),而且 控制簡單。所以一些封裝較小的器件多使用I2C總線,常見的使用I2C總線的設備有EEPROM、RTC及一些傳感器。這裡我們介紹下基於linux的I2C設備驅動的編寫。


  • I2C設備驅動的編寫有多種方式


    一種是直接操作CPU的I2C控制器,正對於某一個設備寫一個字符驅動,這種驅動相對來說比較直接,不需要太依賴於內核相關配置,但是這類設備驅動依賴CPU,可移植性較差。

    一種是基於linux內核I2C子系統完成設備驅動的編寫,一般內核會繼承相關CPU的控制器驅動即使沒有也可以通過技術支持可以獲得,所以我們只需要使用linux下I2C子系統提供的相關接口來構建我們的設備驅動就行了。這樣我們的設備驅動並不依賴於某一個特定的CPU,可移植性較好。

    IIC驅動主要分為Master和Slave,Master就是主機控制器,像A10內部的IIC控制器就是一個Master, Slave就是IIC從機設備,它要被掛接到Master上才能工作
    智能手機和平板電腦上用的sensor幾乎都是IIC設備,最常用的IIC設備就是電容觸摸屏和攝像頭,接下來,我們將針對觸摸屏、EEPROM、攝像頭等驅動來分析。

    • I2C總線工作原理

      I2C 總線是由數據線 SDA 和時鐘 SCL 構成的串行總線,各種被控制器件均

      並聯在這條總線上,每個器件都有一個唯一的地址識別,可以作為總線上的一個


      發送器件或接收器件(具體由器件的功能決定)。I2C 總線的接口電路結構如圖 1所示
      \

      • I2C 總線的幾種信號狀態

        1. 空閒狀態:SDA 和 SCL 都為高電平。

        2. 開始條件(S):SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送數據。

        3. 結束條件(P):SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送數據。

        4. 數據有效:在 SCL 的高電平期間,SDA 保持穩定,數據有效。SDA 的改變只能發生在 SCL 的低電平期間。

        5. ACK 信號:數據傳輸的過程中,接收器件每接收一個字節數據要產生一個 ACK 信號,向發送器件發出特定的低電平脈沖,表示已經收到數據。


        • I2C 總線基本操作

          I2C 總線必須由主器件(通常為微控制器)控制,主器件產生串行時鐘(SCL),同時控制總線的傳輸方向,並產生開始和停止條件。

          數據傳輸中,首先由主器件產生開始條件,隨後是器件的控制字節(前七位是從器件的地址,最後一位為讀寫位)。接下來是讀寫操作的數據,以及 ACK響應信號。數據傳輸結束時,主器件產生停止條件。具體的過程如圖 2 所示。

          \



          二、Linux 系統 I2C 驅動程序
          • I2C驅動層次結構
            Linux 系統對 I2C 設備具有很好的支持,Linux 系統下的 I2C 驅動程序從邏 輯上可以分為 3 個部分: 1. I2C 核心(I2C cZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcmWjqaO6yrXP1rbUIEkyQyDX3M/foaJJMkMgYWRhcHRlciC8sCBJMkMgZHJpdmVyILXEudzA7aGjIAoyLiBJMkMgv9jWxsb3x/22ryBJMkMgYWRhcHRlciCjutXrttSyu82swODQzbXEIEkyQyC/2NbGxvcgo6zKtc/WttQgSTJDINfcz9+3w87KtcS+38zlt723qKGjIAozLiBJMkMgyeixuMf9tq8gSTJDIGRyaXZlcqO61eu21MzYtqi1xCBJMkMgyeixuKOsyrXP1r7fzOW1xLmmxNyjrLD8wKhyZWFko6x3cml0ZSDS1LywIGlvY3RsILXIttTTw7unsuOy2df3tcS907/aoaMgCjxicj4KCtXiyP249rK/t9a1xLLjtM652M+1yOfNvCAzILrNzbwgNCDL+cq+oaMKPGJyPgoKPGJyPgoKPGltZyBzcmM9"/uploadfile/Collfiles/20140612/20140612091726248.jpg" alt="\">


            \



            • I2C 核心(I2C core)
              I2C core 是 Linux 內核用來維護和管理 I2C 的核心部分,其中維護了兩個靜 態的 List,分別記錄系統中的 I2C driver 結構和 I2C adapter 結構。I2C core 提供 接口函數,允許一個 I2C adapter,I2C driver 和 I2C client 初始化時在I2C core 中 進行注冊,以及退出時進行注銷。同時還提供了 I2C 總線讀寫訪問的一般接口(具 體的實現在與 I2C 控制器相關的 I2C adapter 中實現),主要應用在 I2C 設備驅動中。
              • I2C 控制器驅動(I2C adapter)
                I2C adapter 是針對不同類型 I2C 控制器硬件,實現比較底層的對 I2C 總線訪 問的具體方法。I2C adapter 構造一個對 I2C core 層接口的數據結構,並通過接口函數向 I2C core 注冊一個控制器。 I2C adapter 主要實現對 I2C 總線訪問的算法,master_xfer()函數就是 I2C adapter 底層對 I2C 總線讀寫方法的實現。同時 I2C adapter 中還實現了對 I2C 控制器中斷的處理函數。

                • I2C 設備驅動(I2C driver)
                  I2C driver 是對 I2C 從設備的軟件實現。I2C driver 中提供了一個通用的 I2C 設備的驅動程序,實現了字符類型設備的訪問接口,對設備的具體訪問是通過 I2C adapter 來實現的。I2C driver 構造一個對 I2C core 層接口的數據結構,通過 接口函數向 I2C Core 注冊一個 I2C 設備驅動。同時 I2C driver 構造一個對用戶層接口的數據結構,並通過接口函數向內核注冊為一個主設備號為 89 的字符類型設備。I2C driver 實現用戶層對 I2C 設備的訪問,包括 open,read,write,ioctl,release 等常規文件操作,可以通過 open 函數打開 I2C 設備文件,通過 ioctl 函數設定要訪問 I2C 設備的地址,然後就可以通過 read 和 write 函數完成對 I2C 設備的讀寫操作。通過 I2C driver 提供的通用方法可以訪問任何一個 I2C 的設備,但是其中實 現的 read,write 及 ioctl 等功能完全是基於一般設備的實現,所有的操作數據都是基於字節流,沒有明確的格式和意義。為了更方便和有效地使用 I2C 設備,可 以為一個具體的 I2C 設備開發特定的 I2C 設備驅動程序,在驅動中完成對特定的數據格式的解釋以及實現一些專用的功能。

                  三、 基於 SUNXI 平台的 I2C 控制器驅動
                  位於drivers/i2c/busses目錄下的文件i2c-sunxi.c,是基於sunxi平台實現的I2C 總線控制器驅動。它的職責是為系統中 3 條 I2C 總線實現相應的讀寫方法,但是控制器驅動本身並不會進行任何的通訊,而是等待設備驅動調用其函數。 圖 5 是基於 SUNXI 平台的 I2C 驅動層次架構圖,圖中有 3 塊 I2C adapter,分別對應 SUNXI 平台上的 3 塊 I2C 控制器 n峨#`堌源碼結構
                  在 drivers/i2c/目錄下,包含有幾個重要文件和目錄,如下: 1. 文件 i2c-core.c:I2C 子系統核心功能的實現; 2. 文件 i2c-dev.c:通用的從設備驅動實現; 3. 目錄 busses:裡面包括基於不同平台實現的 I2C 總線控制器驅動; 4. 目錄 algos:裡面實現了一些 I2C 總線控制器的 algorithm。
                  四、I2C 設備驅動程序的開發
                  • I2C 設備驅動一般結構
                    一個具體的 I2C 設備驅動需要實現兩個方面的接口,一方面是對 I2C core 層的接口,用以掛接 I2C adapter 來實現對 I2C 總線及 I2C 設備具體的訪問方法, 包括要實現 probe,remove,detect 等接口函數;另一方面是對用戶應用層的接 口,提供用戶程序訪問 I2C 設備的接口,包括實現 open,release,read,write 以及最重要的 ioctl 等標准文件操作的接口函數。 對 I2C core 層的接口函數的具體功能解釋如下:
                    probe:I2C driver 進行設備綁定的回調函數。 remove:I2C driver 解除設備綁定的回調函數。 detect:I2C 設備探測回調函數,它會識別所支持的設備(返回 0 表示支持, 否則返回-ENODEV);此外,需要定義一個供探測的地址列表(address_list)和 一個設備類型(class),這樣使那些僅匹配設備類型的 i2c 總線被探測到。例如, 對 於 一 個 自 動 監 測 硬 件 芯 片 的 驅 動 將 會 設 置 它 的 class 域 為 I2C_CLASS_HWMON,只有那些 class 域為 I2C_CLASS_HWMON 的控制器能 夠被驅動探測。
                    • 常用數據結構解析
                      i2c_adapter
                      struct i2c_adapter {
                      struct module *owner; /* 所屬模塊 */ unsigned int id; /* algorithm 的類型,定義於 i2c-id.h,以 I2C_ALGO_開始 */ unsigned int class; const struct i2c_algorithm *algo; /* 總線通信方法結構體指針 */ void *algo_data; /* algorithm 數據 */ struct rt_mutex bus_lock; int timeout; /* 超時時間,以 jiffies 為單位 */ int retries; /* 重試次數 */ struct device dev; /* 控制器設備 */ int nr; char name[48]; /* 控制器名稱 */ struct completion dev_released; /* 用於同步 */ struct mutex userspace_clients_lock; struct list_head userspace_clients;
                      };
                      i2c_adapter 對應於物理上的一個控制器。一個 I2C 控制器需要 i2c_algorithm 中提供的通信函數來控制控制器上產生特定的訪問周期。

                      i2c_algorithm
                      struct i2c_algorithm {
                      /* I2C 傳輸函數指針 */ int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); /* smbus 傳輸函數指針 */ int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); /* 返回控制器支持的功能 */ u32 (*functionality) (struct i2c_adapter *);
                      }; i2c_algorithm中的關鍵函數master_xfer()用於產生I2C訪問周期需要的信號, 以 i2c_msg(即 I2C 消息)為單位。

                      i2c_msg
                      struct i2c_msg {
                      __u16 addr; /* 從設備地址 */ __u16 flags; /* 消息類型 */ __u16 len; /* 消息長度 */ __u8 *buf; /* 消息數據 */
                      };
                      i2c_msg 是 I2C 傳輸的基本單位,它包含了從設備的具體地址,消息的類型 以及要傳輸的具體數據信息。每個 I2C 消息傳輸前,都會產生一個開始位,緊接 著傳送從設備地址,然後開始數據的發送或接收,對最後的消息還需產生一個停止位。
                      i2c_client
                      struct i2c_client {
                      unsigned short flags; /* 標志 */ unsigned short addr; /* 低 7 位的芯片地址 */ char name[I2C_NAME_SIZE]; /* 設備名稱 */ struct i2c_adapter *adapter; /* 依附的 i2c_adapter */ struct i2c_driver *driver; /* 依附的 i2c_driver */ struct device dev; int irq; /* 設備使用的中斷號 */ struct list_head detected;
                      };
                      i2c_client 對應於真實的物理設備,每個 I2C 設備都需要一個 i2c_client 來描 述。
                      i2c_driver
                      struct i2c_driver {
                      unsigned int class; int (*attach_adapter)(struct i2c_adapter *); /* 依附 i2c_adapter 函數指針 */ int (*detach_adapter)(struct i2c_adapter *); /* 脫離 i2c_adapter 函數指針 */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); void (*alert)(struct i2c_client *, unsigned int data); int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver; const struct i2c_device_id *id_table; /* 該驅動所支持的設備 ID 表 */ int (*detect)(struct i2c_client *, struct i2c_board_info *); /* 設備探測函數 */ const unsigned short *address_list; /* 驅動支持的設備地址 */ struct list_head clients; /* 掛接探測到的支持的設備 */
                      };
                      i2c_driver 對應一套驅動方法,其主要成員函數是 probe()、remove()、 suspend()、resume()等,另外id_table是該驅動所支持的I2C設備的ID表。i2c_driver 與 i2c_client 的關系是一對多,一個 i2c_driver 上可以支持多個同等類型的 i2c_client。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved