IIC子系统测温湿度

 采用stm32MP157AAA芯片,温度传感器 si7006 0x40

1、在内核空间不支持浮点数进行打印,所以需要将读取到的数据拷贝到用户空间,执行用户程序打印

2、在probe函数中

  • 分步注册字符设备驱动
  • 自动创建设备节点

3、在i2c驱动代码中,需要自己封装读写温湿度函数

4、使用ioctl通过判断命令码读取温湿度数据,将数据拷贝到用户空间

        #define GET_SI7006_TEMP _IOR('a',1,int)

        #define GET_SI7006_HUM _IOR('a',0,int)

5、将采集到的温湿度传感器的值,在用户空间进行打印

6、在remove函数中,执行释放相关操作

 si7006

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/device.h>

unsigned int major ; //定义一个变量存放主设备号值
struct device *dev;
struct class *cls;
struct i2c_client *client1;
#define GET_SI7006_TEMP _IOR('a',1,int)
#define GET_SI7006_HUM _IOR('a',0,int)

//函数返回值:读取到的内容,根据芯片手册可知,需要读取两个字节(高8位,低8位)
short read_hum_tem_value(unsigned char reg)
{
    char r_buf[] = {reg}; //读取的命令码,从机地址
    unsigned short value; //保存读到的温湿度数据
    //消息结构体的封装
    struct i2c_msg r_msg[] = {
        [0] = {
            .addr = client1->addr, //从机地址
            .flags = 0, //写
            .len = 1,   //描述buf字节长度
            .buf = r_buf, //寄存器地址
        },
        [1] = {
            .addr =client1->addr,
            .flags = 1,
            .len = 2,
            .buf = (__u8 *)&value,
        },
    };
    //发送消息
    int ret = i2c_transfer(client1->adapter,r_msg,ARRAY_SIZE(r_msg));
    if(ret != ARRAY_SIZE(r_msg))
    {
        printk("消息传输失败\n");
        return -EIO;
    }
    return value>>8|value<<8;  //高8位和低8位进行拼接
}
//打开
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)
{
    //读取温湿度
    short hum,tem;
    int ret;
    switch ((cmd))
    {
    case GET_SI7006_HUM: //判断湿度命令码
        hum = read_hum_tem_value(0xE5); //读取湿度值
        ret = copy_to_user((void *)arg,(void*)&hum,2); //将内核空间数据拷贝到用户空间
        if(ret)
        {
            printk("coyp_to_user err %d\n",__LINE__);
        }
    
        break;
    case GET_SI7006_TEMP:
        tem = read_hum_tem_value(0xE5);
        ret = copy_to_user((void *)arg,&tem,2);
        if(ret)
        {
            printk("coyp_to_user err %d\n",__LINE__);
        }  
        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 si7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    client1 = client;
    // 1、分步注册字符设备驱动
    //1.分配对象,就是分配struct cdev结构体指针 cdev_alloc
   
    major = register_chrdev(0,"si7006",&fops);
    if(major < 0)
    {
        printk("字符设备驱动注册失败\n");
        return  major;
    
    }
 printk("字符设备驱动注册成功\n");
    //(1)、
    //2、自动创建设备节点
    //(2)、注册字符设备驱动
    //(2)、向上层提交目录信息 /sys/class查看向上层提交目录信息
    cls = class_create(THIS_MODULE,"si7006");
    if(IS_ERR(cls))
    {
        printk("class create is error\n");
        return PTR_ERR(cls);
    }
    //(2)、向上层提交设备信息 /dev目录下查看创建设备节点名字
    dev = device_create(cls,NULL,MKDEV(major,0),NULL,"si7006");
    if(IS_ERR(dev))
    { //判断地址是否在4k空间
         return -PTR_ERR(dev); //将错误码指针转换为错误码
    }    
    //设备驱动层和总线驱动层匹配成功执行函数
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
  

}

int si7006_remove(struct  i2c_client *client)
{
    //设备驱动层和总线驱动层分离执行函数
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    //释放函数
    //设备信息注销
    device_destroy(cls,MKDEV(major,0));
    //设备节点注销
    class_destroy(cls);
    //驱动注销
    unregister_chrdev(major,"si7006");
    return 0;
}
//定义设备树匹配的表
const struct of_device_id oftable[] = {
    {.compatible = "hqyj,si7006",},
    {},
};

//分配i2c_driver对象
struct i2c_driver si7006 = {
    .probe = si7006_probe,
    .remove = si7006_remove,
    .driver = {
        .name  = "si7006",
        .of_match_table = oftable,
    },
};

//一键注册i2c子系统宏
module_i2c_driver(si7006);
MODULE_LICENSE("GPL");

 test.c 应用层写执行逻辑


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#define GET_SI7006_TEMP _IOR('a',1,int)
#define GET_SI7006_HUM _IOR('a',0,int)

int main(int argc, char const *argv[])
{
    char buf[128]={0};
    unsigned short hum,tem;
    float hum1,tem1;
    //打开设备文件
    int fd =-1;
    fd = open("/dev/si7006",O_RDWR);
    if(fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        //读取温湿度数据
        //fd,命令码,读取数据
        ioctl(fd,GET_SI7006_HUM,&hum);
        ioctl(fd,GET_SI7006_TEMP,&tem);
        //进行字节序转换
        // hum = ntohs(hum);
        // tem = ntohs(tem);
       // 数据转换
        hum1 = (float)hum*125/65536-6;
        tem1 = (float)tem*175.72/65536-46.85;
        
        printf("rhum = %0.2f  rtem = %0.2f\n",hum1,tem1);
        sleep(1);
    }
    close(fd);
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通用的链栈实现(C++)

template<class T> class MyStack//链栈 { private:struct StackNode{T data;StackNode* next;StackNode(const T& val T(), StackNode* p nullptr) :data(val), next(p) {}//};StackNode* top;int cursize;void clone(const MyStack& s){Clear();cursize s.c…

cgo与调用c的回调函数指针

cgo直接调用函数&#xff0c;使用基本数据类型非常简单&#xff0c;包括一些结构体也比较简单&#xff0c;嵌套的稍微复杂些&#xff0c;但也可以&#xff0c;但有的时候&#xff0c;cgo调用c函数&#xff0c;会需要传递一个回调函数的指针&#xff0c;这时候就比较复杂了&…

office365 outlook邮件无法删除

是否遇到过&#xff0c;office365邮件存储满了&#xff0c;删除邮件无法删除&#xff0c;即便用web方式登录到outlook&#xff0c;删除邮件当时是成功的&#xff0c;但一会儿就回滚回来了&#xff0c;已删除的邮件&#xff0c;你想清空&#xff0c;最后清理后还是回到原样。 请…

YTM32的循环冗余校验CRC外设模块详解

YTM32的循环冗余校验CRC外设模块详解 文章目录 YTM32的循环冗余校验CRC外设模块详解引言原理与机制CRC算法简介从CRC算法到CRC硬件外设 应用要点&#xff08;软件&#xff09;CRC16 用例CRC32 用例 总结参考文献 引言 在串行通信帧中&#xff0c;为了保证数据在传输过程中的完…

基于Python优化图片亮度与噪点

支持添加噪点类型包括&#xff1a;添加高斯噪点、添加椒盐噪点、添加波动噪点、添加泊松噪点、添加周期性噪点、添加斑点噪点、添加相位噪点&#xff0c;还提供清除噪点的功能。 我们先看一下实测效果&#xff1a;&#xff08;test.jpg为原图&#xff0c;new.jpg为添加后的图片…

自动化测试的成本高效果差,那么自动化测试的意义在哪呢?

一、自动化测试的成本高效果差&#xff0c;那么自动化测试的意义在哪呢&#xff1f; 我觉得这个问题带有很强的误导性&#xff0c;是典型的逻辑陷阱之一。“自动化测试的成本高效果差”是真的吗&#xff1f;当然不是。而且我始终相信&#xff0c;回答问题的最好方式是把问题本身…

达索系统3DEXPERIENCE WORKS 2024流体仿真功能增强

设计工作中&#xff0c;网格划分和设计验证十分重要&#xff0c;它可以方便我们把复杂组件简单化处理&#xff0c;从而提升工作效率。 轻松应对&#xff0c;精准划分 在优化设计以获得更好的空气动力学性能时&#xff0c;需要了解空气在其周围产生的流动方式。达索系统3DEXPE…

(论文阅读29/100 人体姿态估计)

29.文献阅读笔记 简介 题目 DeepCut: Joint Subset Partition and Labeling for Multi Person Pose Estimation 作者 Leonid Pishchulin, Eldar Insafutdinov, Siyu Tang, Bjoern Andres, Mykhaylo Andriluka, Peter Gehler, and Bernt Schiele, CVPR, 2016. 原文链接 h…

STM32 X-CUBE-AI:Pytorch模型部署全流程

文章目录 概要版本&#xff1a;参考资料STM32CUBEAI安装CUBEAI模型支持LSTM模型转换注意事项模型转换模型应用1 错误类型及代码2 模型创建和初始化3 获取输入输出数据变量4 获取模型前馈输出模型应用小结 小结 概要 STM32 CUBE MX扩展包&#xff1a;X-CUBE-AI部署流程&#xf…

Accelerate 0.24.0文档 一:两万字极速入门

文章目录 一、概述1.1 PyTorch DDP1.2 Accelerate 分布式训练简介1.2.1 实例化Accelerator类1.2.2 将所有训练相关 PyTorch 对象传递给 prepare()方法1.2.3 启用 accelerator.backward(loss) 1.3 Accelerate 分布式评估1.4 accelerate launch1.4.1 使用accelerate launch启动训…

k8s集群搭建(ubuntu 20.04 + k8s 1.28.3 + calico + containerd1.7.8)

环境&需求 服务器&#xff1a; 10.235.165.21 k8s-master 10.235.165.22 k8s-slave1 10.235.165.23 k8s-slave2OS版本&#xff1a; rootvms131:~# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.5 LTS Release: …

Java自学第11课:电商项目(4)重新建立项目

经过前几节的学习&#xff0c;我们已经找到之前碰到的问题的原因了。那么下面接着做项目学习。 1 新建dynamic web project 建立时把web.xml也生成下&#xff0c;省的右面再添加。 会询问是否改为java ee环境&#xff1f;no就行&#xff0c;其实改过来也是可以的。这个不重要。…

css3 初步了解

1、css3的含义及简介 简而言之&#xff0c;css3 就是 css的最新标准&#xff0c;使用css3都要遵循这个标准&#xff0c;CSS3 已完全向后兼容&#xff0c;所以你就不必改变现有的设计&#xff0c; 2、一些比较重要的css3 模块 选择器 1、标签选择器&#xff0c;也称为元素选择…

滚珠螺杆在注塑机械手中起什么作用?

注塑机械手的配件中滚珠螺杆是重要的一环&#xff0c;在注塑机械手中起着重要的作用。注塑机械手是一种自动化设备&#xff0c;可以在注塑生产中实现自动化操作&#xff0c;而滚珠螺杆则是实现这一操作的关键部件之一。 滚珠螺杆是一种将旋转运动转化为直线运动的精密传动部件&…

在Linux系统下微调Llama2(MetaAI)大模型教程—Qlora

Llama2是Meta最新开源的语言大模型&#xff0c;训练数据集2万亿token&#xff0c;上下文长度是由Llama的2048扩展到4096&#xff0c;可以理解和生成更长的文本&#xff0c;包括7B、13B和70B三个模型&#xff0c;在各种基准集的测试上表现突出&#xff0c;最重要的是&#xff0c…

【Linux网络】本地DNS服务器搭建

目录 一、什么是DNS&#xff0c;相关介绍 1、dns是什么&#xff1a; 2、域名的分类&#xff1a; 3、服务器的类型 二、DNS解析的过程 三、DNS的相关配置文件学习 1、本地主机有关的DNS文件学习 2、本地的DNS缓存服务器的文件 3、bind软件的相关配置文件&#xff1a; 4…

Jmeter执行接口自动化测试-如何初始化清空旧数据

需求分析&#xff1a; 每次执行完自动化测试&#xff0c;我们不会执行删除接口把数据删除&#xff0c;而需要留着手工测试&#xff0c;此时会导致下次执行测试有旧数据我们手工可能也会新增数据&#xff0c;导致下次执行自动化测试有旧数据 下面介绍两种清空数据的方法 一、通…

nginx代理docker容器服务

场景描述 避免暴力服务端口&#xff0c;使用nginx代理 一个前端&#xff0c;一个后端&#xff0c;docker方式部署到服务器&#xff0c;使用docker创建的nginx代理端口请求到前端端口 过程 1 docker 安装nginx 1.1 安装一个指定版本的nginx docker pull nginx#启动一个ngi…

vuejs - - - - - 移动端设备兼容(pxtorem)

pxtorem的使用 1. 依赖安装2. vue.config.js配置3. 动态设置html的font-size大小4. 效果如图&#xff1a; 1. 依赖安装 yarn add postcss-pxtorem -D 2. vue.config.js配置 module.exports {...css: {loaderOptions: {postcss: {plugins: [require("postcss-pxtorem&quo…