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

1.前言

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

2.C语言的例子

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

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

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

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

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);

猜你喜欢

转载自blog.csdn.net/sam0535/article/details/78547956