Linux I2C驱动个人理解(二)

来源:互联网 发布:淘宝手机版店招制作 编辑:程序博客网 时间:2024/05/22 10:42

I2C的核心也就是I2C总线驱动如何设备驱动如何连接起来的,下面一组函数表示主要的。

1.i2c_adapter.

int i2c_add_adapter(struct i2c_adapter *adap);

int i2c_del_adapter(struct i2c_adapter *adap);

2.i2c_driver

int i2c_register_driver(struct module *owner ,struct i2c_driver * driver);

  int i2c_del_driver(struct i2c_driver * driver);

inline int i2c_add_driver(struct i2c_driver * driver);

3.i2c_client

int i2c_attach_client(struct i2c_client *client);

int i2c_detach_client(struct i2c_client *client);

4.

int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs,int num);

int i2c_master_send(struct i2c_client *client ,const char *buf ,int count);

int i2c_master_recv(struct i2c_client *client ,const char *buf ,int count);

以上函数原型都可以在i2c-core.c中找到,有助于理解。

/**********************************************************************************************************************************************/

说一下i2c设备驱动

1.首先是初始化

static  struct i2c_driver  xx_driver={

.driver={

.name="xx",

},

.probe=xx_probe,

.remove=xx_remove,

.id_table=xx_id,

};

2.加载与卸载

static int  __init xx_init(void)

{

return  i2c_add_driver(&xx_driver);

}

static int __exit xx_exit(void)

{

i2c_del_driver(&xx_driver);

}

3.读写

struct i2c_msg msg[2];

/*******写******/

msg[0].addr=client->addr;

msg[0].flags=0;

msg[0].len=1;

msg[0].buf=&offs;

/*********读******/

msg[0].addr=client->addr;

msg[0].flags=I2C_M_RD;

msg[0].len=sizeif(buf);

msg[0].buf=&buf[0];

i2c_transfer(client->adapter,msg,2);

4.ioctl

i2cdev_ioctl()常用功能:I2C_SLAVE(设置从地址),I2C_RETRIES(没有收到ACK充实次数,默认为1),I2C_TIMEOUT(超时),I2C_RDWR。

demo:

#include <stdio.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <string.h>#include <stdlib.h>#define I2C_DEFAULT_TIMEOUT     1#define I2C_DEFAULT_RETRY       3/* * fd       : 文件描述符 * timeout  : 发送超时时间 * retry    : 重复发送次数 *///重复发送次数可以设多一点,在调试的时候,只设置了一次,导致有时候发送会失败。int i2c_set(int fd, unsigned int timeout, unsigned int retry){    if (fd == 0 )        return -1;    if (ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT) < 0)        return -1;    if (ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY) < 0)        return -1;    return 0;}/* * fd   : 文件描述符 * addr : i2c的设备地址 * reg  : 寄存器地址 * val  : 要写的数据 * 描述 :从指定地址写数据 */int i2c_byte_write(int fd, unsigned char addr, unsigned char reg, unsigned char val){    int ret = 0;    unsigned char outbuf[2];    struct i2c_rdwr_ioctl_data packets;    struct i2c_msg messages;    packets.nmsgs = 1;    packets.msgs = &messages;    //发送要读取的寄存器地址    messages.addr = addr;    messages.flags = 0;    messages.len = 2;       //寄存器地址加数据,共发送2个字节    messages.buf = outbuf;    outbuf[0] = reg;    outbuf[1] = val;    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets);   //读出来    if (ret < 0)        ret = -1;    return ret;}/*   * fd   : 文件描述符 * addr : i2c的设备地址 * reg  : 寄存器地址 * val  : 要写的数据 * len  : 数据长度 * 描述 :从指定地址写数据 *        24c02以8字节为1个page,如果在一个page里面写,写的字节长度超过这个page的末尾, *        就会从page的开头写,覆盖开头的内容 */int i2c_nbytes_write(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len){    int ret = 0;    struct i2c_rdwr_ioctl_data packets;    struct i2c_msg messages;    int i;    packets.nmsgs = 1;    packets.msgs = &messages;    //发送要读取的寄存器地址    messages.addr = addr;    messages.flags = 0;         //write    messages.len = len + 1;     //数据长度    //发送数据    messages.buf = (unsigned char *)malloc(len+1);    if (NULL == messages.buf)    {        ret = -1;        goto err;    }    messages.buf[0] = reg;    for (i = 0; i < len; i++)    {        messages.buf[1+i] = val[i];    }    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets);//读出来    if (ret < 0){        printf("write error!\n");        return -1;    }err:    free(messages.buf);    return ret;}/*   * fd   : 文件描述符 * addr : i2c的设备地址 * val  : 保存读取数据 * 描述 :从当前地址读取一个字节数据 */int i2c_byte_read(int fd, unsigned char addr, unsigned char *val){    int ret = 0;    struct i2c_rdwr_ioctl_data packets;    struct i2c_msg messages;    packets.nmsgs = 1;              //数据帧类型只有一种,读操作,只需要发送一个起始信号,因此是1    packets.msgs = &messages;    //发送要读取的寄存器地址    messages.addr = addr;           //i2c设备地址    messages.flags = I2C_M_RD;      //读操作    messages.len = 1;               //数据长度    messages.buf = val;             //读取的数据保存在val    ret = ioctl (fd, I2C_RDWR, (unsigned long)&packets);  //发送数据帧    if (ret < 0)        ret = -1;    return ret;}/* * fd   : 文件描述符 * addr : i2c的设备地址 * reg  : 寄存器地址 * val  : 保存读取的数据 * len  : 读取数据的长度 * 描述 :读取达到eeprom的末尾时,会读取最开头的字节 */int i2c_nbytes_read(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len){    int ret = 0;    unsigned char outbuf;    struct i2c_rdwr_ioctl_data packets;    struct i2c_msg messages[2];    /* 数据帧类型有2种     * 写要发送起始信号,进行写寄存器操作,再发送起始信号,进行读操作,     * 有2个起始信号,因此需要分开来操作。     */    packets.nmsgs = 2;               //发送要读取的寄存器地址    messages[0].addr = addr;    messages[0].flags = 0;              //write    messages[0].len = 1;                //数据长度    messages[0].buf = &outbuf;          //发送寄存器地址    outbuf = reg;    //读取数据    messages[1].len = len;                           //读取数据长度    messages[1].addr = addr;                         //设备地址    messages[1].flags = I2C_M_RD;                    //read    messages[1].buf = val;    packets.msgs = messages;    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets); //发送i2c,进行读取操作     if (ret < 0)        ret = -1;    return ret;}

0 0
原创粉丝点击