驱动开发 Linux按键中断点灯

news2025/1/11 2:41:08

华清远见上海中心22071班

三个按键实现按键中断,

key1->led1

key2->led2

key3->led3

按键按一下灯亮,再按一下灯灭 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>

#define CNAME "myled"
int major;
int minor = 0;
int count = 3;
int irqnum_key1;
int irqnum_key2;
int irqnum_key3;
struct cdev *cdev;
struct class *cls;
struct device *dvc;
struct device_node *lednode;
struct device_node *irqnode;
struct gpio_desc *topled1;
struct gpio_desc *topled2;
struct gpio_desc *topled3;
// myleds
// {
//     topled1 = <&gpioe 10 0>;
//     topled2 = <&gpiof 10 0>;
//     topled3 = <&gpioe 8 0>;
// };
// myirq
// {
//     interrupt-parent = <&gpiof>;
//     interrupts = <7 0>, <8 0>, <9 0>; //第一个成员指的是gpio编号,第二个成员表示触发方式,0表示默认属性
// };

struct file_operations fops;

irqreturn_t irq_handler_key1(int irqno, void *dev)
{
    gpiod_set_value(topled3, !gpiod_get_value(topled3));
    return IRQ_HANDLED;
}

irqreturn_t irq_handler_key2(int irqno, void *dev)
{
    gpiod_set_value(topled2, !gpiod_get_value(topled2));
    return IRQ_HANDLED;
}

irqreturn_t irq_handler_key3(int irqno, void *dev)
{
    gpiod_set_value(topled1, !gpiod_get_value(topled1));
    return IRQ_HANDLED;
}

static int __init led_init(void)
{
    int res, i;
    dev_t devt;

    //分配cdev结构
    cdev = cdev_alloc();
    if (NULL == cdev)
    {
        printk("申请空间失败\n");
        res = -EIO;
        goto ERR1;
    }

    //初始化cdev结构体
    cdev_init(cdev, &fops);

    //动态注册字符设备编号
    res = alloc_chrdev_region(&devt, 0, count, CNAME);
    if (res)
    {
        printk("动态注册字符设备编号失败(err %d)\n", -res);
        goto ERR2;
    }
    major = MAJOR(devt);
    minor = MINOR(devt);

    //向系统中添加字符设备
    res = cdev_add(cdev, devt, count);
    if (res)
    {
        printk("系统添加字符设备失败(err %d)\n", -res);
        goto ERR3;
    }

    //上传目录
    cls = class_create(THIS_MODULE, CNAME);
    if (IS_ERR(cls))
    {
        printk("上传目录失败 (err %ld)\n", PTR_ERR(cls));
        res = PTR_ERR(cls);
        goto ERR4;
    }

    //上传节点
    for (i = 0; i < count; i++)
    {
        dvc = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
        if (IS_ERR(dvc))
        {
            printk("节点上传失败 (err %ld)\n", PTR_ERR(dvc));
            res = PTR_ERR(dvc);
            goto ERR5;
        }
    }

    lednode = of_find_node_by_path("/myleds");
    if (NULL == lednode)
    {
        printk("寻找设备树节点失败\n");
        res = -EFAULT;
        goto ERR5;
    }

    //申请GPIO号
    topled1 = gpiod_get_from_of_node(lednode, "topled1", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(topled1))
    {
        printk("topled1 GPIO号获取编号失败 (err %ld)\n", PTR_ERR(topled1));
        res = PTR_ERR(topled1);
        goto ERR5;
    }

    topled2 = gpiod_get_from_of_node(lednode, "topled2", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(topled2))
    {
        printk("topled2 GPIO号获取编号失败 (err %ld)\n", PTR_ERR(topled2));
        res = PTR_ERR(topled2);
        goto ERR5;
    }

    topled3 = gpiod_get_from_of_node(lednode, "topled3", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(topled3))
    {
        printk("topled3 GPIO号获取编号失败 (err %ld)\n", PTR_ERR(topled3));
        res = PTR_ERR(topled3);
        goto ERR5;
    }

    //设置相对应的gpio引脚为输出模式
    gpiod_direction_output(topled1, 0);
    gpiod_direction_output(topled2, 0);
    gpiod_direction_output(topled3, 0);

    //获取中断设备树节点
    irqnode = of_find_node_by_path("/myirq");
    if (NULL == lednode)
    {
        printk("寻找设备树节点失败\n");
        res = -EFAULT;
        goto ERR5;
    }

    //从节点信息中获取KEY1软中断号
    irqnum_key1 = irq_of_parse_and_map(irqnode, 2);
    if (irqnum_key1 == 0)
    {
        printk("key1 获取软中断号失败\n");
        res = -EINVAL;
        goto ERR5;
    }

    //从节点信息中获取KEY2软中断号
    irqnum_key2 = irq_of_parse_and_map(irqnode, 0);
    if (irqnum_key2 == 0)
    {
        printk("key2 获取软中断号失败\n");
        res = -EINVAL;
        goto ERR5;
    }

    //从节点信息中获取KEY3软中断号
    irqnum_key3 = irq_of_parse_and_map(irqnode, 1);
    if (irqnum_key3 == 0)
    {
        printk("key3 获取软中断号失败\n");
        res = -EINVAL;
        goto ERR5;
    }

    //将需要使用的软中断号key1注册进内核
    res = request_irq(irqnum_key1, irq_handler_key1, IRQF_TRIGGER_FALLING, "key1_inte", NULL);
    if (res)
    {
        printk("key1 注册失败\n");
        return -EINVAL;
    }
    //将需要使用的软中断号key2注册进内核
    res = request_irq(irqnum_key2, irq_handler_key2, IRQF_TRIGGER_FALLING, "key2_inte", NULL);
    if (res)
    {
        printk("key2 注册失败\n");
        return -EINVAL;
    }
    //将需要使用的软中断号key3注册进内核
    res = request_irq(irqnum_key3, irq_handler_key3, IRQF_TRIGGER_FALLING, "key3_inte", NULL);
    if (res)
    {
        printk("key3 注册失败\n");
        return -EINVAL;
    }

    return 0;
ERR5:
    for (--i; i >= 0; i--)
    {
        device_destroy(cls, MKDEV(major, i));
    }
    class_destroy(cls);

ERR4:
    cdev_del(cdev);
ERR3:
    unregister_chrdev_region(devt, count);
ERR2:
    kfree(cdev);
ERR1:
    return res;
}

static void __exit led_exit(void)
{
    int i;
    gpiod_set_value(topled1, 0);
    gpiod_set_value(topled2, 0);
    gpiod_set_value(topled3, 0);

    gpiod_put(topled1);
    gpiod_put(topled2);
    gpiod_put(topled3);

    for (i = 0; i < count; i++)
    {
        device_destroy(cls, MKDEV(major, i));
    }
    class_destroy(cls);

    cdev_del(cdev);

    unregister_chrdev_region(MKDEV(major, minor), count);

    kfree(cdev);

    free_irq(irqnum_key1, NULL);
    free_irq(irqnum_key2, NULL);
    free_irq(irqnum_key3, NULL);
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

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

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

相关文章

外贸供应链ERP怎么选?全流程综合管理解析

随着外贸体制深入改革、进出口权放开等&#xff0c;以往处于垄断地位&#xff0c;享有种种优惠政策的外贸企业&#xff0c;将面临越来越严峻的国内外市场的竞争及各种挑战。长期以来形成的相对落后的管理体制和经营模式&#xff0c;严重地影响外贸企业在新形势下的生存和发展。…

m基于GA遗传优化+SA模拟退火的混合改进算法的多产品多机器生产优化matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 这里&#xff0c;我们首先介绍一下改进算法的基本原理&#xff0c;按照前面说的&#xff0c;这里我们主要将GA和SA进行合并。 这里&#xff0c;我研究了下&#xff0c;将两种算法做如下方法的结合…

Microcorruption 第一关 Tutorial

Microcorruptioin 第一关 Tutorial 首先进入Tutorial这一关&#xff0c;这是闯关页面。 在主函数设置断点&#xff0c;控制台输入"break main"或"b main"或手动点击反汇编栏中main函数的第一行设置断点。 该闯关游戏主要是破解密码&#xff0c;查看主函数…

前端开发免费资源分享

Fancy-Border-Radius 地址&#xff1a;https://9elements.github.io/fancy-border-radius/ 简介&#xff1a;在线编辑border-radius的可视化工具&#xff0c;通过调节可以很方便地帮我们生成想要的形状&#xff0c;然后直接复制下面的css代码&#xff0c;即可使用 Make some …

sCrypt 合约中的椭圆曲线算法:第二部分

我们在脚本中实现了椭圆曲线 (EC) 算法。在之前的实现中&#xff0c;我们进行链下计算并在脚本中验证结果。我们这里直接用脚本计算。 基于EC的应用非常多&#xff0c;特别是在密码学领域&#xff0c;如数字签名、加密、承诺方案等。作为具体示例&#xff0c;我们重新实现了 E…

11.28作业

实现对点灯所涉及函数的封装 1.头文件 #ifndef __GPIO_H__ #define __GPIO_H__ //结构体封装 typedef struct{volatile unsigned int MODER;volatile unsigned int OTYPER;volatile unsigned int OSPEEDR;volatile unsigned int PUPDR;volatile unsigned int IDR;volatile un…

Kotlin进阶指南 - 单元测试

为了减少一些功能繁琐的测试流程&#xff0c;单元测试是提升开发效率的有效方式之一 在早些年的时候我有记录过一篇 Android 使用单元测试&#xff0c;只不过当时更多的针对 Java 方面的单元测试&#xff1b;在使用 Kotlin 后&#xff0c;我发现单元测试有点不同&#xff0c;好…

Nacos注册中心和服务消费方式

目录 一&#xff0c;服务治理介绍 什么是服务治理&#xff1f; 常见的注册中心 二&#xff0c;nacos简介 三&#xff0c;搭建nacos环境 四&#xff0c;代码演示 五&#xff0c;基于Feign实现服务调用 什么是Feign Feign的使用 Feign参数传递 一&#xff0c;服务治理介…

全国心力衰竭日:重症心衰的黑科技——永久型人工心脏

今天是第8个“全国心力衰竭日”。近几年&#xff0c;中国逐渐老龄化&#xff0c;心衰则是老龄化面临的严峻问题。我国心衰患病率估计已达1.3%&#xff0c;至少有1000万心力衰竭患者。中国已成为世界上拥有最大心衰患者群的国家之一。心力衰竭作为大多数心血管疾病的终末阶段&am…

如何在 docker 容器使用 nginx 实现反向代理统一站点入口

在微服务架构下&#xff0c;我们会部署很多微服务来实现我们的系统。每个微服务会有不同的端口。而用户在访问我们的站点时希望通过统一的端口来访问所有的服务&#xff0c;因为在很多情况下用户只能通过 80 或者 443 端口访问外界服务。 这个时候我们就可以使用反向代理来实现…

云上“两地三中心”,中小企业都用得起的多保险灾备方案

在云时代&#xff0c;大部分中小型企业都奔跑在云上或是服务器托管公司。任何规模的数据中心服务中断都会让你的企业踩雷。据统计&#xff0c;80%的数据中心服务中断都是由服务器硬件造成的。 据万博智云不完全统计&#xff1a; 2021年3月&#xff0c;一场大火完全摧毁了OVH在…

[附源码]计算机毕业设计SpringBoot蛋糕购物商城

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

如何将pdf转word?这几个软件可以做到文档格式转换

我们在日常办公中使用较为频繁的就是pdf和word两种文件格式&#xff0c;pdf的兼容性较好&#xff0c;就算跨设备传输也不会出现乱码的情况&#xff1b;word文档可以直接进行编辑修改&#xff0c;各有各的好处。如果我们想对pdf的内容进行修改的话&#xff0c;就需要把pdf文件转…

优维低代码:Redirect 路由重定向If 条件渲染

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 连载…

Centos7扩容root分区

Background 安装centos7系统时&#xff0c;如果没有自定义分区&#xff0c;系统默认给root分配的空间只有50G&#xff0c;其他空间都分配给了你创建的普通用户/home目录。这里我们把home的空间匀出一部分给root。 1、首先要注意数据安全 备份home目录的数据 tar zcf /tmp/hom…

vue学习1~18

1. vue基础知识和原理 1.1 初识Vue 想让Vue工作&#xff0c;就必须创建一个Vue实例&#xff0c;且要传入一个配置对象demo容器里的代码依然符合html规范&#xff0c;只不过混入了一些特殊的Vue语法demo容器里的代码被称为【Vue模板】Vue实例和容器是一一对应的真实开发中只有…

城市三维地理信息可视化 技术解析

一、三维地理信息系统分析空间数据的科学工具 三维地理信息系统&#xff0c;即三维GIS&#xff0c;是对包括大气层在内的地球表层&#xff0c;与地理有关的数据进行采集、储存、管理、运算、分析、显示和描述的技术系统。 基于三维GIS将现实世界中三维对象的相关属性与空间位…

什么是CRM系统?CRM的价值体现在哪里?

图为简道云看板对企业来说&#xff0c;完整的工作流程可以概括为售前、售中和售后三个阶段。每一个阶段都需要不同的管理。而CRM客户关系管理系统&#xff0c;能够帮助企业在这三个阶段进行业务管理及客户管理&#xff0c;帮助企业更好地运营&#xff0c;提高企业的竞争力。 简…

软件设计与体系结构简答题汇总

假设系统中有三个类&#xff0c;分别为类 A 、类 B 和类 C 。在现有的设计中&#xff0c;让类 A 直接依赖类 B &#xff0c;如果要将类 A 改为依赖类 C &#xff0c;必须通过修改类 A 的代码来达成&#xff0c;请问这样的设计符合开闭原则吗&#xff08; 2 分&#xff09;&…

跟着官方帮助文档学ICEM网格划分(附视频教程)

作者 | 如鹰展翅上腾 导读&#xff1a;划分结构化网格是ICEM软件的一大特色&#xff0c;自学的话会比较耗时&#xff0c;如有人带的话&#xff0c;入门进阶都是比较快的&#xff0c;就像一层窗户纸一捅就破。软件是使我们研究的问题得以求解的工具&#xff0c;重点侧向于操作…