linux_驱动_iic总线获取si7006温湿度

应用层si7006.c

复制代码
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include "head.h"

int main(int argc,char const *argv[])
{
    int tem,hum;
    float tem1,hum1;
    int fd = open("/dev/si7006",O_RDWR);
    if(fd < 0)
    {
        printf("设备文件打开失败\n");
        exit(-1);
    }
    while(1)
    {
        //获取数据
        ioctl(fd,GET_HUM,&hum);
        ioctl(fd,GET_TEM,&tem);

        //大小端转换
        hum = ntohs(hum);
        tem = ntohs(tem);

        //计算数据
        hum1 = 125.0*hum/65536-6;
        tem1 = 175.72*tem/65536-46.85;
        printf("tem=%f,hum=%f\n",tem1,hum1);
        sleep(1);
    }
    return 0;
}

驱动层myiic.c

复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/device.h>
#include "head.h"

unsigned int major;
struct class *cls;
struct device *dev;
struct i2c_client *client1;

// 读取温湿度的函数
int i2c_read_hum_tem(char reg)
{
    short value;
    char r_buf[] = {reg};
    int ret;
    // 封装消息
    struct i2c_msg r_msg[] = {
        [0] = {
            .addr = client1->addr,
            .flags = 0,
            .len = sizeof(r_buf),
            .buf = r_buf,
        },
        [1] = {
            .addr = client1->addr,
            .flags = 1,
            .len = 2,
            .buf = (char *)&value,
        },
    };
    // 将消息传送
    ret = i2c_transfer(client1->adapter, r_msg, 2);
    if (ret != 2)
    {
        printk("消息传输失败\n");
        return -EIO;
    }
    return value; // 将读取到的温度和湿度返回
}

int si7006_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

long si7006_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int tem, hum, ret;
    switch (cmd)
    {
    case GET_HUM: // 读取湿度
        // 读取湿度的逻辑
        hum = i2c_read_hum_tem(0XE5);
        ret = copy_to_user((void *)arg, &hum, 4);
        if (ret < 0)
        {
            printk("向用户拷贝数据失败\n");
            return ret;
        }
        break;
    case GET_TEM: // 读取温度
                  // 读取温度的逻辑
        tem = i2c_read_hum_tem(0XE3);
        ret = copy_to_user((void *)arg, &tem, 4);
        if (ret < 0)
        {
            printk("向用户拷贝数据失败\n");
            return ret;
        }
        break;
    }
    return 0;
}

int si7006_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

struct file_operations fops = {
    .open = si7006_open,
    .unlocked_ioctl = si7006_ioctl,
    .release = si7006_close,
};

// 给对象分配空间并初始化
int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    client1 = client;
    // 字符设备驱动的注册
    major = register_chrdev(0, "si7006", &fops);
    if (major < 0)
    {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功\n");
    // 自动创建设备节点
    cls = class_create(THIS_MODULE, "si7006");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");
    // 向上提交设备节点
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "si7006");
    if (IS_ERR(dev))
    {
        printk("向上提交节点信息失败\n");
        return -PTR_ERR(dev);
    }
    printk("向上提交节点信息成功\n");
    // 硬件信息的获取
    return 0;
}

// remove 和设备信息分离时执行
int i2c_remove(struct i2c_client *client)
{
    // 销毁节点
    device_destroy(cls, MKDEV(major, 0));
    // 目录和设备信息的销毁
    class_destroy(cls);
    // 驱动的注销
    unregister_chrdev(major, "si7006");
    return 0;
}

// 构建设备树匹配信息
struct of_device_id oftable[] = {
    {
        .compatible = "vivi,si7006",
    },
    {

    },
};

// 分配iic驱动对象并初始化
struct i2c_driver i2c_drv = {
    .probe = i2c_probe,
    .remove = i2c_remove,
    .driver = {
        .name = "si7006",
        .of_match_table = oftable, // 设备树匹配
    },
};
module_i2c_driver(i2c_drv);
MODULE_LICENSE("GPL");

在根节点外添加设备树

复制代码
*********添加************
在stm32mp157a-fsmp1a.dts文件的根节点外部,添加如下内容:

&i2c1 {
    pinctrl-names = "default", "sleep";//关于pinctrl的一个列表,"default"表示默认工作模式
     //"sleep"表示低功耗模式
    pinctrl-0 = <&i2c1_pins_b>;//-0表示pinctrl-name列表中第一个值default
    pinctrl-1 = <&i2c1_sleep_pins_b>;
 //在stm32mp15-pinctrl.dtsi文件中存在内核添加的各种用于管脚复用的节点,i2c1_pins_a就是其中之一

    i2c-scl-rising-time-ns = <100>;
    i2c-scl-falling-time-ns = <7>;
    status = "okay";
    /delete-property/dmas;  //删除不必要的属性
    /delete-property/dma-names;
    
    si7006@40{  //添加SI7006的从机节点
        compatible="hqyj,si7006";
        reg=<0X40>;
    };

};

效果演示

相关推荐
Dreamboat-L1 小时前
云服务器上部署nginx
java·服务器·nginx
广州灵眸科技有限公司1 小时前
瑞芯微(EASY EAI)RV1126B CAN使用
linux·网络·单片机·嵌入式硬件
咕噜签名-铁蛋2 小时前
AI扣子:重构人机交互的智能连接点
服务器
AI科技星3 小时前
张祥前统一场论宇宙大统一方程的求导验证
服务器·人工智能·科技·线性代数·算法·生活
魂万劫4 小时前
如何在虚拟机VM上|Linux环境内安装windows
linux·运维·服务器·windows
序属秋秋秋4 小时前
《Linux系统编程之进程控制》【进程等待】
linux·c语言·c++·进程·系统编程·进程控制·进程等待
zfj3214 小时前
top 命令中的 wa (IO wait) 指标,理论上几乎完全是由磁盘IO(包括swap)引起的,而不是网络IO
linux·网络·top·iowait
Xの哲學4 小时前
Linux网卡注册流程深度解析: 从硬件探测到网络栈
linux·服务器·网络·算法·边缘计算
不哦罗密经4 小时前
python相关
服务器·前端·python
用户6135411460164 小时前
libicu-62.1-6.ky10.x86_64.rpm 安装步骤详解(麒麟V10系统)
linux