I2C子系统、读取温湿度的逻辑及代码
一、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;
}
相关文章:
I2C子系统、读取温湿度的逻辑及代码
一、IIC子系统 两根线: scl:时钟线 sda:数据线 iic有4种信号: 起始信号(start):scl是高电平,sda下降沿 终止信号(stop):scl高电平,sda上升沿 应答信号…...
数据结构——排序
排序算法 前言一、认识排序排序的概念常见的排序算法排序实现的接口 二、常见排序算法的实现插入排序直接插入排序希尔排序 选择排序直接选择排序堆排序 交换排序冒泡排序 三、各个排序的效率比较四、完整代码演示:shell_insert.hshell_insert.ctest.c 总结 前言 来…...
资深java面试题及答案整理
编写 Java 程序时, 如何在 Java 中创建死锁并修复它? 经典但核心Java面试问题之一。 如果你没有参与过多线程并发 Java 应用程序的编码,你可能会失败。 如何避免 Java 线程死锁? 如何避免 Java 中的死锁?是 Java 面试的热门问题之…...
buuctf-[网鼎杯 2020 朱雀组]phpweb
1.打开网站,吓我一跳 2.查看源代码,主要看到timezone,然后这个页面是五秒就会刷新一次 一开始去搜了这个,但是没什么用 3.使用bp抓包 会发现有两个参数,应该是用func来执行p 4.修改func和p file_get_contents&#…...
SpringBoot实战(二十四)集成 LoadBalancer
目录 一、简介1.定义2.取代 Ribbon3.主要特点与功能4.LoadBalancer 和 OpenFeign 的关系 二、使用场景一:Eureka LoadBalancer服务A:loadbalancer-consumer 消费者1.Maven依赖2.application.yml配置3.RestTemplateConfig.java4.DemoController.java 服务…...
文件挂载nas挂载
准备资源 nas服务器: 192.168.1.2 分配的nas卷名: mynasvolumename 在本地机器挂载nas卷 mkdir -p /mnt/localmountdir 执行挂载 mount -t nfs 192.168.1.2:mynasvolumename/ /mnt/localmountdir 本地进入nas目录 cd /mnt/localmountdir 可以…...
电影格式怎么转换mp4?电影格式转换教程
电影格式怎么转换mp4?平时喜欢看电影的小伙伴都知道,平时我们下载到的电影文件格式可谓是五花八门,如Mp4、Flv、AVI、WMV、MKV、MOV等。然而,相较于其他常用格式,MP4是一种使用最为广泛的视频格式,并且文件…...
HarmonyOS之 组件的使用
一 容器 1.1 容器分类 Column表示沿垂直方向布局的容器。Row表示沿水平方向布局的容器。 1.2 主轴和交叉轴 主轴:在Column容器中的子组件是按照从上到下的垂直方向布局的,其主轴的方向是垂直方向;在Row容器中的组件是按照从左到右的水平方向…...
IAM:身份验证与授权
身份验证和授权可能听起来相似,但在核心功能方面它们是不同的。身份验证和授权是在用户尝试访问其资源时执行的安全过程。身份验证和授权在防止网络安全漏洞和加强组织的安全系统方面发挥着至关重要的作用。 验证:验证用户的身份 - 用户是谁?…...
Linux——vi编辑器
目录 一、基本简介 二、命令模式下的常用按键 1、光标跳转按键 2、复制、粘贴、删除 三、编辑模式 四、末行模式 1、查找关键字并替换 2、保存退出 3、其他操作 五、模式切换 一、基本简介 1、最早可追随到1991年,全称为“Vi IMproved” 2、模式 ——命…...
【Linux学习笔记】权限
1. 普通用户和root用户权限之间的切换2. 权限的三个w2.1. 什么是权限(what)2.1.1. 用户角色2.1.2. 文件属性 2.2. 怎么操作权限呢?(how)2.2.1. ugo-rwx方案2.2.2. 八进制方案2.2.3. 文件权限的初始模样2.2.4. 进入一个…...
Aspose转pdf乱码问题
一、问题描述 在centos服务器使用aspose.word转换word文件为pdf的时候显示中文乱码(如图),但是在win服务器上使用可以正常转换 二、问题原因 由于linux服务器缺少对应的字库导致文件转换出现乱码的 三、解决方式 1.将window中字体(c:\windows\fonts)放到linux…...
table中的td内部的元素不能与td等高的问题
解决该问题的办法: td标签内部的元素使用table布局,但是需要注意的是td必须设置高度,高度为任意值都可以,虽然设置了高度,但是td依然会被内部内容的高度撑开 <template><table><tr><td><div class&q…...
Layui + Flask | 实现数据表格修改(案例篇)(09)
此案例内容比较多,建议滑到最后点击阅读原文,阅读体验更佳。后续也会录制案例视频,将在本周内上传到同名的 b 站账号。 接下来演示用 flask + layui 搭建一个学员信息管理的案例 这个案例将会利用 flask 做后端,layui table 组件做前端,基于 restful api 完成一个学员信息…...
BCC源码编译和安装
接前一篇文章:BCC源码下载 1. 进入源码根目录 进入到BCC源码根目录。命令及结果如下: $ cd bcc ~/eBPF/BCC/bcc$ ls cmake CONTRIBUTING-SCRIPTS.md docs images libbpf-tools man scripts src CMakeLists.txt …...
linux上gitlab备份与还原
三 Gitlab备份 1.gitlab安装 1.1 添加镜像地址 添加镜像地址的目的是为了提高国内用户软件下载的速度,编辑(新建)文件gitlab-ce.repo,指令: vi /etc/yum.repos.d/gitlab-ce.repo复制 输入: [gitlab-ce] namegitlab-ce # 清华…...
【精华】具身智能:人工智能的下一个浪潮
从符号主义到联结主义,智能体与真实世界的交互得到日益重视。上世纪五十年代的达特茅斯会议之后的一段时期内,对人工智能的研究主要限于符号处理范式(符号主义)。符号主义的局限性很快在实际应用中暴露出来,并催动了联…...
【线性回归、岭回归、Lasso回归分别预测患者糖尿病病情】数据挖掘实验一
Ⅰ、项目任务要求 任务描述:将“diabetes”糖尿病患者数据集划分为训练集和测试集,利用训练集分别结合线性回归、岭回归、Lasso回归建立预测模型,再利用测试集来预测糖尿病患者病情并验证预测模型的拟合能力。具体任务要求如下: …...
037:vue项目监听页面变化,动态设置iframe元素高度
第037个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…...
探索前端生成二维码技术:简单实用的实现方式
引言 随着智能手机的普及,二维码已经成为了现代生活中不可或缺的一部分。在许多场景下,我们都需要将某些信息或链接以二维码的形式展示出来。本文将介绍一种简单实用的前端生成二维码的技术,并给出具体的代码示例。 二维码生成原理 首先&a…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
