SR501人体红外模块

news2024/11/25 6:30:52

文章目录

  • 前言
  • 一、SR501模块介绍
  • 二、设备树添加节点
  • 三、驱动程序
  • 四、测试程序
  • 五、上机测试及效果
  • 总结


前言

人体红外模块 是一种能够检测人或动物发射的红外线而输出电信号的传感器。广泛应用于各种自动化控制装置中。比如常见的楼道自动开关、防盗报警等。


一、SR501模块介绍

引脚 : VCC,OUT, GND

功能 :一种常见的人体红外传感器模块,用于检测人体的活动。

红外感应原理 :SR501 模块内部包含一个红外传感器探测单元,该单元可以检测环境中的红外辐射变化。即使在黑暗中,人体也会通过辐射红外能量来体现温度差异。

  • 静止状态(无人靠近)时,OUT 引脚通常为电平。
  • 有人体靠近时,OUT 引脚通常会从低电平变为电平。

2 个电位器 : 可以通过电位器实现封锁时间和检测距离的调节 ( 延时控制,距离调节 )。

在这里插入图片描述在这里插入图片描述

二、设备树添加节点

配置设备树需要对 GPIO 引脚 以及相关的 pincontrol 配置。由于本实验是使用 SR501 模块,所以不需要配置 pincontrol 。

通过 SR501人体红外模块 的原理图得到 该模块 高电平有效。我将其接到开发板的 gpio4-19 引脚。
compatible :用于 和 驱动程序进行匹配。
使用 gpio4 组的 19 号引脚。(每一组有 32 个引脚)

在这里插入图片描述

三、驱动程序

  1. 定义字符设备结构体。
    由于 使用 模块 SR501,只需要读出引脚电平即可。
static struct file_operations sr501_ops={
	.owner = THIS_MODULE,
    .read  = sr501_read,
};
  1. 实现 read 函数。

wait_event_interruptible(sr501_wq, sr501_data); : 这是一个等待队列的函数调用。当前执行的线程(或进程)进入睡眠状态,直到满足指定的条件。

sr501_wq :等待队列头对象。

sr501_data 是条件。如果 sr501_data 为真(非零),表示数据已经准备好,线程可以继续执行。否则,线程将进入睡眠状态,并被放入等待队列。
copy_to_user 函数的作用是将内核空间中的数据复制到用户空间的缓冲区(buf)中。

static wait_queue_head_t sr501_wq;		// 定义队列头

static ssize_t sr501_read (struct file *file, char __user *buf, size_t size, loff_t *oddset)
{
	int err;
	int len = (size < 4) ? size : 4;
	wait_event_interruptible(sr501_wq, sr501_data);		/* 无数据休眠,有数据唤醒 */
	err = copy_to_user(buf, &sr501_data, len);
	sr501_data = 0;
	return len;
}
  1. 定义一个platform_driver
    sr501_table 数组 用于和设备树里的 信息进行匹配。
    匹配成功后 直接调用 sr501_probe 函数。
static const struct of_device_id sr501_table[] = {
	{ .compatible = "my,sr501"},
	{},
};

static struct platform_driver sr501_driver = {
	.driver = {
		.name		= "sr501",
		.of_match_table = sr501_table,
	},
	.probe			= sr501_probe,
	.remove			= sr501_remove,
};
  1. 注册一个 file_operations 结构体,platform_driver。
    在 入口函数里进行注册,在出口函数里进行 卸载。

init_waitqueue_head:这是一个内核函数,用于初始化一个等待队列头对象。等待队列头用于管理等待队列。
&sr501_wq:这是等待队列头对象的地址

static int sr501_init(void)  
{
	int err;
	major = register_chrdev(0, "sr501", &sr501_ops);
	class = class_create(THIS_MODULE, "sr501_class");
	err = PTR_ERR(class);   
	if (IS_ERR(class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "sr501");
		return -1;
	}
	
	platform_driver_register(&sr501_driver);
	
	init_waitqueue_head(&sr501_wq);						// 初始化等待队列头
	return 0;
}
static void sr501_exit(void)  
{
	platform_driver_unregister(&sr501_driver);
	class_destroy(class);
	unregister_chrdev(major, "sr501");
}
  1. 实现 probe 函数。
    当设备树 和 驱动和程序匹配成功后调用 probe 函数。

gpiod_get :从设备树里获取 GPIO 引脚信息。
==gpiod_direction_input ==: 设置引脚方向。()输入
gpiod_to_irq :获得中断号。
request_irq : 申请中断。第二个参数是 中断处理函数。

static int sr501_probe(struct platform_device *pdev)
{
	sr501_gpio = gpiod_get(&pdev->dev, NULL, 0);		//获取引脚信息
	gpiod_direction_input(sr501_gpio);		// 设置为 输入引脚

	irq = gpiod_to_irq(sr501_gpio);			// 获取中断号
	request_irq(irq, sr501_isr, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "sr501", NULL);		//请求中断

    device_create(class, NULL, MKDEV(major, 0), NULL, "sr501"); 		//创建设备节点
	return 0;
}
  1. 在 probe 里申请了,就需要在 remove 函数里进行卸载.
	device_destroy(class,MKDEV(major, 0));
	free_irq(irq, NULL);
	gpiod_put(sr501_gpio);
  1. 中断处理函数。
    wake_up 唤醒 在 read 函数里休眠的队列。将 sr501_data 赋值为 1 ,则 read 函数里条件为真,执行程序。
static irqreturn_t sr501_isr(int irq, void *dev_id)
{
	sr501_data = 1;
	wake_up(&sr501_wq);			/* 唤醒队列 */
	return IRQ_HANDLED;
}

四、测试程序

首先判断参数 argc 是否正确。
O_RDWR 可读可写的方式打开设备节点,获取设备句柄 fd
while 循环里读引脚电平,当 引脚为高电平 并且 正确读出时,打印有人靠近。

	if(argc != 2)
	{
		printf("Usage: %s <dev>\n",argv[0]);
		return -1;
	}

	//打开文件
	fd = open(argv[1], O_RDWR);
	if(-1 == fd)
	{
		printf("open %s error!\n",argv[1]);
		return -1;
	}

	while (1)
	{
		ret = read(fd, &val, 4);
		if((1 == val) && (ret == 4))
			printf("有人靠近!\n");
	}
	close(fd);

五、上机测试及效果

  1. 将 .ko 文件加载到内核。
    使用 insmod 命令可以将 KO 文件加载到内核中,使模块生效。而使用rmmod 命令可以卸载已加载的模块,lsmod 命令 可以观察已加载到内核的文件。
    在这里插入图片描述
  2. 执行测试程序。 /dev/sr501 是在驱动程序中创建的设备节点 ( device_create )。
    当有人靠近时,通过读出引脚电平的变化判断是否有人靠近。
    在这里插入图片描述

总结

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

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

相关文章

深度学习-第R1周心脏病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 我的环境&#xff1a; 语言环境&#xff1a;Python3.10.7编译器&#xff1a;VScode深度学习环境&#xff1a;TensorFlow 2.13.0 一、前期工作&#xff1a; …

语义通信中基于深度双Q网络的多维资源联合分配算法

目录 论文简介系统模型多维资源联合分配模型多维资源联合分配算法 论文简介 作者 林润韬 郭彩丽 陈九九 王彦君发表期刊or会议 《移动通信》发表时间 2023.4 系统模型 场景中的边缘服务器部署在路边单元上&#xff0c;每个路边单元具有一定的无线覆盖区域&#xff0c;服务器将…

安装mmocr

安装mmocr 一、安装mmdetection 在安装前&#xff0c;如果已经安装过mmcv&#xff0c;先卸载掉&#xff0c;否则不同版本会导致ModuleNotFoundError报错&#xff01; 1、先安装对应版本的pytorch&#xff08;本次cuda10.2&#xff0c;pytorch1.7&#xff09; 2、安装对应版本的…

TableGPT: Towards Unifying Tables, Nature Language and Commands into One GPT

论文标题&#xff1a;TableGPT: Towards Unifying Tables, Nature Language and Commands into One GPT 论文地址&#xff1a;https://github.com/ZJU-M3/TableGPT-techreport/blob/main/TableGPT_tech_report.pdf 发表机构&#xff1a;浙江大学 发表时间&#xff1a;2023 本文…

搭建基于Nginx+Keepalived的高可用web集群并实现监控告警

目录 搭建相关服务器DNS服务器配置WEB服务器配置配置静态IP编译安装nginx 负载均衡器配置lb1lb2高可用配置 NFS服务器配置配置静态IP安装软件包新建共享目录web服务器挂载 监控服务器配置安装node-exporter编写prometheus.yml安装alertmanager和钉钉插件获取机器人webhook编写a…

ubuntu22.04上如何创建有privilege权限,有固定自定义IP的空容器

需求背景&#xff1a; 我想用docker来隔离自己的主机环境&#xff0c;来创建一个隔离的空白全新的开发环境&#xff0c;并且使之有固定的IP&#xff0c;在里面可以自由更新下载各种编译依赖&#xff0c;具有privileged权限的容器&#xff0c;以下是操作实现的具体步骤 查看do…

系统架构设计师-软件架构设计(2)

目录 一、基于架构的软件开发方法&#xff08;ABSD&#xff09; 1、架构需求 1.1 需求获取 1.2 标识构件 1.3 架构需求评审 2、架构设计 2.1 提出架构模型 2.2 映射构件 2.3 分析构件的相互作用 2.4 产生架构 2.5 设计评审 3、架构文档化 4、架构复审 5、架构实现 5.1 分析与…

JVM运行时区域——对象创建内存分配过程

新创建的对象&#xff0c;都存放在伊甸园区域&#xff0c;当垃圾回收时&#xff0c;将伊甸园区域的垃圾数据销毁&#xff0c;然后将存活的对象转移到幸存者0区域&#xff0c;之后创建的新的对象还是存放在伊甸园区域&#xff0c;等到再次垃圾回收后&#xff0c;将伊甸园区域和幸…

《Docker资源限制和调度策略:性能优化与资源管理,打造高效稳定的容器环境》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Python 集合 pop()函数使用详解,pop随机删除原理

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 pop函数使用详解 1、随机删除并不完全随机1.1、纯数字1.2、纯字符1.3、混合情况 …

【软件测试】Git 详细实战-远程分支(超细总结)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 远程分支 远程引…

2023云曦期中复现

目录 SIGNIN 新猫和老鼠 baby_sql SIGNIN 签到抓包 新猫和老鼠 看到反序列化 来分析一下 <?php //flag is in flag.php highlight_file(__FILE__); error_reporting(0);class mouse { public $v;public function __toString(){echo "Good. You caught the mouse:&…

使用Selenium与Chrome DevTools交互

目录 为什么我们应该自动化Chrome开发工具&#xff1f; 如何打开Chrome DevTools 元素 控制台 源代码 网络 应用 安全 性能 如何使用Selenium使用chrome Devtools实现自动化&#xff1f; 收集性能指标 使用Selenium DevTols捕获控制台日志 模拟位置 网络节流 捕…

论文精读之Transformer论文

目录 Abstract Conclusion Introduction Background Training Abstract 在一个序列转录模型中&#xff0c;在编码器与译码器之间使用一个“注意力机制”的东西&#xff0c;做了两个机器翻译的实验&#xff0c;效果较其他模型效果更好。 Conclusion Transformer是第一个用于…

全志F1C200S嵌入式驱动开发(调整cpu频率和dram频率)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 f1c200s默认的cpu频率是408M,默认的dram频率是156M。这两个数值,坦白说,都算不上特别高的频率。因为我们的晶振是24M输入,所以408/24=17,相当于整个cpu的频率只是晶振倍频了17…

vue引入自定义字体并使用

结构 font.scss引入字体 charset "UTF-8";font-face{font-family: "caoshu";src: url("caoshu.ttf");font-weight: normal;font-style: normal; }font-face{font-family: "Xingkai";src: url("XingKai.ttf");font-weight: …

leetcode 144.二叉树的前序遍历 145.二叉树的后序遍历 94.二叉树的中序遍历

⭐️ 题目描述 &#x1f31f; 链接1&#xff1a;leetcode 144.二叉树的前序遍历 &#x1f31f; 链接2&#xff1a;leetcode 145.二叉树的后序遍历 &#x1f31f; 链接3&#xff1a;leetcode 94.二叉树的中序遍历 思路&#xff1a; leetcode的遍历和普通的遍历还略有一些不同&a…

【Spring篇】初识 Spring IoC 与 DI

目录 一. Spring 是什么 ? 二. 何为 IoC ? 三. 如何理解 Spring IoC ? 四. IoC 与 DI 五 . 总结 一. Spring 是什么 ? 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃⽽ 庞⼤…

SAP 执行失败JOB及dump日志监控

背景 系统使用时间较长&#xff0c;存在大量的后台作业&#xff0c;用户量较大&#xff0c;需要及时监控后台作业状况及系统dump情况&#xff0c;以便及时处理。 功能 1. 查询屏幕填写日期前n秒状态为错误及未知的后台作业 2. 查询屏幕填写日期前n秒系统中的dump记录--客制化程…

有关动态内存管理的笔试题

题目一&#xff1a; void GetMemory(char* p) {p (char*)malloc(100); }void test(void) {char* str NULL;GetMemory(str);strcpy(str, "hello world");printf(str); }int main() {test();return 0; } 请问上述代码输出结果是什么&#xff0c;理由是什么&#xf…