树莓派学习笔记——Linux I2C驱动说明

1.前言

【 linux内核说明】
通常情况下,I2C设备由内核驱动控制,但是某些情况下I2C设备也可由用户空间控制。如果在用户空间控制I2C设备,需要访问/dev目录中所提供的接口,在使用I2C设备之前必须要载入i2c-dev设备。
每一个已经注册的IC设备都有一个编号,该编号从0开始计算。可以查看/sys/class/i2c-dev目录以获得I2C适配器的信息,或者使用i2cdetect工具查看I2C适配器。i2cdetect是一个简单易用的I2C工具包。
【 树莓派学习笔记——I2C Tools 学习笔记】

2.C语言的例子

让我们从一个简单的C语言的例子开始Linux I2C设备的使用。在开始之前需要包括 linux/i2c-dev.h。然后需要决定访问的I2C适配器,可以查看/sys/class/i2c-dev,或者使用i2cdetect - l命令。

接着便可打开文件,请看示例代码
  int file;
  int adapter_nr = 1; /* I2C适配器编号 */
  char filename[20];
 
  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* 打开失败 */
    exit(1);
  }

打开设备时,必须确定I2C从机地址。
  int addr = 0x40; /* I2C 从机地址 */
  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* 打开失败 */
    exit(1);
  }

完成了基本设置,下面便可以使用SMBUS指令或纯I2C函数与芯片通信。 SMBUS函数形式是一个很不错的选择。
 __u8 register = 0x10; /* I2C从机 寄存器地址 */
  __s32 res;
  char buf[10];
  /* 使用SMBus函数 */
  res = i2c_smbus_read_word_data(file, register);
  if (res < 0) {
    /* 错误 */
  } else {
    /* 成功读取到一个字 */
  }
  /* 使用I2C Write, 等价于i2c_smbus_write_word_data(file, register, 0x6543) */
  buf[0] = register;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) ! =3) {
    /* 错误*/
  }
  /* 使用I2C Read, 等价于 i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* 错误 */
  } else {
    /* buf[0]为读取到的字节 */
  }

3.SMBUS详细说明


【内核说明】
标记符
长度
说明
S
1 bit
I2C启动
P
1 bit
I2C停止
Rd/Wr
1 bit
控制字中的读写标志位,读操作为1,写操作为0
A, NA
1 bit
应答标志
Addr
7 bits
7位I2C地址
Data
8 bit
字节数据
Comm
8 bits
命令字节,可理解为I2C设备寄存器地址
[..]
N char
I2C设备返回的数据

【1】__s32 i2c_smbus_write_quick(int file, __u8 value);
发送一个写控制字,可用于测试I2C设备是否存在。
S Addr Rd [A] [Data] NA P

【2】__s32 i2c_smbus_read_byte(int file);
发送一个读控制字,并从I2C设备中读取一个字节。
S Addr Rd [A] [Data] NA P

【3】__s32 i2c_smbus_write_byte(int file, __u8 value);
发送一个写控制字,并向I2C设备中写入一个字节。
S Addr Wr [A] Data [A] P

【4】__s32 i2c_smbus_read_byte_data(int file, __u8 command);
向I2C设备发送一个写控制字+控制指令(寄存器地址),再发送一个读控制字,此时I2C从设备内部的读写指针转移到指定的位置,并返回一个字节,最后返回一个无应答NA。
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P

【5】__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
向I2C设备发送一个写控制字+控制指令(寄存器地址),紧接着发送指令内容(寄存器内容,单字节)。
S Addr Wr [A] Comm [A] Data [A] P

【6】__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 *values);
向I2C设备发送一个写控制字+控制指令(寄存器地址),再发送一个读控制字,此时I2C从设备内部的读写指针转移到指定的位置,并连续返回多个字节,I2C主机读取到一定数量字节内容之后发送无应答NA。
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P

【7】__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values);
向I2C设备发送一个写控制字+控制指令(寄存器地址),接着发送发送指令内容(寄存器内容,多字节)
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P

【注意点1】
这些函数如果返回-1代表操作失败。在一些具有写功能的函数中,返回0代表操作成功,在具有读功能的函数中,返回读取的字节数(除i2c_smbus_read_block_data)。读块(block)操作时不应超过32个字节。
【注意点2】
树莓派不支持以下函数。
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values);

4.参考资料

【 i2c_smbus_write_block_data 和 i2c_smbus_write_i2c_block_data区别】
【 I2C操作笔记——以 AT24C04为例】

你可能感兴趣的:(树莓派学习笔记——Linux I2C驱动说明)