IIC子系统-实现si7006温湿度传感器采集温湿度功能

news/2025/2/19 17:31:20/

1.将IIC核心层和总线驱动层配置进内核

*********************配置核心层*************************1.找到核心层代码目录:内核顶层目录/drivers/i2c2. 内核顶层目录执行make menuconfig3. > Device Drivers > I2C support  ->-*-I2C support4.保存退出********************配置总线驱动层************1.找到iic总线驱动层代码目录:内核顶层目录/drivers/i2c/busses2.内核顶层目录执行make menuconfig3. > Device Drivers > I2C support > I2C Hardware Bus support-》<*> STMicroelectronics STM32F7 I2C support 4.保存退出*************编译**********1.内核顶层目录下执行make uImage   LOADADDR=0XC20000002.cp 内核层目录/arch/arm/boot/uImage ~/tftpboot3.重启开发板

2.I2C设备树节点的修改和SI7006设备树节点的添加

在stm32mp157a-fsmp1a.dts文件的根节点外部,添加如下内容:&i2c1 {pinctrl-names = "default", "sleep";//关于pinctrl的一个列表,"default"表示默认工作模式//"sleep"表示低功耗模式pinctrl-0 = <&i2c1_pins_b>;//-0表示pinctrl-name列表中第一个值defaultpinctrl-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>;};};

3.si7006读取温湿度的功能码

 4.温湿度的读取时序

 5.温度湿度的计算公式

 6.读取温湿度实例

头文件

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

 应用程序

#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;
}

驱动程序

#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){printk("向用户拷贝数据失败\n");return ret;}break;case GET_TEM://读取温度//读取温度的逻辑tem=i2c_read_hum_tem(0XE3);ret=copy_to_user((void *)arg,&tem,4);if(ret){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;
}
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="hqyj,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");

http://www.ppmy.cn/news/1002110.html

相关文章

poium测试库之JavaScript API封装原理

为什么要封装JavaScript的API&#xff1f; 因为有些场景下Selenium提供的API并不能满足我们需求。比如&#xff0c;滑动浏览滚动条&#xff0c;控制元素的显示/隐藏&#xff0c;日历控件的操作等&#xff0c;都可以通过JavaScrip实现&#xff0c;而且Selenium为我们提供了 exe…

在中国人民大学与加拿大女王金融硕士项目的岁月,不会负了每个有心人

学习&#xff0c;就像是一场战争&#xff0c;有时你觉得在这拼命撕杀的战场上&#xff0c;你是孤独与无助的&#xff0c;但你殊不知&#xff0c;你其实并不是孤身奋战的&#xff01;学习路上会遇见很多有心人&#xff0c;在中国人民大学与加拿大女王金融硕士项目的岁月&#xf…

2023天猫休闲零食市场分析(天猫数据分析软件)

基于较大的人口基数以及人们对休闲零食的需求&#xff0c;我国的休闲零食市场始终保持着稳健的增长趋势&#xff0c;行业整体的规模也比较大。根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;2023年1月份至4月份&#xff0c;天猫平台上休闲零食行业的销量为6亿&#xff…

Linux--#ifdef和#endif的作用

#ifdef:如果指定的标识符已经定义&#xff0c;则编译下面的代码。 #ifdef DEBUG// 在调试模式下会编译这部分代码printf("Debug mode enabled.\n"); #endif#endif&#xff1a;结束条件编译块。

【雕爷学编程】MicroPython动手做(30)——物联网之Blynk

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

if语句实现成绩等级判断

if语句实现成绩等级判断 案例分析代码实现小结Time 案例分析 使用键盘输入一个成绩&#xff0c;然后通过if判断语句实现成绩等级的判断 代码实现 import java.util.Scanner;public class DetermineDemo {public static void main(String[] args) {Scanner scanner new Scanne…

C# Blazor 学习笔记(5):blazor文件夹组件引入

文章目录 前言文件夹组件引入文件夹分类文件引入解决方法 前言 为了更好的组件化管理整个文件&#xff0c;我选择使用分文件夹对项目组件进行分类。 文件夹组件引入 文件夹分类 Shared&#xff1a;Layout布局空间放置地方&#xff0c;由于默认创建&#xff0c;动也不好动&a…

Java面向对象之Object类

Object类 Object类是所有Java类的根父类。 public class ObjectTest {public static void main(String[] args) {Order order new Order();System.out.println(order.getClass().getSuperclass());} }class Order {}如果在类的声明中未使用extends关键字指明其父类&#xff…