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

news2025/1/10 20:55:39

应用层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>;
    };

};

效果演示

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/836031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学生信息管理系统springboot学校学籍专业数据java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 学生信息管理系统springboot 系统3权限&#xff1a;超…

C语言 函数指针详解

一、函数指针 1.1、概念 函数指针&#xff1a;首先它是一个指针&#xff0c;一个指向函数的指针&#xff0c;在内存空间中存放的是函数的地址&#xff1b; 示例&#xff1a; int Add(int x&#xff0c;int y) {return xy;} int main() {printf("%p\n",&Add);…

Linux tcpdump 命令详解

简介 用简单的话来定义tcpdump&#xff0c;就是&#xff1a;dump the traffic on a network&#xff0c;根据使用者的定义对网络上的数据包进行截获的包分析工具。 tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的…

MPLS(下)

LDP --- 标签分发协议 --- 主要应用在MPLS的控制层面 MPLS控制层面需要完成的工作主要就是分配标签和传递标签。分配标签的前提是本地路由表中得先存在标签&#xff0c;传递标签的前提也是得先具备路由基础。所以&#xff0c;LDP想要正常工作&#xff0c;则需要IGP作为基础。 …

Docker实战-操作Docker容器实战(一)

导语   在之前的分享中&#xff0c;我们介绍了关于如何去操作Docker镜像&#xff0c;下面我们来看看如何去操作容器。 简单来讲&#xff0c;容器是镜像运行的一个实例&#xff0c;与镜像不同的是镜像只能作为一个静态文件进行读取&#xff0c;而容器是可以在运行时进行写入操…

嵌入式的日常工作内容是什么?

1、看器件文档 2、找供应商要资料 3、打电话或微信联系供应商了解技术或器件细节 4、忍受门外汉领导连环夺命吹&#xff0c;因为他们不懂技术&#xff0c;只会问进度 5、写技术文档 6、跟硬件工程师联合测试&#xff0c;查看电路板未工作状态各种问题。有时还要自己手动DI…

tomcat通用回显

​Tomcat架构简析 tomcat的架构图 Server:整个tomcat启动的时候只有一个server Service:一个server中包含了多个service,表示服务 **Container:**容器,可以看作是一个servlet容器,包含一些Engine,Host,Context,Wraper等,访问的路径什么的就存放在这里 Engine -- 引擎 Host …

搞个个人博客,纯学习想找个纯html模板咋就这难

以前做毕业设计的时候老想找一些不掺杂后端代码的前端模板。 可是下载下来&#xff0c;不是php就是python后台的。看又看不懂&#xff0c;想换语言就必须先把里面的后台代码拿掉。 就很像买了个精装的二手房&#xff0c;白白多花了砸墙钱。 就比如&#xff0c;想做个带菜单的…

编写SPI_Master驱动程序_新方法

编写SPI_Master驱动程序_新方法 文章目录 编写SPI_Master驱动程序_新方法一. SPI驱动框架1.1 总体框架1.2 怎么编写SPI_Master驱动1.2.1 编写设备树1.2.2 编写驱动程序 二、 编写程序2.1 数据传输流程2.2 写代码 致谢 参考资料&#xff1a; 内核头文件&#xff1a;include\lin…

vsphere6.5 创建数据中心、集群和添加主机

1、新建数据中心&#xff0c;在入门页面选择创建数据中心&#xff0c;名称可以自定义。 2、创建完成数据中心后就可以添加主机和创建集群了。 3、新建一个集群&#xff0c;并打开DRS和HA功能&#xff0c;这两个功能的一些其他选项可以在创建完成后进一步设置&#xff0c;关于EV…

我能“C“——扫雷游戏

一.前言&#xff1a; 扫雷游戏&#xff0c;一款经典的游戏&#xff0c;没玩过的话也可以试着玩一玩&#xff0c;这样对写扫雷游戏这个小游戏的化是会有一个很好的思路的。那么本片博客就来介绍如何实现扫雷游戏的具体步骤。扫雷游戏链接&#x1f449; 扫雷游戏网页版 - Minesw…

人工智能在推动生产力上的分析

像ChatGPT这样的大型语言模型正在成为强大的工具&#xff0c;不仅可以提高工人的生产力&#xff0c;还可以提高创新率&#xff0c;为经济增长的显著加速奠定基础。作为一项通用技术&#xff0c;人工智能将影响广泛的行业&#xff0c;促进对新技能的投资&#xff0c;改变业务流程…

DWG图纸在SOLIDWORKS软件里如何使用?

经常有工程师咨询DWG图纸在SOLIDWORKS软件里如何使用&#xff0c;其实这涉及到DWG图纸在SOLIDWORKS软件里的重用问题&#xff0c;SOLIDWORKS支持对DWG图纸的重用&#xff0c;常用的有三种方法&#xff1a; 1.作为原始DWG图纸查看作为原始DWG图纸查看是指使用SOLIDWORKS软件直接…

Nginx使用proxy_cache指令设置反向代理缓存静态资源

场景 CentOS7中解压tar包的方式安装Nginx&#xff1a; CentOS7中解压tar包的方式安装Nginx_centos7 tar文件 怎么load_霸道流氓气质的博客-CSDN博客 参考上面流程实现搭建Nginx的基础上&#xff0c;实现静态资源的缓存设置。 注意上面安装时的目录是在/opt/nginx目录下&…

Python编程从入门到实践练习第四章:对列表进行操作

本文目录 一、 创建数值列表1.1 使用range创建数字列表涉及方法使用实例输出 1.2 列表解析1.3 练习题代码输出 二、对列表部分元素进行操作2.1 切片使用实例 2.2 复制列表2.3 练习题代码输出 三、元组3.1 元组介绍3.2 练习题代码输出 一、 创建数值列表 1.1 使用range创建数字…

理解Android生命周期

写一个demo&#xff0c;实现两个页面之间的跳转。重写7个生命周期方法&#xff0c;在方法中打印日志&#xff0c;观察状态的变化。 MainActivity 设置一个常量。 private static final String TAG "hello_activity_1";重写7个生命周期。 在生命周期方法中&#…

No primary or single unique constructor found for interface java.util.List

报错截图&#xff1a; 报错内容&#xff1a; 2023-08-04 15:46:32.884 ERROR 14260 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing fa…

对当下AI的一些观感思考

目前来看&#xff0c;AI技术地震的震中还是在美帝那旮瘩。尤其是M7&#xff0c;这几家市值加总快15万亿美元了&#xff0c;个个都是行业翘楚&#xff0c;个个都有拿得出手的东西。AI是个技术密集、人才密集、计算密集的产业。美帝拥有全球一流的顶尖人才&#xff0c;以及财力、…

【Leetcode】(自食用)树的中序遍历(递归+栈非递归)

step by step. 题目&#xff1a; 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入…

【LNMP】LNMP

LNMP&#xff1a;是目前成熟的企业网站的应用模式之一&#xff0c;指的是一套协同工作的系统和相关软件&#xff1b;能够提供静态页面服务&#xff0c;也可以提供动态web服务 L Linux系统&#xff0c;操作系统N Nginx网站服务&#xff0c;前端&#xff0c;提供前端的静态…