当湿度达到70蜂鸣器警报

news/2024/11/25 21:40:54/

1.编写设备树,添加蜂鸣器等设备

 驱动代码:

#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 "si7006.h"
#include <linux/of_gpio.h>
#include <linux/gpio.h>
int major;
struct class *cls;
struct device *dev;
//tclient指向的结构体,存储设备驱动和总线驱动匹配成功的信息
struct i2c_client *tclient;
//指向gpio节点
struct device_node *node;
//定义结构体指针指向gpio编号
struct gpio_desc *gpiono;
int rcv;
//获取温湿度的函数
int i2c_read_hum_tem(unsigned char reg)
{int  ret;char r_buf[]={reg}; //地址放到数组中,读取消息unsigned short val; //读的数据//设备驱动将要收发的消息放到结构体中struct i2c_msg r_msg[]={[0]={.addr=tclient->addr,.flags=0,.len=1,  //发送的地址长度是8bit一字节.buf=r_buf,},[1]={.addr=tclient->addr,.flags=1,.len=2,.buf=(char*)&val,}};//消息传输ret=i2c_transfer(tclient->adapter,r_msg,ARRAY_SIZE(r_msg));if(ret!=ARRAY_SIZE(r_msg)){printk("获取温湿度数据失败\n");return -EAGAIN;}return val;
}
int si7006_open(struct inode *inode, struct file *file)
{printk("open\n");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=i2c_read_hum_tem(0xe5);ret=copy_to_user((void*)arg,(void*)&hum,sizeof(int));if(ret){printk("copy to user failed\n");return -EINVAL;}break;case GET_TEM:tem=i2c_read_hum_tem(0xe3);ret=copy_to_user((void*)arg,(void*)&tem,sizeof(int));if(ret){printk("copy to user failed\n");return -EINVAL;}break;case FENGM:gpiod_set_value(gpiono,1);break;}return 0;
}
int si7006_close(struct inode *inode, struct file *file)
{printk("close\n");return 0;
}
struct file_operations fops={.open=si7006_open,.unlocked_ioctl=si7006_ioctl,.release=si7006_close,
};
//注册字符设备驱动
int chrdev(void){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;}//定义一个probe函数int si7006_probe(struct i2c_client *client,const struct i2c_device_id *id){tclient=client;//将总线驱动指针编程全局的//注册字符设备驱动rcv=chrdev();//获取节点信息node=of_find_node_by_name(NULL,"extend_dev");if(node==NULL){printk("通过名字解析设备树节点失败\n");return -EFAULT;}printk("设备树解析成功\n");//获取并申请gpio编号,键值fengmgpiono=gpiod_get_from_of_node(node,"fengm",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono)){printk("获取gpiono 失败\n");return PTR_ERR(gpiono);}printk("获取gpiono 成功\n");return 0;}//设备分离后执行removeint si7006_remove(struct i2c_client *client){gpiod_set_value(gpiono,0);//销毁设备节点device_destroy(cls,MKDEV(major,0));//销毁目录class_destroy(cls);//驱动注销unregister_chrdev(major,"si7006");printk("%s:%d",__func__,__LINE__);return 0;}struct of_device_id oftable[]={{.compatible="hqyj,si7006",},{},};//热插拔宏,可以在插入硬件时,自动安装驱动MODULE_DEVICE_TABLE(of,oftable);//对象初始化struct i2c_driver si7006={.probe=si7006_probe,.remove=si7006_remove,  .driver={.name="tem_hum_driver",  //按名字匹配,只能匹配一个设备.of_match_table=oftable,//设备树匹配     }, };module_i2c_driver(si7006);
MODULE_LICENSE("GPL");

 应用层代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include "si7006.h"
int main(int argc, char const *argv[])
{int hum,tem;float hum1,tem1;int ret;int ubuf[20];int fd=open("/dev/si7006",O_RDWR);if(fd<0){printf("打开设备文件失败\n");exit(-1);}while(1){//通过ioctl获取温湿度,放到tem,hum所在的地址ioctl(fd,GET_TEM,&tem);ioctl(fd,GET_HUM,&hum);//大端转小端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);//当湿度达到70触发警报---PB6蜂鸣器if(hum1>=70){ioctl(fd,FENGM);printf("警报\n");}sleep(1);}return 0;
}

头文件:

#ifndef __SI7006_H__
#define __SI7006_H__
//命令码封装,方向,大小,类型m,功能0
#define GET_TEM _IOR('m',0,int)
#define GET_HUM _IOR('m',1,int)
#define FENGM _IOW('u',3,int)
#endif

报错:

 [root@fsmp1a /]#rmmod driver.ko
rmmod: can't unload module 'driver': Device or resource busy

解决办法:

vi  /proc/devices

删除驱动信息,重启开发板

实验现象: 


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

相关文章

预警仪产品上市增加曝光量如何使用新闻来打造

新闻宣传是一种把产品推广到更大范围的方法&#xff0c;它利用新闻媒体把产品和服务传播给大众&#xff0c;从而提高公司的知名度和美誉度&#xff0c;增加产品的销售量。预警仪是安全领域的重要产品&#xff0c;在今天的社会中&#xff0c;安全是重中之重&#xff0c;预警仪得…

电量计方案

一.引言 在当前的项目应用中&#xff0c;越来越多的设备使用电池供电&#xff0c;如果设备能够精确的了解电池的电量&#xff0c;不仅能够很好地保护了电池&#xff0c;防止其过放电&#xff0c;同时也能够让用户精确地知道剩余电量来估算所能使用的时间&#xff0c;及时地保存…

阿里云物联网平台测评:以温度报警器开发为例

点此查看 所有教程、项目、源码导航 文章目录 1. 物联网平台概述2. 阿里云物联网平台的优势2.1 快速接入2.2 超高负载能力2.3 可用性2.4 安全性2.5 性价比 3. 温度报警器开发3.1 开通物联网平台3.2 创建产品3.3 添加设备3.4 定义产品模型3.5 开发硬件设备3.6 订阅设备消息3.7 开…

气体传感器阈值报警

一氧化碳气体无色、无臭、无味&#xff0c;无法感觉它的存在&#xff0c;但它却有着致命的威胁&#xff0c;一氧化碳中毒的事件时常发生&#xff0c;我们又该如何避免悲剧的发生。 于是有了基于开源平台&#xff0c;使用DFRobot推出的Gravity气体传感器&#xff0c;搭建的气体检…

【复习笔记】FreeRTOS(四) 列表项的插入和删除

本文是FreeRTOS复习笔记的第四节&#xff0c;列表项的插入和删除。 上一篇文章&#xff1a; 【复习笔记】FreeRTOS(三)任务挂起和恢复 文章目录 一、列表和列表项1.1. 列表1.2. 列表项1.3. 迷你列表项 二、实验目的三、测试例程四、实验效果 一、列表和列表项 列表和列表项是F…

雨量水位报警站声光报警仪,水位点按需设置

雨量水位报警站由水位探测器、雨量传感器、报警灯、扩音器、太阳能板和采集传输控制器组成。实时采集水位等级&#xff0c;三个水位探测器对应3个水位等级&#xff0c;当现场水面浸没相应探测器时&#xff0c;本机会实时发出语音报警&#xff0c;同时可发送相应的预警/报警等级…

Bosun 预警配置

表达式 数据类型 Scalar: This is the simplest type, it is a single numeric value with no group associated with it. Keep in mind that an empty group, “{}” is still a group.NumberSet: A number set is a group of tagged numeric values with one value per uniq…

SPL06-001 气压计

歌尔是全球领先的MEMS厂家&#xff0c;最新推出新款气压传感器SPL06-001&#xff0c;定位精度可达5cm 手册地址 https://download.csdn.net/download/zhangxuechao_/10548473 寄存器 计算方法 举例 //气压测量速率(sample/sec),Background 模式使用 #define PM_RATE_…