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

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值