I2C設備聲明以及應用實現

(本文內容涉及的代碼全部取自linux-2.6.36內核中,本文中的部分內容參考了Documentation/i2c/說明文檔)

 

在自己使用8位單片機的時代,i2c就是一種最簡單而且常用的總線,它可以提供一個實現多設備連接的低價低速率的通訊方式。

在開始進行i2c應用編成前先重新瞭解一下i2c的數據格式。

 

Simplesend transaction

===========================

Thiscorresponds to i2c_master_send.

 

  S Addr Wr[A] Data [A] Data [A] ... [A] Data [A] P

 

Simplereceive transaction

===========================

Thiscorresponds to i2c_master_recv

 

  S Addr Rd [A] [Data] A [Data] A ... A [Data]NA P

 

S     (1 bit) : 起始位

P     (1 bit) : 結束位

Rd/Wr(1 bit) : 讀/寫位. Rd = 1, Wr = 0.

A,NA (1 bit) : 接收位.

Addr  (7 bits): I2C 7 位地址,可擴展到10位.

Comm  (8 bits): 命令字.

Data  (8 bits): 數據字

Count(8 bits): 塊長度.

 

在進行編成前首先了解一個比較重要的結構定義:

/* This is thestructure as used in the I2C_SMBUSioctl call */

struct i2c_smbus_ioctl_data {

       __u8read_write;

       __u8command;

       __u32size;

       unioni2c_smbus_data __user *data;

};

 

/* This is thestructure as used in the I2C_RDWRioctl call */

struct i2c_rdwr_ioctl_data {

       structi2c_msg __user *msgs;   /* pointers to i2c_msgs */

       __u32nmsgs;                    /* number of i2c_msgs */

};

上面兩個結構是用來調用對應算法的結構定義,當需要使用I2C_SMBUS算法是即使用struct i2c_smbus_ioctl_data;同理當需要I2_RDWR算法是即調用struct i2c_rdwr_ioctl_data。

struct i2c_msg {

       __u16addr; /* slave address               */

       __u16flags;

#define I2C_M_TEN         0x0010  /* this is a ten bit chip address */

#define I2C_M_RD           0x0001  /* read data, from slave to master */

#define I2C_M_NOSTART              0x4000  /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_REV_DIR_ADDR    0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_IGNORE_NAK       0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_NO_RD_ACK        0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_RECV_LEN            0x0400  /* length will be first received byte */

       __u16len;           /* msg length                          */

       __u8*buf;           /* pointer to msg data                  */

};

上面這個結構從結構注視中可以基本瞭解其功能,它是一個在用戶空間使用的底層結構,i2c_transfer()進行處理這個結構,並且通過i2c-dev與用戶空間進行數據交換。

 

下面開始具體代碼的分析(本代碼使用內核版本爲2.6.36,使用tiny6410開發板進行調試):

/*

 * 本程序實現對AT24C08進行一個字節的讀寫操作

 */

#include<stdio.h>

#include<stdlib.h>

#include<fcntl.h>

#include<linux/i2c.h>

#include<linux/i2c-dev.h>

 

intmain(){

    int res,count;

    struct i2c_rdwr_ioctl_data e2prom;

 

    res = open ("/dev/i2c-0", O_RDWR);      //打開設備文件根據設備具體註冊名打開

    if(res < 0){

        perror ("open i2c0");

    }

 

    e2prom.nmsgs = 2;

    e2prom.msgs =(struct i2c_msg*)malloc(e2prom.nmsgs * sizeof(struct i2c_msg));

 

    if (e2prom.msgs == 0){

        perror ("i2c mem inital");

         return 1;

    }else {

        perror ("i2c mem inital");

    }

   

    sleep (1);

   

    e2prom.nmsgs = 1;

    (e2prom.msgs[0]).len = 2;

    (e2prom.msgs[0]).addr = 0x51; 

    (e2prom.msgs[0]).flags = 0;

    (e2prom.msgs[0]).buf = (unsigned char*)malloc(2);

    (e2prom.msgs[0]).buf[0] = 0x00;

    (e2prom.msgs[0]).buf[1] = 0x88;

 

    if((ioctl(res, I2C_RDWR, (unsigned long)&e2prom)) < 0)

    {

        perror("ioctl I2C_WR");

        return 1;

    }else {

        perror("ioctl I2C_WR");

        printf("Writedata:%d\n",(e2prom.msgs[0]).buf[1]); 

    }

   

    for (count = 3;count != 0; count --){

        printf("delay time%d\n",count);

        sleep(1);

    }

 

    e2prom.nmsgs=2;

    (e2prom.msgs[0]).len = 1;

    (e2prom.msgs[0]).addr = 0x51;

    (e2prom.msgs[0]).flags = 0;

    (e2prom.msgs[0]).buf[0] = 0x00;

    (e2prom.msgs[1]).len = 1;

    (e2prom.msgs[1]).addr = 0x51;

    (e2prom.msgs[1]).flags = I2C_M_RD;

    (e2prom.msgs[1]).buf = (unsignedchar*)malloc(1);

    (e2prom.msgs[1]).buf[0] = 0;

 

    if((ioctl(res,I2C_RDWR,(unsigned long)&e2prom)) < 0)

    {

        perror("ioctl I2C_RD");

        return 1;

    }else {

        perror("ioctl I2C_RD");

    }

 

    printf("Read data=%d\n",(e2prom.msgs[1]).buf[0]);

    close(res);

    return 0;

}

 

配置內核打開CONFIG_S3C_DEV_I2C0,並且加入

s3c_i2c0_set_platdata(NULL);

該函數是plat-samsung中,創建platform_device的功能。

(samsung用戶的福音阿,不需要進行復雜的驅動編程就可以簡單實現i2c設備的操作,但是它是如何與i2c子系統搞上關係的,也看的我一霧水)

 

I2c設備初始化採用Declarethe I2C devices bybus number的方式。

首先創建一個i2c的設備信息。

 

staticstruct i2c_board_infoi2c_devs0[] __initdata = {

    { I2C_BOARD_INFO("ov965x",0x60), },

};

 

然後在mini6410_machine_init中添加註冊功能:

    if (ARRAY_SIZE(i2c_devs0)) {

        i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));

    }

    if (ARRAY_SIZE(i2c_devs1)) {

        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));

    }

 

運行結果:

i2c mem inital: Success

ioctlI2C_WR: Success

Writedata:136

delaytime 3

delaytime 2

delaytime 1

ioctl I2C_RD:Success

Read data =136

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章