Linux驱动开发基础(SR501人体红外模块)

news2024/11/24 9:04:43

所学来自百问网

目录

1.模块简介

2.原理图及接线

3.设备树修改

4.驱动程序

5.应用程序

6.makefile

7.编译运行


1.模块简介

人体都有恒定的体温,一般在37度,所以会发出特定波长10uM左右的红外线,被动式红外探头就是靠探测人体发射的10uM左右的红外线而进行工作的。 人体发射的 10uM 左右的红外线通过菲泥尔滤光片增强后聚集到红外感应源上。 红外感应源通常采用热释电元件,这种元件在接收到人体红外辐射温度发生变化时就会失去电荷平衡,向外释放电荷,后续电路经检测处理后就能产生报警信号。 人体红外模块是一种能够检测人或动物发射的红外线而输出电信号的传感器。广泛应用于各种自动化控制装置中。比如常见的楼道自动开关、防盗报警等。 如果有人在量程内运动,DO引脚将会输出有效信号。

市面上人体红外模块有很多,但其外形和原理都差不多,如下是一个典型的人体红外模式原理图:

实物和使用方法如下图所示,可以设置探测距离、延迟控制等:

通过跳线来设置是否可以重复触发,默认为L。其中L表示不可重复,H表示可重复。含义如下:

① 不可重复触发方式: 感应到人体并输出高电平后,延时时间一结束,输出将自动从高电平变为低电平。

② 重复触发方式: 感应到人体后输出高电平后,在延时时间段内,如果有人体在其感应范围内活动,其输出将一直保持高电平,直到人离开后才延时将高电平变为低电平(感应模块检测到人体的每一次活动后会自动顺延一个延时时间段,并且以最后一次活动的时间为延时时间的起始点)。 可以通过电位器实现封锁时间和检测距离的调节:

① 调节检测距离: 即有效距离的远近。调节距离电位器顺时针旋转,感应距离增大(约 7 米); 反之,感应距离减小(约 3 米)。

② 封锁时间: 感应模块在每一次感应输出后(高电平变为低电平),可以紧跟着设置一个封锁时间,在此时间段内感应器不接收任何感应信号。 此功能可以实现(感应输出时间和封锁时间)两者的间隔工作,可应用于间隔探测产品;同时此功能可有效抑制负载切换过程中产生的各种干扰。 调节延时电位器顺时针旋转,感应延时加长(约300S),反之,感应延时减短(约0.5S)。

2.原理图及接线

以imx6ull为例:

接线图为:

3.设备树修改

进入对应目录在根节点下添加如下代码:

在iomuxc节点下添加:

修改完成后编译设备树

4.驱动程序

#include <linux/module.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>

static int major;
static struct class *sr501_class;
static struct gpio_desc *sr501_gpio;
static int irq;
static int sr501_data = 0;  
static wait_queue_head_t sr501_wq; // 等待队列

/* 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t sr501_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
#if 0
	int val;
	int len = (size < 4)? size : 4;
	
	val = gpiod_get_value(sr501_gpio); 
	copy_to_user(buf, &val, len);
	return len;
#else
	int len = (size < 4)? size : 4;
	
	/*无数据就休眠:  放入某个链表 */
	wait_event_interruptible(sr501_wq, sr501_data);	
	/*有数据就copy_to_uesr */
	copy_to_user(buf, &sr501_data, len);
	// 重置状态
	sr501_data = 0;
	return len;
#endif
}

static unsigned int sr501_drv_poll(struct file *fp, poll_table * wait)
{
//	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
//	poll_wait(fp, &sr501_wait, wait);
	return 0;
}


/* 定义自己的file_operations结构体                                              */
static struct file_operations sr501_fops = {
	.owner	 = THIS_MODULE,
	.read    = sr501_drv_read,
	.poll    = sr501_drv_poll,
};


static irqreturn_t sr501_isr(int irq, void *dev_id)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	/* 1. 记录数据 */
	sr501_data = 1;

	/* 2. 唤醒APP:去同一个链表把APP唤醒 */
	wake_up(&sr501_wq);
	
	return IRQ_HANDLED; // IRQ_WAKE_THREAD;
}


/* 1. 从platform_device获得GPIO
 * 2. gpio=>irq
 * 3. request_irq
 */
static int sr501_probe(struct platform_device *pdev)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* 1. 获得硬件信息 */
	// 获取gpio信息
	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);

	/* 2. device_create */
	// 设备创建放在这里的主要原因是为了当有多个节点匹配时,为每个节点创建设备
	device_create(sr501_class, NULL, MKDEV(major, 0), NULL, "/dev/sr501");
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	return 0;
}

static int sr501_remove(struct platform_device *pdev)
{
	// 设备销毁
	device_destroy(sr501_class, MKDEV(major, 0));
	// 清空中断号
	free_irq(irq, NULL);
	// 释放获取的GPIO信息
	gpiod_put(sr501_gpio);
	return 0;
}

// 用于与platform_driver匹配
static const struct of_device_id ask100_sr501[] = {
    { .compatible = "100ask,sr501" },
    { },
};

/* 1. 定义platform_driver */
static struct platform_driver sr501s_driver = {
    .probe      = sr501_probe,
    .remove     = sr501_remove,
    .driver     = {
        .name   = "100ask_sr501",
        .of_match_table = ask100_sr501,
    },
};

/* 2. 在入口函数注册platform_driver */
static int __init sr501_init(void)
{
    int err;
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* 注册file_operations 	*/
	major = register_chrdev(0, "sr501", &sr501_fops);  

	sr501_class = class_create(THIS_MODULE, "sr501_class");
	if (IS_ERR(sr501_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "sr501");
		return PTR_ERR(sr501_class);
	}
	// 初始化等待队列
	init_waitqueue_head(&sr501_wq);

	
    err = platform_driver_register(&sr501s_driver); 
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	return err;
}

/* 3. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数
 *     卸载platform_driver
 */
static void __exit sr501_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    platform_driver_unregister(&sr501s_driver);
	class_destroy(sr501_class);
	unregister_chrdev(major, "sr501");
}


/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */

module_init(sr501_init);
module_exit(sr501_exit);

MODULE_LICENSE("GPL");

5.应用程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>

static int fd;

/*
 * ./sr501_test /dev/sr501
 *
 */
int main(int argc, char **argv)
{
	int val;

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


	/* 2. 打开文件 */
	fd = open(argv[1], O_RDWR);
	if (fd == -1)
	{
		printf("can not open file %s\n", argv[1]);
		return -1;
	}


	while (1)
	{
		if (read(fd, &val, 4) == 4)
			printf("get body: 0x%x\n", val);
		else
			printf("while get body: -1\n");
	}
	
	close(fd);
	
	return 0;
}

6.makefile


# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR
# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量:
# 2.1 ARCH,          比如: export ARCH=arm64
# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu-
# 2.3 PATH,          比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin 
# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同,
#       请参考各开发板的高级用户使用手册

KERN_DIR =  /home/book/100ask_imx6ull-sdk/Linux-4.9.88

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	$(CROSS_COMPILE)gcc -o sr501_test sr501_test.c
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order  sr501_test

# 参考内核源码drivers/char/ipmi/Makefile
# 要想把a.c, b.c编译成ab.ko, 可以这样指定:
# ab-y := a.o b.o
# obj-m += ab.o

obj-m += sr501_drv.o

7.编译运行

将编译好的设备树传入开发板并复制到/boot目录下并重启开发板

[root@100ask:/mnt]# cp 100ask_imx6ull-14x14.dtb /boot
[root@100ask:/mnt]# reboot

编译出ko文件:

传入开发板

装载并查看驱动是否装载成功

查看是否匹配成功

运行

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

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

相关文章

Kafka·概述

概览 Producer 生产者发送消息给broker&#xff0c;并不是生成一条消息后立刻发送&#xff0c;而是积攒多条后&#xff0c;批量发送到broker。可以通过配置参数batch.size&#xff08;单位字节&#xff09;调整积攒多少后发送 Consumer Topic 消息的分类 当Producer发送指定…

沾包问题,wireshark和netstat的使用

一.沾包 TCP是一个面向字节流的传输层协议。“流” 意味着 TCP 所传输的数据是没有边界的。这不同于 UDP 协议提供的是面向消息的传输服务&#xff0c;其传输的数据是有边界的。TCP 的发送方无法保证对方每次收到的都是一个完整的数据包。于是就有了粘包、拆包问题的出现。粘包…

[数据集][目标检测]电力场景输电线杆塔塔架金属锈蚀腐蚀生锈检测数据集VOC+YOLO格式1344张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1344 标注数量(xml文件个数)&#xff1a;1344 标注数量(txt文件个数)&#xff1a;1344 标注…

医学领域使用Python语言的逻辑和代码的规范

在医学领域使用Python进行数据分析和建模时&#xff0c;掌握良好的编程逻辑和代码规范非常重要。这不仅可以提高代码的质量&#xff0c;还能让其他研究人员更容易理解和复现你的工作。下面是一些关于如何编写高质量Python代码的建议&#xff1a; 代码组织 模块化&#xff1a;…

软件设计师教程(第5版)第5章 软件工程基础知识(更新中)

5.1 软件工程概述 【软件工程】是指应用计算机科学、数学及管理科学等原理,以工程化的原则和方法来解决软件问题的工程&#xff0c;其目的是提高软件生产率、提高软件质量、降低软件成本。P239 5.1.1 计算机软件 计算机软件是指计算机系统中的【程序】及其【文档】。P240 【…

android13 隐藏状态栏里面的背光调节 隐藏下拉栏背光调节

总纲 android13 rom 开发总纲说明 目录 1.前言 2.问题分析 3.修改方法 4.编译运行 5.彩蛋 1.前言 隐藏下拉栏里面的背光调节,禁止用户在这里调节背光亮度。 2.问题分析 我们找到对应的布局,然后在里面隐藏掉。 使用之前文章介绍的布局查找工具,查找亮度条id id/bri…

驱动开发系列11 - Linux Graphics 图形栈概述(二)

目录 一:GPU 和 硬件 现代 GPU 功能概览: 硬件结构: 屏幕驱动: 屏幕连接器: 屏幕 CRT 控制器: CPU与GPU通信: 现代主机通信总线介绍: 通信方法: GPU 编程:通过 MMIO 访问寄存器 CPU 和 GPU 内存请求路由: GPU 可访问的内存区域: GTT/GART 是 CPU 与 GPU 共享的通信缓…

谷粒商城实战笔记-254-商城业务-消息队列-Direct-Exchange

文章目录 一&#xff0c;252-商城业务-消息队列-Direct-Exchange1&#xff0c;创建4个队列2&#xff0c;exchange绑定queue3&#xff0c;发送消息 二&#xff0c;253-商城业务-消息队列-Fanout-Exchange1&#xff0c;创建一个type为fanout的exchange2&#xff0c;给这个exchang…

开源的即时聊天解决方案Papercups

Papercups&#xff1a;让聊天支持变得简单、私密、实时。 - 精选真开源&#xff0c;释放新价值。 概览 Papercups是一款开源的实时客户支持工具&#xff0c;它使用Elixir语言构建&#xff0c;为注重客户数据隐私和安全性的公司提供了一个自托管的解决方案。这款工具的设计理念…

【C语言】常见文件操作

文件的常见操作 #include<stdio.h>// 由于devc代码编码为ANCI&#xff0c;故读取的文件中若有中文&#xff0c;请设置文件编码为ANCI&#xff0c;否则会乱码 // 读文件 void test1() {char ch;FILE *fp; // 创建文件指针fp fopen("./file.txt", "r"…

秋招突击——8/21——知识补充——计算机网络——cookie、session和token

文章目录 引言正文Cookie——客户端存储和管理Session——服务端存储和管理Token补充签名和加密的区别常见的加密算法和签名算法 面试题1、HTTP用户后续的操作&#xff0c;服务端如何知道属于同一个用户&#xff1f;如果服务端是一个集群机器怎么办&#xff1f;2、如果禁用了Co…

BaseCTF [第 1 周] ez_maze

笔记。 64ida打开。 更加确定。 所以常规做这类型题 思路(简单的话)&#xff1a; 先提取字符 计算其长度 对半分。 BaseCTF{131b7d6e60e8a34cb01801ae8de07efe}

基于YOLOv8的无人机高空红外(HIT-UAV)检测算法,魔改SimAM注意力助力涨点(一)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文内容&#xff1a;针对基于YOLOv8的无人机高空红外&#xff08;HIT-UAV&#xff09;检测算法进行性能提升&#xff0c;加入各个创新点做验证性试验。 1&#xff09;魔改SimAM注意力&#xff0c;引入切片操作&#xff1a;mAP从原始的…

算法日记day 46(单调栈之下一个更大元素|柱状图中最大图形)

一、下一个更大元素1 题目&#xff1a; nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。 给你两个 没有重复元素 的数组 nums1 和 nums2 &#xff0c;下标从 0 开始计数&#xff0c;其中nums1 是 nums2 的子集。 对于每个 0 …

【Oracle问题】ORA-12516:监听程序找不到符合协议堆栈要求的可用处理程序问题处理

ORA-12516:监听程序找不到符合协议堆栈要求的可用处理程序 这种一般都是会话数或者process和session已经到达临界值或者超过最大值了。 1.先cmd登录sqlplus&#xff1a; sqlplus / as sysdba;2.查看设置的最大的连接数和进程数&#xff1a; show parameter process&#xff…

三维平面电磁铁、交流电磁铁、显微镜磁场北京大学方案

根据用户北京大学需求设计制造方案如下 三维平面电磁铁产品规格 5MPS63-25型三维平面电磁铁&#xff0c;X、Y方向磁场由2对正交的磁极产生&#xff0c;Z轴由一组同轴线圈产生&#xff1b; 每轴对应的两个线圈正接产生均匀磁场&#xff0c;反接产生梯度磁场&#xff1b; …

JetBrains GoLand 2024.2 (macOS, Linux, Windows) - 为 Go 开发者打造的完整 IDE

JetBrains GoLand 2024.2 (macOS, Linux, Windows) - 为 Go 开发者打造的完整 IDE JetBrains 跨平台开发者工具 请访问原文链接&#xff1a;https://sysin.org/blog/jetbrains-goland/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sy…

一文解决---IDEA汉化问题(含中英文切换)

一、英文->中文&#xff1a; ①.下载汉化包插件&#xff1a; 操作顺序&#xff1a;File->Settings->Plugins 在搜索框输入Chinese&#xff0c;然后找到 Chinese (Simplified) Language &#xff08;汉化插件&#xff09;&#xff0c;等待下载完→Install (安装)&…

《机器学习》—— 通过下采样方法实现逻辑回归分类问题

文章目录 一、什么是下采样方法&#xff1f;二、通过下采样方法实现逻辑回归分类问题三、下采样的优缺点 一、什么是下采样方法&#xff1f; 机器学习中的下采样&#xff08;Undersampling&#xff09;方法是一种处理不平衡数据集的有效手段&#xff0c;特别是在数据集中某些类…

VTK随笔三:坐标系统、空间变换、VTK管线、VTK智能指针

一、坐标系统 Model坐标系统&#xff1a;定义模型时所采用的坐标系统&#xff0c;通常是局部的笛卡尔坐标系。World坐标系统&#xff1a;是放置Actor的三维空间坐标系&#xff0c;Actor(vtkActor类)其中的一个功能就是负责将模型从Model坐标系统变换到World坐标系统。每一个模…