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

通常情况下,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

这里写图片描述
根据里面的时序要求可得知,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;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
I2C控制器驱动程序是用于与I2C设备进行通信的软件模块。它允许应用程序通过I2C总线与外部设备进行数据交换。根据引用和引用的描述,I2C控制器驱动程序可以分为两种模式:用户模式设备驱动和普通设备驱动。 用户模式设备驱动是一种依赖于i2c-dev驱动的驱动程序。它要求应用程序员具备一定的硬件知识,了解I2C设备的时序、地址等信息。使用用户模式设备驱动时,应用程序员需要直接调用I2C控制器来实现设备的读写操作。 普通设备驱动是一种更简单的驱动程序,应用程序员可以像读写文件一样使用它。普通设备驱动隐藏了底层I2C控制器的细节,提供了一组简单的API应用程序使用。应用程序员不需要了解I2C设备的底层细节,只需要调用相应的API来进行数据交换。 下面是一个示例,演示了如何使用普通设备驱动程序进行I2C设备的读写操作: ```c #include <linux/i2c-dev.h> #include <fcntl.h> #include <unistd.h> int main() { int file; char *filename = "/dev/i2c-0"; // I2C设备文件路径 int addr = 0x50; // I2C设备地址 // 打开I2C设备文件 if ((file = open(filename, O_RDWR)) < 0) { printf("Failed to open the bus.\n"); return 1; } // 设置I2C设备地址 if (ioctl(file, I2C_SLAVE, addr) < 0) { printf("Failed to acquire bus access and/or talk to slave.\n"); return 1; } // 向I2C设备写入数据 char buffer[2] = {0x01, 0x02}; if (write(file, buffer, 2) != 2) { printf("Failed to write to the I2C device.\n"); return 1; } // 从I2C设备读取数据 char data[2]; if (read(file, data, 2) != 2) { printf("Failed to read from the I2C device.\n"); return 1; } // 关闭I2C设备文件 close(file); return 0; } ``` 这是一个使用C语言编写的简单示例,演示了如何使用普通设备驱动程序进行I2C设备的读写操作。在示例中,我们首先打开I2C设备文件,然后设置I2C设备地址。接下来,我们向I2C设备写入数据,并从I2C设备读取数据。最后,我们关闭I2C设备文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值