Linux应用程序直接调用I2C控制器实现的设备驱动

版权声明:本文为博主原创文章,未经博主允许转载。 https://blog.csdn.net/jklinux/article/details/80888717

参考内核源码里的dev-interface文档.

在linux内核里i2c控制器驱动好后, i2c设备驱动方式通常由设备驱动通过控制器读写i2c设备数据、再提供应用程序调用和访问的接口.
除此设备驱动方工外,驱动好的i2c控制器也可提供应用程序直接调用控制器收发i2c设备数据的接口(dev-interface).这接口适用于一些没涉及到中断的简单设备,如dht12, eeprom等设备.

内核配置里的dev-interface选项:

make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Device Drivers  --->
    <*> I2C support  --->
        <*>   I2C device interface

选上此项,更新内核镜像重启系统后,应就可以在/dev目录下发生i2c-*的设备文件,应用程序就是通过这些设备文件调用控制器的.
设备文件的命名方式, 如序号为0的控制器,对应的设备文件应为/dev/i2c-0.

依照内核文档dev-interface的说明, i2c_smbus_xxxx_xxxx的操作函数无法实现操作, 只有ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)的方式测试成功.

操作步骤:

1  打开要调用的控制器设备文件
    int fd = open("/dev/i2c-0", O_RDWR);


2  设置超时和传输失败时的重试次数(非必须作)
    ioctl(fd, I2C_TIMEOUT, 10);
    ioctl(fd, I2C_RETRIES, 2);


3  准备好需要传输的数据. 

    struct i2c_msg {
        __u16 addr; /* slave address            */
        __u16 flags;  //写为0, 读为I2C_M_RD
        __u16 len;      /* msg length               */
        __u8 *buf;      /* pointer to msg data          */
    };

    struct i2c_rdwr_ioctl_data {
            struct i2c_msg *msgs;  /* ptr to array of simple messages */
            int nmsgs;             /* number of messages to exchange */
    };

    ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset); 
        //调用此ioctl函数类似设备驱动里调用i2c_transfer函数。调用一次,只会在完成时发出一个停止信号,不管发出了多少个i2c_msg。 而且每一个i2c_msg都会有一个开始信号.

获取dht12温湿度传感器的例子:

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

#define DHT12_ADDR  0x5c

int main(void)
{
    int fd, i;
    char addr = 0, data[5];

    fd = open("/dev/i2c-0", O_RDWR);
    if (fd < 0)
        return 1;

    ioctl(fd, I2C_TIMEOUT, 10);
    ioctl(fd, I2C_RETRIES, 2);


    struct i2c_msg msgs[2] = {
        {DHT12_ADDR, 0, 1, &addr},
        {DHT12_ADDR, I2C_M_RD, 5, data},
    };

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

    if (ioctl(fd, I2C_RDWR, &idata) < 0)
    {
        perror("ioctl");
        return 2;
    }

    for (i = 0; i < 5; i++)
        printf("%d ", data[5]);

    close(fd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jklinux/article/details/80888717