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

本文介绍如何通过应用程序直接操作I2C设备,包括打开控制器设备文件、使用ioctl进行读写操作的具体步骤。适用于简单读写设备如EEPROM、DHT12等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常情况下,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.youkuaiyun.com/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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值