IIC(Inter-Integrated Circuit,集成电路总线)由飞利浦公司在1980年代提出,此接口使用两根信号线实现一主多从的通信,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
Rockchip I2C 控制器支持下列功能︰
RK3568最大支持6组I2C,开发板上引出了两路,分别为I2C1和I2C5,位于此处
下面以操作I2C5下挂一个at24c32 为例介绍如何进行I2C读写。at24c32是32kbit的EEPROM,此器件I2C地址为0x50,寄存器为16位长度。每一个寄存器就是一个字节的存储单元。接线图如下
"/dev/i2c-*"的节点需要root权限才能执行读写操作,使用命令行或者C语言编译出来的程序操作i2c都需要root权限。如果是ssh或者使用LX终端的,先执行如下命令获取root权限。
sudo su
Linux下提供了i2ctool来操作i2c,其中比较实用的两个工具是i2cdetect和i2ctransfer。另外还有i2cget和i2cset其实是i2ctransfer的简化版本。板上的系统自带了这些命令
检测i2c5下面有哪些设备
i2cdetect -y 5
连续读取at24c32从0x0000开头的三个字节数据。其中w2代表要连续写入2字节,由于寄存器地址为2字节即16位,0x50是其I2C器件地址,r3代表要连续读操作3个寄存器
i2ctransfer -f -y 5 w2@0x50 0x00 0x00 r3
连续写入at24c32从0x0000开头的三个字节数据0x01 0x02 0x03。其中w5代表要连续写入5字节,由于寄存器地址为2字节即16位,然后还有三个字节的数据,0x50是其I2C器件地址
i2ctransfer -f -y 5 w5@0x50 0x00 0x00 0x01 0x02 0x03
操作结果如下图
通过连接 libperipheral_api.a 静态库,可以使用C语言调用以下接口来操作I2C
/**
* @name: user_i2c_open
* @description: 打开i2c设备
* @param i2c_num: i2c号,板上引出的i2c包括 1 5
* @return 大于等于0 - 成功,返回值为文件描述符 小于0 - 失败
*/
int user_i2c_open(int i2c_num);
/**
* @name: user_i2c_read
* @description: 从i2c设备读取数据
* @param fd: 文件描述符,user_i2c_open返回值
* @param slave_addr: i2c设备地址
* @param reg_addr: 寄存器地址的指针
* @param addr_len: 寄存器地址长度
* @param buf: 读入数据的指针
* @param len: 读入数据的长度
*
* @return 等于0 - 成功 小于0 - 失败
*/
int user_i2c_read(int fd, unsigned short slave_addr, unsigned char *reg_addr, unsigned char addr_len, unsigned char *buf, unsigned short len);
/**
* @name: user_i2c_read
* @description: 从i2c设备读取数据
* @param fd: 文件描述符,user_i2c_open返回值
* @param slave_addr: i2c设备地址
* @param reg_addr: 寄存器地址的指针
* @param addr_len: 寄存器地址长度
* @param buf: 写入数据的指针
* @param len: 写入数据的长度
*
* @return 等于0 - 成功 小于0 - 失败
*/
int user_i2c_write(int fd, unsigned short slave_addr, unsigned char *reg_addr, unsigned char addr_len, unsigned char *buf, unsigned short len);
/**
* @name: user_i2c_close
* @description: 关闭i2c
* @param fd: 文件描述符,user_i2c_open 返回值
* @return 始终等于0,无意义
*/
int user_i2c_close(int fd);
测试demo如下,以操作挂在I2C5下的AT24C32为例
#include "peripheral_api.h"
void i2c_api_test(void)
{
int fd = -1;
int ret = 0;
unsigned char reg[2] = {0x00, 0x00};
unsigned char buf_write[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
unsigned char buf_read[5] = {0};
fd = user_i2c_open(5);
if (fd < 0) {
printf("user_i2c_open fail\n");
return;
}
ret = user_i2c_write(fd, 0x50, reg, 2, buf_write, 5);
if (ret < 0) {
printf("user_i2c_write fail\n");
user_i2c_close(fd);
return;
}
usleep(100 * 1000);
ret = user_i2c_read(fd, 0x50, reg, 2, buf_read, 5);
if (ret < 0) {
printf("user_i2c_read fail\n");
user_i2c_close(fd);
return;
}
user_i2c_close(fd);
if (memcmp(buf_write, buf_read, 5) == 0) {
printf("buf_write buf_read same\n");
} else {
printf("buf_write buf_read diff %d %d %d %d %d\n", buf_read[0], buf_read[1], buf_read[2], buf_read[3], buf_read[4]);
}
return;
}
int main()
{
i2c_api_test();
return 0;
}
编译并运行结果如下
root@linaro-alip:/home/linaro# ./test
buf_write buf_read same