18 i2c控制器之应用程序的调用

时间:2022-04-21 17:55:09

通常情况下,i2c设备驱动里应是通过调用已驱动好的i2c控制器来实现i2c设备的操作的。但i2c控制器驱动里也直接提供应用程序调用的接口,可用于实现应用程序直接读写操作的设备。
//注意这种方法只适用于仅需读写操作的简单设备. 如eeprom, dht12这些设备.


使用这种方法前,除i2c控制器需要驱动好外,内核里也需要选上:

make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
Device Drivers --->
I2C support --->
<*> I2C device interface

正常情况下/dev/目录下应出现i2c-x 设备文件,用于应用程序调用相应的控制器使用.


应用程序的调用方法参考: 内核源码目录 Documentation/i2c/dev-interface
// smbus相关的操作方法需要控制器驱动的支持,并不是所有的方案都可以使用。
通用的方法可以是:

1.  打开要操作的控制器设备文件, 如需操作第0个i2c控制器:
int fd = open("/dev/i2c-0", O_RDWR);
if (fd < 0)
{
perror("open i2c controller");
return 1;
}

2
. 使用ioctl(fd, I2C_RDWR, struct i2c_rdwr_ioctl_data *dat)来读/写设备
struct i2c_rdwr_ioctl_data {
struct i2c_msg *msgs; //struct i2c_msg表示一条i2c的操作消息,每个i2c_msg都会有一个start信号
__u32 nmsgs; //消息的个数
};
//一定要注意: ioctl(fd, I2C_RDWR, ...)调用一次才会在结束操作前发出仅仅一个停止信号,不管struct i2c_msg的消息有多少条(需要根据设备的传输时序里的开始信号及停止信号确定消息的个数和ioctl的调用次数)

struct i2c_msg {
__u16 addr; /* 设备地址,不包含读写位 */
__u16 flags; // 0表示写, I2C_M_RD表示读
__u16 len; /* 数据长度(不包括地址) */
__u8 *buf; /* 数据缓冲区的长度 */
};


dht12的i2c工作方式原理参考: http://blog.csdn.net/jklinux/article/details/74199964

18 i2c控制器之应用程序的调用
根据里面的时序要求可得知,ioctl(fd, I2C_RDWR, ..)需要调用一次(有一个停止信号),共需发出两条消息(有两个开始信号,而且这两个信号间没有停止信号)

dht12接到板上的第0个i2c控制器接口后的测试代码:

/* app.c */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

#define DHT12_ADDR 0x5c

unsigned char data[5];
int main(void)
{
int fd;

fd = open("/dev/i2c-0", O_RDWR);
if (fd < 0)
{
perror("open i2c controller");
return 1;
}
///////////////////////////////////////
// struct i2c_msg表示一条i2c的操作消息,每个i2c_msg都会有一个start信号.
// ioctl调用一次才会产生一个停止信号,不管一次发出多少条消息

unsigned char reg = 0x00;
unsigned char datas[5];

struct i2c_msg msgs[2] = {
{DHT12_ADDR, 0, 1, &reg},
{DHT12_ADDR, I2C_M_RD, sizeof(datas), datas},
};


struct i2c_rdwr_ioctl_data rdat = {
.msgs = msgs,
.nmsgs = 2,
};

if (ioctl(fd, I2C_RDWR, &rdat) < 0)
{
perror("i2c rdwr failed\n");
return 3;
}

int i;
for (i = 0; i < sizeof(datas); i++)
printf("%02d ", datas[i]);
printf("\n");

//////////////////////////////////////

close(fd);
return 0;
}