Linux驱动---光电开关、火焰传感器、人体红外传感器

news2024/10/10 0:26:35

文章目录

  • 一、电路连接
  • 二、设备树
  • 三、驱动代码

一、电路连接

人体红外 – PF12
检测到人体时会产生一个上升沿

光电开关 – PE15
有遮挡物时会产生一个上升沿

火焰传感器 – PF5
有火焰时会产生一个上升沿

二、设备树

/{	
	//人体红外PF12
	human{ 
		compatible = "zyx,human";
		interrupt-parent = <&gpiof>;  	//中断父节点是gpiof
		interrupts = <12 0>;			//第一个参数是中断控制器下标
	};
	//光电开关PE15
	light{
		compatible = "zyx,light";
		interrupt-parent = <&gpioe>;
		interrupts = <15 0>;
	};
	//火焰传感器PF5
	fire{
		compatible = "zyx,fire";
		interrupt-parent = <&gpiof>;
		interrupts = <5 0>;
	};
};

三、驱动代码

以光电开关为例
使用了platform总线驱动

/***人体红外PF12
 * ***/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h> //设备树文件相关头文件
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>

#define CNAME "light"
struct cdev *cdev_light;
struct class *class_light;
struct device *device_light;
int major = 0; //主设备号
int minor = 0;
dev_t devno_light;

int irqno_light; //中断号

/***中断处理函数***/
irqreturn_t light_irq_handler(int irqno, void *dev){
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return IRQ_HANDLED;
}

/***字符设备***/
int light_open(struct inode *inode, struct file *file){
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
int light_close (struct inode *inode, struct file *file){
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}

const struct file_operations lightfops = {
    .open = light_open,
    .release = light_close,
};

int light_probe(struct platform_device *dev){
    int ret=0;
    /***注册字符设备驱动***/
    //1. 分配对象
    cdev_light = cdev_alloc();
    if(NULL == cdev_light){ //成功返回结构体指针,失败返回NULL
        pr_err("cdev_alloc error");
        ret = -ENOMEM;
        goto err1;
    }
    //初始化对象:部分成员初始化
    cdev_init(cdev_light,&lightfops);
    //申请设备号:如果major为0,则动态申请,否则就静态指定
    if(major > 0){ //静态申请
        ret = register_chrdev_region(MKDEV(major,minor),1,CNAME);
        if (ret) {
            pr_err("register_chrdev_region error\n");
            goto err2;
        }
    }else if(major == 0){ //动态申请
        ret = alloc_chrdev_region(&devno_light,0,1,CNAME); 
        if (ret) {
            pr_err("alloc_chrdev_region error\n");
            goto err2;
        }
        major=MAJOR(devno_light);
        minor=MINOR(devno_light);
    }
    //注册
    ret = cdev_add(cdev_light,MKDEV(major,minor),1); 
    if (ret) {
        pr_err("cdev_add error\n");
        goto err3;
    }
    /***自动创建设备节点***/
    class_light=class_create(THIS_MODULE,CNAME);
    if(IS_ERR(class_light)){
        pr_err("class_create error");
        ret = PTR_ERR(class_light);
        goto err4;
    }
    device_light = device_create(class_light,NULL,MKDEV(major,minor),NULL,CNAME);
     if(IS_ERR(device_light)){
        pr_err("device_create error");
        ret = PTR_ERR(device_light);
        goto err5;
    }
    /***初始化中断***/
    //获取软中断号
    irqno_light=platform_get_irq(dev,0);
    if(irqno_light < 0){
        pr_err("platform_get_irq error");
        ret = irqno_light;
        goto err6;
    }
    //3.注册中断号
    ret = request_irq(irqno_light,light_irq_handler,IRQF_TRIGGER_FALLING,"light_IRQ",NULL);
    if(ret){
        pr_err("request_irq error");
        goto err6;
    }

    return 0;
err6:
    device_destroy(class_light, MKDEV(major,minor));
err5:
    class_destroy(class_light);
err4:
    cdev_del(cdev_light);
err3:
    unregister_chrdev_region(MKDEV(major,minor),1);
err2:
    kfree(cdev_light);
err1:
    return ret;
}

int light_remove(struct platform_device *dev){
    free_irq(irqno_light,NULL);
    device_destroy(class_light, MKDEV(major, minor));
    class_destroy(class_light);
    cdev_del(cdev_light);
    unregister_chrdev_region(MKDEV(major,minor),1);
    kfree(cdev_light);
    return 0;
}

//设备树匹配
struct of_device_id	light_of_match[]={
    {.compatible="zyx,light"},
    {},
};
struct platform_driver light_driver={
    .probe=light_probe,
    .remove=light_remove,
    .driver={
        .name="light_driver",
        .of_match_table=light_of_match,
    },
};

module_platform_driver(light_driver);
MODULE_LICENSE("GPL");

实验现象:

当触发光电开关的中断时,就会打印提示信息
在这里插入图片描述

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

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

相关文章

电池大师 2.3.9 | 专业电池管理,延长寿命优化性能

Battery Guru 显示电池使用情况信息&#xff0c;测量电池容量&#xff08;mAh&#xff09;&#xff0c;并通过有用技巧帮助用户改变充电习惯&#xff0c;延长电池寿命。支持显示电池健康状况&#xff0c;优化电池性能。 大小&#xff1a;9.6M 百度网盘&#xff1a;https://pan…

数据库软题7-数据库设计

一、概念结构设计 题1-ER图的属性分类 题2-局部ER图的冲突分类 1.命名冲突 命名冲突有同名异义&#xff0c;异名同义2.结构冲突 结构冲突分为&#xff1a;统一实体不同属性&#xff0c;同一对象在不同关系里可能为属性或者实体 教师其实就是职工&#xff0c;他们有不同的属性…

基于Arduino的超声波测距模块HC-SR04

一. HC-SR04超声波模块简介 HC-SR04超声波模块是一种常用的测距模块&#xff0c;通过不断检测超声波发射后遇到障碍物所反射的回波&#xff0c;从而测出发射和接收回波的时间差&#xff0c;并据此求出距离。它主要由两个‌压电陶瓷超声传感器和一个外围信号处理电路构成&#…

重生之我在代码随想录刷算法第十九天 | 第77题. 组合、216.组合总和III、 17.电话号码的字母组合

参考文献链接&#xff1a;代码随想录 本人代码是Java版本的&#xff0c;如有别的版本需要请上代码随想录网站查看。 第77题. 组合 力扣题目链接 解题思路 这道题目乍一看可以用暴力解法解决&#xff0c;但如果k的数量增加那就需要套特别多的循环&#xff0c;所以这种组合类…

植物大战僵尸修改器-MFC

创建项目 创建mfc应用 基于对话框 打开资源视图下的 IDD_MFCAPPLICTION2_DIALOG 限制对话框大小 将属性中Border的值改为对话框外框 删除对话框中原有的控件 属性-外观-Caption 设置对话框标题 工具箱中拖放一个按钮 修改按钮名称 将按钮ID改为IDC_COURSE 在MFCApplication2…

django(二):定义第一个函数及url介绍

1.定义index函数 """ django里的第一个函数必须是request,不写会报错 """def index(request):return HttpResponse("Hello, world. Youre at the index of djangoProject.")注意&#xff01; ①.index函数里的形参必须为request ②.r…

STM32输入捕获模式详解(上篇):原理、测频法与测周法

1. 前言 在嵌入式系统的开发过程中&#xff0c;常常需要对外部信号进行精确的时间测量&#xff0c;如测量脉冲信号的周期、频率以及占空比等。STM32系列微控制器提供了丰富的定时器资源&#xff0c;其中的输入捕获&#xff08;Input Capture, IC&#xff09;模式能实现对信号的…

【测试】BUG篇——BUG

bug的概念 定义&#xff1a;⼀个计算机bug指在计算机程序中存在的⼀个错误(error)、缺陷(flaw)、疏忽(mistake)或者故障(fault)&#xff0c;这些bug使程序⽆法正确的运⾏。Bug产⽣于程序的源代码或者程序设计阶段的疏忽或者错误。 准确的来说&#xff1a; 当且仅当规格说明&am…

网站集群批量管理-Ansible(ad-hoc)

1. 概述 1. 自动化运维: 批量管理,批量分发,批量执行,维护 2. 无客户端,基于ssh进行管理与维护 2. 环境准备 环境主机ansible10.0.0.7(管理节点)nfs01 10.0.0.31(被管理节点)backup10.0.0.41(被管理节点) 2.1 创建密钥认证 安装sshpass yum install -y sshpass #!/bin/bash ##…

SpringBoot整合MyBatis记录

整体目录结构 创建数据库 创建一个MySQL的表&#xff0c;表名是student。 create table student (id int auto_increment comment 唯一标识idprimary key,name varchar(30) not null comment 姓名,age int not null comment 年龄 ) 插入一条数据记录到数据库当中去…

【数据结构与算法-高阶】并查集

【数据结构与算法-高阶】并查集 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;数据结构与算法&#x1f345; &#x1f33c;文章目录&#x1f33c; 1. 并查集原理 2. 并查集实现 3. 并查集应用 1. 并查集原理 在一些应用问题中&…

Matlab|基于遗传粒子群算法的无人机路径规划【遗传算法|基本粒子群|遗传粒子群三种方法对比】

目录 主要内容 模型研究 部分代码 结果一览 下载链接 主要内容 为了更高效地完成复杂未知环境下的无人机快速探索任务&#xff0c;很多智能算法被应用于无人机路径规划方面的研究&#xff0c;但是传统粒子群算法存在粒子更新思路单一、随机性受限、收敛速度慢…

修改calibre-web最大文件上传值

修改calibre-web最大文件上传值 Windows安装calibre-web&#xff0c;Python-CSDN博客文章浏览阅读541次&#xff0c;点赞10次&#xff0c;收藏11次。pip install calibreweb报错&#xff1a;error: Microsoft Visual C 14.0 or greater is required. Get it with "Microso…

案例:问题处理与原因分析报告的模板

系统上线后暴露的问题也是一种财富&#xff0c;我们需要从中吸收经验教训&#xff0c;规避其他类似的问题。对于上线后的问题如何进行原因分析&#xff0c;我提供两个分析报告的模板&#xff0c;供大家参考。 模板案例1&#xff1a;共性现象的原因分析报告 模板案例二&#xf…

C(十三)for、while、do - while循环的抉择 --- 打怪闯关情景

前言&#xff1a; 继C&#xff08;十&#xff09;for循环 --- 黑神话情景之后&#x1f449; https://blog.csdn.net/2401_87025655/article/details/142684637 今天&#xff0c;杰哥想用一个打怪闯关的场景让与大家一起初步认识一下for、while、do - while循环的抉择。&#xf…

Docker在linux系统中的下载与使用

Docker在linux系统中的下载与使用 一、docker作用,下载及安装二、docker镜像三、创建容器四、容器数据卷 一、docker作用,下载及安装 ubuntu下载安装docker 命令&#xff1a;在ubuntu上面执行这个命令 Docker version:查看docker是否安装成功 配置阿里云镜像加速:进入阿里云网站…

阿里140滑块-滑块验证码逆向分析思路学习

一、声明&#xff01; 原创文章&#xff0c;请勿转载&#xff01; 本文内容仅限于安全研究&#xff0c;不公开具体源码。维护网络安全&#xff0c;人人有责。 文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;均已做脱敏处…

JUC高并发编程8:读写锁

1 概述 1.1 悲观锁和乐观锁 在并发编程中&#xff0c;锁机制是用来控制多个线程对共享资源的访问。悲观锁和乐观锁是两种不同的并发控制策略。 1.1.1 悲观锁&#xff08;Pessimistic Locking&#xff09; 悲观锁假设在最坏的情况下&#xff0c;多个线程会同时访问和修改共享…

Qt-QDockWidget浮动窗口相关操作(49)

目录 描述 使用 描述 在 Qt 中&#xff0c;浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗口⼀般是位于核心部件的周围&#xff0c;可以有多个。 使用 创建我们可以参考下面的语法格式 使用起来也很简单&#xff0c;不过只能创建一个 Q…

【C语言】使用结构体实现位段

文章目录 一、什么是位段二、位段的内存分配1.位段内存分配规则练习1练习2 三、位段的跨平台问题四、位段的应用五、位段使用的注意事项 一、什么是位段 在上一节中我们讲解了结构体&#xff0c;而位段的声明和结构是类似的&#xff0c;它们有两个不同之处&#xff0c;如下&…