I2C子系统、读取温湿度的逻辑及代码

news2024/11/26 20:21:20

一、IIC子系统

两根线:    scl:时钟线         sda:数据线

iic有4种信号:        

        起始信号(start):scl是高电平,sda下降沿

        终止信号(stop):scl高电平,sda上升沿

        应答信号(ack):第9个周期,sda是低电平

        非应答信号(NACK:)第9个周期,sda维持高电平

 iic总线特点:     串行同步半双工

iic总线的时序:   

       1)写时序

         2)读时序

二、IIC设备驱动层API

struct device_driver

{

        const char *name;

         const struct of_device_id *of_match_table;

};

2.给对象分配空间并且初始化

3.注册

        #define i2c_add_driver(struct i2c_driver *driver) \

                        i2c_register_driver(THIS_MODULE, driver)

4.注销

        void i2c_del_driver(struct i2c_driver *driver)

5.一键注册宏

        module_i2c_driver(__i2c_driver)

三、修改I2C1设备树节点以及添加si7006的子节点

四、struct i2c_client结构体

        当驱动匹配设备信息成功后内核中就会存在一个struct i2c_client 对象,对象内部保存的是匹配成功的设备的信息以及总线相关的信息

        

五、i2c数据传输的函数

        基于I2C总线进行数据传输

        int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)        

                             adap:用于索引总线驱动的对象指针 client->adapter

                              msgs:要传输的一个或者多个消息, 一个消息是以起始信号作为出发点

                              num:传输的消息的数量

六、消息结构体 struct i2c_msg

一条消息中要包含从机地址读写标志位以及消息的正文

根据时序来,有几个起始信号就要有几条消息

1)写消息的封装

        

2)读消息的封装

        

七、读取温湿度传感器

1.温湿度的读取时序:

        

2.温度和湿度的计算公式

        

3.代码

head.h
#ifndef __HEAD_H__
#define __HEAD_H__

#define GET_HUM  _IOR('m',1,int)//获取湿度的功能码
#define GET_TEM  _IOR('m',0,int)//获取温度的功能码


#endif
pdrv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include "head.h"
unsigned int major;
struct class *cls;
struct device *dev;
struct i2c_client *client1;
// 封装函数读取温度和湿度
int read_hum_tem(char reg)
{
    // 封装传输的消息
    char r_buf[] = {reg};
    short value;
    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,
        },
    };
    //传输消息
    int 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;
    int ret;
    switch (cmd)
    {
    case GET_HUM: // 读取湿度
        // 读取湿度的逻辑
        hum = read_hum_tem(0XE5);
        ret = copy_to_user((void *)arg, &hum, 4);
        if (ret)
        {
            printk("copy_to_user err\n");
            return ret;
        }
        break;
    case GET_TEM: // 读取温度
        // 读取温度的逻辑
        tem = read_hum_tem(0XE3);
        ret = copy_to_user((void *)arg, &tem, 4);
        if (ret)
        {
            printk("copy_to_user err\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;
    int ret;
    // 字符设备驱动的注册
    major = register_chrdev(0, "si7006", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        ret = major;
        goto out1;
    }
    printk("注册字符设备驱动成功\n");
    // 设备节点的创建
    // 向上提交目录
    cls = class_create(THIS_MODULE, "si7006");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret = PTR_ERR(cls);
        goto out2;
    }
    printk("向上提交目录信息成功\n");
    // 向上提交设备节点信息
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "si7006");
    if (IS_ERR(dev))
    {
        printk("向上提交设备节点信息失败\n");
        ret = PTR_ERR(dev);
        goto out3;
    }
    printk("向上提交设备节点信息成功\n");

        return 0;
out3:
    class_destroy(cls);
out2:
    unregister_chrdev(major, "si7006");
out1:
    return ret;
}

int i2c_remove(struct i2c_client *client)
{
    // 设备信息的注销
    // 设备节点的销毁
    // 驱动的注销
    return 0;
}
// 定义设备树匹配的表
struct of_device_id oftable[] = {
    {
        .compatible = "hqyj,si7006",
    },
    {},
}; // 名字表的构建

// 分配驱动信息对象
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");
test.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;
}

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

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

相关文章

面试官:说说JavaScript中的数据类型?区别?

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 一、概述 二、显示转换 Number() parseInt() String() Boolean() 三、隐式转换 自动转换为布尔值 自动转换…

SOLIDWORKS2024新功能--SOLIDWORKS篇(二)

该章节包括以下主题&#xff1a; 切口工具槽口延伸戳记工具薄片和槽口中的切割法线 切口工具 您可以使用切口工具在空心或薄壁圆柱体和圆锥体中生成切口。通过选择圆柱面或圆锥面上的边线&#xff0c;您可以将零件平展为钣金。 在早期版本中&#xff0c;如果您有圆柱形或圆锥形…

CTF是什么?

前言 &#x1f4bb;随着大数据、人工智能的发展&#xff0c;人们步入了新的时代&#xff0c;逐渐走上科技的巅峰。 ⚔科技是一把双刃剑&#xff0c;网络安全不容忽视&#xff0c;人们的隐私在大数据面前暴露无遗&#xff0c;账户被盗、资金损失、网络诈骗、隐私泄露&#xff…

spring源码环境搭建

spring源码环境搭建 步骤1 &#xff1a;下载Spring-framework源码 https://github.com/spring-projects/spring-framework/tree/5.1.x步骤2&#xff1a;修改build.gradle配置文件 修改repositories里面的maven使用阿里云镜像 maven { url “https://maven.aliyun.com/reposit…

JVM基础知识(内存区域划分,类加载,GC垃圾回收)

目录 内存区域划分 JVM中的栈 JVM中的堆 程序计数器 方法区(元数据区) 给一段代码,某个变量在哪个区域上? 类加载 类加载时机 双亲委派模型 GC 垃圾回收机制 GC 实际工作过程 1.找到垃圾/判定垃圾 1.可达性分析(Java中的做法) 2.引用计数 2.清理垃圾 1.标记清除…

小程序商城开发搭建;

小程序商城系统是基于移动互联网的一种在线购物平台&#xff0c;提供线上商城购物、在线下单、支付及配送等功能。随着智能手机普及率的加速提升&#xff0c;小程序商城系统也成为更多商家的选择。下面是小程序商城系统的主要功能介绍&#xff1a; 1、商品展示&#xff1a;商家…

Vue路由与node.js环境搭建

目录 前言 一.Vue路由 1.什么是spa 1.1简介 1.2 spa的特点 1.3 spa的优势以及未来的挑战 2.路由的使用 2.1 导入JS依赖 2.2 定义两个组件 2.3 定义组件与路径对应关系 2.4 通过路由关系获取路由对象 2.5 将对象挂载到vue实例中 2.6 定义触发路由事件的按钮 2.7 定…

华为云云耀云服务器L实例评测|云耀云服务器L实例的购买及使用体验

华为云云耀云服务器L实例评测&#xff5c;云耀云服务器L实例的购买及使用体验 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点1.3 云耀云服务器L实例使用场景 二、云耀云服务器L实例支持的镜像2.1 镜像类型2.2 系统镜像2.3 应用镜像 三、购买云…

HOOPS Visualize 2023 SP2 U1 Crack-HOOPS Visualize

HOOPS Visualize 是一个以工程为中心的高性能图形库&#xff0c;用于在桌面、移动和 AR/VR 设备上渲染 3D CAD 模型。该 3D 图形库具有线程安全的 C 和 C# 接口以及 OpenGL 和 DirectX 驱动程序&#xff0c;并由响应迅速的专业图形专家提供支持。通过访问最新的 3D GPU 功能&am…

【业务功能篇112】Springboot + Spring Security 权限管理-登录模块开发实战

合家云社区物业管理平台 4.权限管理模块研发 4.3 登录模块开发 前台和后台的认证授权统一都使用SpringSecurity安全框架来实现。首次登录过程如下图: 4.3.1 生成图片校验码 4.3.1.1 导入工具类 (1) 导入Constants 常量类 /*** 通用常量类* author spikeCong* date 2023/5…

【数据结构】【C++】封装红黑树模拟实现map和set容器

【数据结构】&&【C】封装红黑树模拟实现map和set容器 一.红黑树的完成二.改造红黑树(泛型适配)三.封装map和set的接口四.实现红黑树迭代器(泛型适配)五.封装map和set的迭代器六.解决key不能修改问题七.实现map[]运算符重载 一.红黑树的完成 在上一篇红黑树的模拟实现中…

抖音、知乎、小红书的流量算法

目前我国网民规模已超过10亿&#xff0c;在这互联网时代&#xff0c;更是流量为王。各个平台里的每个视频、每张图片&#xff0c;背后都有着算法的身影&#xff0c;支配着所有人的流量。作为内容创作者及运营者来说&#xff0c;除了制作高质量的内容以外&#xff0c;也需要掌握…

五年全满分 | 求臻医学满分通过2023 NGSST-A 能力验证

近期&#xff0c;求臻医学以满分的优异成绩顺利通过了美国病理学家协会&#xff08;College of American Pathologists, CAP&#xff09;组织开展的NGSST-A 2023&#xff08;Next-Generation Sequencing Solid Tumor&#xff09;能力验证项目。至此&#xff0c;公司已连续五年满…

如何去除音乐中的人声,只留伴奏?

如何去除音乐中的人声&#xff0c;只留伴奏&#xff1f;看到很多小伙伴都有这种需求&#xff0c;今天给大家分享一个宝藏网站&#xff0c;简易操作&#xff0c;可以轻松提取伴奏&#xff0c;想学的一起来看看吧&#xff01; 音分轨——人声分离软件&#xff0c;这是一个用了人工…

Spring 6.0 新特性

文章目录 Spring的发展历史AOTGraalVMSpringBoot实战AOTRuntimeHints案例分析RuntimeHintsRegistrar SpringBoot中AOT核心代码 Spring的发展历史 AOT Spring 6.0的新特性Ahead of Time&#xff08;AOT&#xff09;编译是一种技术&#xff0c;可以提前将Spring应用程序编译成原…

Linux为什么不能像鸿蒙一样实现万物互联?

Linux为什么不能像鸿蒙一样实现万物互联? 可能原因&#xff0c;Linux不会炒作。 万物互联&#xff0c;先从网络开始&#xff0c;光纤入户&#xff0c;首先接入光猫&#xff0c;光猫的操作系统&#xff0c;不确定是不是openWRT&#xff0c;但是这个确定是Linux内核。 然后进入…

免杀对抗-java语言-shellcode免杀-源码修改+打包exe

JAVA-ShellCode免杀-源码修改&打包EXE Shellcode-生成/上线 1.msf生成shellcode 命令&#xff1a;msfvenom -p java/meterpreter/reverse_tcp LHOSTx.x.x.x LPORTxxxx -f jar -o msf.jar 2.msf设置监听 3.执行msf生成的shellcode jar包&#xff0c;成功上线 命令&#xff1…

【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…

echarts柱状图上方的数值为0时设置不展示

未去掉0的效果图 series: [{data: this.barData.y,type: "bar",barWidth: 20,itemStyle: {normal: {// 设置柱子圆角barBorderRadius: [2, 2, 0, 0],},},label: {show: true,position: top,color:#fff,formatter: function (params) {if (params.value > 0) {retu…

Vue3父组件访问子组件方法 defineExpose用法

父组件示例 <template><div class"container"><h-demo ref"childDom" /><button click"getChild"></button></div> </template><script setup> import Hdemo from /components/Hdemo; import …