I2C设备的无驱访问

来源:互联网 发布:中小企业数据统计 编辑:程序博客网 时间:2024/04/29 11:18

做中间件,最首要的原则就是内聚,由于驱动程序的特殊性,不可避免的要开源,这对知识产权与中间件的可移植性都有负面的影响。但很多情况下,Kernel对于通用设备都提供了User Space的访问接口,可以在应用程序中直接访问设备,例如,本文将要提到的i2c-dev,就避免的在中间件发布时,提供驱动程序的问题。
i2c-dev提供了i2c设备的/dev接口,该用户层接口基于i2c adapter访问连接的i2c设备。要使用i2c的/dev接口,要在kernel中的打开i2c device interface的支持:driver->I2C support->I2C device interface,加载新的kernel后,可以在/dev目录下找到i2c的adapter,命名方式采用i2c-%d(i2c-0, i2c-1, etc.)
User Space程序编写:

打开设备:

  int file;  int adapter_nr = 2; /* probably dynamically determined */  char filename[20];  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);  file = open(filename, O_RDWR);  if (file < 0) {    /* ERROR HANDLING; you can check errno to see what went wrong */    exit(1);  }

设置i2c设备地址:

采用SMBus方式访问的i2c设备,要单独设置i2c设备的地址:

int addr = 0x40; /* The I2C address */if (ioctl(file, I2C_SLAVE, addr) < 0) {    /* ERROR HANDLING; you can check errno to see what went wrong */    exit(1);  }

通过SMBus方式访问i2c设备:

__u8 register = 0x10; /* Device register to access */__s32 res;char buf[10];/* Using SMBus commands */res = i2c_smbus_read_word_data(file, register);if (res < 0) {  /* ERROR HANDLING: i2c transaction failed */} else {  /* res contains the read word */}/* Using I2C Write, equivalent of   i2c_smbus_write_word_data(file, register, 0x6543) */buf[0] = register;buf[1] = 0x43;buf[2] = 0x65;if (write(file, buf, 3) ! =3) {  /* ERROR HANDLING: i2c transaction failed */}/* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */if (read(file, buf, 1) != 1) {  /* ERROR HANDLING: i2c transaction failed */} else {  /* buf[0] contains the read byte */}

上面代码中用到的smbus系列接口在标准kernel中未提供,原型在i2c-tools这个工具里面。
同时,i2c device interface还支持i2c协议直接操作,例程如下:

bool I2cReadBlock( int fd, uint8_t reg, uint8_t * data, int16_t len ){    struct i2c_rdwr_ioctl_data _data;    struct i2c_msg _msg[2];    int _retry  =   0, _len;    _data.nmsgs =   2;    _data.msgs  =   &_msg;    _data.msgs[0].addr  =   I2C_DEV_ADDR;    _data.msgs[0].flags =   0;    _data.msgs[0].len   =   1;    _data.msgs[0].buf   =   &reg;    _data.msgs[1].addr  =   I2C_DEV_ADDR;    _data.msgs[1].flags =   I2C_M_RD;    _data.msgs[1].len   =   len;    _data.msgs[1].buf   =   data;    ioctl( fd, I2C_RDWR, ( unsigned long )&_data );    return TRUE;}bool I2cWriteBlock( int fd, uint8_t reg, uint8_t * data, int16_t len ){    struct i2c_rdwr_ioctl_data _data;    struct i2c_msg _msg;    uint8_t _buf[ 1 + len ];    int _retry  =   0;    _data.nmsgs =   1;    _data.msgs  =   &_msg;    _buf[0] =   reg;    memcpy( _buf + 1, data, len );    _data.msgs[0].addr  =   I2C_DEV_ADDR;    _data.msgs[0].flags =   0;    _data.msgs[0].len   =   1 + len;    _data.msgs[0].buf   =   _buf;    ioctl( fd, I2C_RDWR, ( unsigned long )&_data );    return TRUE;}
0 0
原创粉丝点击