当前位置: 首页 > news >正文

驱动开发day8

编写LED灯的驱动,使用GPIO子系统,里面添加按键的中断处理

1.应用程序发送指令控制LED亮灭

2.按键1 按下,led1电位反转 按键2按下,led2电位反转 按键3 按下,led3电位反转

驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"
struct device_node *dev_key;
unsigned int irqno_key1;
unsigned int irqno_key2;
unsigned int irqno_key3;struct device_node *dev_led;
struct gpio_desc *gpiono_led1;
struct gpio_desc *gpiono_led2;
struct gpio_desc *gpiono_led3;int major;
struct class *cls;
struct device *dev;
// 中断处理函数
irqreturn_t myirq_handler_key1(int irq, void *dev)
{gpiod_set_value(gpiono_led1,!gpiod_get_value(gpiono_led1));return IRQ_HANDLED;
}
irqreturn_t myirq_handler_key2(int irq, void *dev)
{gpiod_set_value(gpiono_led2,!gpiod_get_value(gpiono_led2));return IRQ_HANDLED;
}
irqreturn_t myirq_handler_key3(int irq, void *dev)
{gpiod_set_value(gpiono_led3,!gpiod_get_value(gpiono_led3));return IRQ_HANDLED;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_ON:switch (arg){case 1:                           // LED1gpiod_set_value(gpiono_led1,1);; // LED1开灯break;case 2:                           // LED2gpiod_set_value(gpiono_led2,1); // LED2开灯break;case 3:                          // LED3gpiod_set_value(gpiono_led3,1); // LED3开灯break;}break;case LED_OFF:switch (arg){case 1:gpiod_set_value(gpiono_led1,0);break;case 2:gpiod_set_value(gpiono_led2,0);break;case 3:gpiod_set_value(gpiono_led3,0);break;}break;}return 0;
}
struct file_operations fops = {.unlocked_ioctl = mycdev_ioctl,};
static int __init mycdev_init(void)
{int i;// 字符设备驱动注册major = register_chrdev(0, "mychrdev", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "myled");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备节点信息for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}}printk("向上提交设备节点成功\n");int ret;// 解析按键的设备树节点dev_key = of_find_node_by_path("/myirq");if (dev_key == NULL){printk("解析设备树节点失败\n");return -EFAULT;}printk("解析设备树节点成功\n");// 根据设备树节点解析出软中断号irqno_key1 = irq_of_parse_and_map(dev_key, 0); // 按键1索引号为0if (!irqno_key1){printk("解析软中断号失败\n");return -ENXIO;}printk("key1解析软中断号成功 irqno=%d\n", irqno_key1);irqno_key2 = irq_of_parse_and_map(dev_key, 1); // 按键1索引号为0if (!irqno_key2){printk("解析软中断号失败\n");return -ENXIO;}printk("key2解析软中断号成功 irqno=%d\n", irqno_key2);irqno_key3 = irq_of_parse_and_map(dev_key, 2); // 按键1索引号为0if (!irqno_key3){printk("解析软中断号失败\n");return -ENXIO;}printk("key3解析软中断号成功 irqno=%d\n", irqno_key3);// 注册中断ret = request_irq(irqno_key1, myirq_handler_key1, IRQF_TRIGGER_FALLING, "key1", NULL);if (ret){printk("注册中断失败\n");return ret;}printk("key1注册中断成功\n");ret = request_irq(irqno_key2, myirq_handler_key2, IRQF_TRIGGER_FALLING, "key2", NULL);if (ret){printk("注册中断失败\n");return ret;}printk("key2注册中断成功\n");ret = request_irq(irqno_key3, myirq_handler_key3, IRQF_TRIGGER_FALLING, "key3", NULL);if (ret){printk("注册中断失败\n");return ret;}printk("key3注册中断成功\n");// 根据设备树节点的路径解析设备树信息dev_led = of_find_node_by_path("/leds");if (dev_led == NULL){printk("解析设备树节点失败\n");return -EFAULT;}printk("解析设备树节点成功\n");// 申请gpio_desc对象并设置输出为低电平gpiono_led1 = gpiod_get_from_of_node(dev_led, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono_led1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono_led1);}printk("申请gpio_led1对象成功\n");gpiono_led2 = gpiod_get_from_of_node(dev_led, "led2-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono_led2)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono_led2);}printk("申请gpio_led1对象成功\n");gpiono_led3 = gpiod_get_from_of_node(dev_led, "led3-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono_led3)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono_led3);}printk("申请gpio_led1对象成功\n");return 0;
}
static void __exit mycdev_exit(void)
{// 注销中断free_irq(irqno_key1, NULL);free_irq(irqno_key2, NULL);free_irq(irqno_key3, NULL);// 灭灯gpiod_set_value(gpiono_led1, 0);// 释放gpio编号gpiod_put(gpiono_led1);// 灭灯gpiod_set_value(gpiono_led2, 0);// 释放gpio编号gpiod_put(gpiono_led2);// 灭灯gpiod_set_value(gpiono_led3, 0);// 释放gpio编号gpiod_put(gpiono_led3);int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录信息class_destroy(cls);// 注销字符设备驱动unregister_chrdev(major, "mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用程序

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"int main(int argc, char const *argv[])
{int a, b;char buf[128] = {0};int fd0 = open("/dev/mycdev0", O_RDWR);if (fd0 < 0){printf("打开设备文件失败\n");exit(-1);}int fd1 = open("/dev/mycdev1", O_RDWR);if (fd1 < 0){printf("打开设备文件失败\n");exit(-1);}int fd2 = open("/dev/mycdev2", O_RDWR);if (fd2 < 0){printf("打开设备文件失败\n");exit(-1);}while (1){// 从终端读取printf("请输入指令\n");printf("0(关灯) 1(开灯)\n");printf("请输入>");scanf("%d", &a);printf("请输入要控制的灯 1(LED1) 2(LED2) 3(LED3)>");scanf("%d", &b);switch (b){case 1:switch (a){case 1:ioctl(fd0, LED_ON); // 开灯break;case 0:ioctl(fd0, LED_OFF);break;}break;case 2:switch (a){case 1:ioctl(fd1, LED_ON); // 开灯break;case 0:ioctl(fd1, LED_OFF);break;}break;case 3:switch (a){case 1:ioctl(fd2, LED_ON); // 开灯break;case 0:ioctl(fd2, LED_OFF);break;}break;}}close(fd0);close(fd1);close(fd2);return 0;
}

相关文章:

驱动开发day8

编写LED灯的驱动&#xff0c;使用GPIO子系统&#xff0c;里面添加按键的中断处理 1.应用程序发送指令控制LED亮灭 2.按键1 按下&#xff0c;led1电位反转 按键2按下&#xff0c;led2电位反转 按键3 按下&#xff0c;led3电位反转 驱动程序 #include <linux/init.h> #i…...

CAS 机制

问题分析与思考&#xff1a; CAS 是 Java 中 Unsafe 类里面的方法&#xff0c;它的全称是 CompareAndSwap&#xff0c;比较并交换 的意思。 它的主要功能是能够保证在多线程环境下&#xff0c;对于共享变量的修改的原子性。 举个例子&#xff0c;比如说有这样一个场景&#xff…...

#P1003. [NOIP2009普及组] 道路游戏

题目描述 小新正在玩一个简单的电脑游戏。 游戏中有一条环形马路&#xff0c;马路上有 nn 个机器人工厂&#xff0c;两个相邻机器人工厂之间由一小段马路连接。小新以某个机器人工厂为起点&#xff0c;按顺时针顺序依次将这 nn 个机器人工厂编号为 1\sim n1∼n&#xff0c;因…...

python-网络爬虫.regular

regular 正则表达式 (regular expression) 正则表达式(regular expression)描述了一种字符串匹配的模式 &#xff08;pattern&#xff09;&#xff0c; 可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串 中取出符合某个条件的子串等。 正则表达式是由普通…...

手动搭建gateway,项目集成gateway实现Token效果

目录 背景步骤1、首先创建springboot项目2、引入依赖3、配置文件&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;超级重要&#xff01;&#xff01;&#xff01;根据自己的需要进行配置&#xff09;4、相关类我们在服务中进行的白名单中接口的操作如…...

linux下SVN服务器搭建

在本教程中&#xff0c;我们将介绍如何在Linux系统下搭建Subversion&#xff08;SVN&#xff09;服务器。Subversion是一种流行的版本控制系统&#xff0c;它允许多个人在同一项目上进行协作&#xff0c;同时避免了他们各自的更改发生冲突。 安装SVN 在大多数Linux发行版中&am…...

技术等级 TRL 定义

“不同环境、不同目标下TRL表述不一样” 技术等级 TRL 定义 TRL1 基本原理提出和发现 TRL2 技术应用研究 TRL3 完成概念验证&#xff0c;如叶栅试验、燃烧室头部试验等 TRL4 完成模拟部件试验&#xff0e;如压气机性能试验&#xff0c;燃烧室扇形试验 TRL5 完…...

DHorse v1.3.0 发布,基于k8s的发布平台

综述 DHorse是一个简单易用、以应用为中心的云原生DevOps系统&#xff0c;具有持续集成、持续部署、微服务治理等功能&#xff0c;无需安装依赖Docker、Maven、Node等环境即可发布Java、Vue、React应用&#xff0c;主要特点&#xff1a;部署简单、操作简洁、功能快速。 新增特…...

Redis - 缓存的双写一致性

概念&#xff1a; 当修改了数据库的数据也要同时更新缓存的数据&#xff0c;缓存和数据库的数据要保持一致 那为什么会有不一致的情况呢&#xff1f; 如果不追求一致性&#xff0c;正常有两种做法 先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库 我们以先删除旧的…...

opencv03-Mat矩阵API的使用

opencv03-Mat矩阵API的使用 构造方法(具体介绍看API文档) int main() {Mat m1 Mat(200, 100, CV_8UC1);imshow("o1", m1);Mat m2 Mat(Size(100, 200), CV_8UC1);imshow("o2", m2);Mat m3 Mat(200, 100, CV_8UC3, Scalar(255, 0, 0));imshow("o3&…...

2023届浙江大学MPA提面A资格经验总结分享

本人是去年报考的浙大MPA项目&#xff0c;并通过提面获得了A资格&#xff0c;新一年浙大MPA项目提前批面试已经开始了&#xff0c;受达立易考周老师邀请来分享下我的提面经验&#xff0c;希望我的经验能对还在迷茫中的小伙伴有所帮助。 点开提面通知&#xff0c;首先看到…...

BugKu CTF(杂项篇MISC)—想要种子吗

BugKu CTF(杂项篇MISC)—想要种子吗 提 示: 描 述:flag{} 题目下载后是一张图片&#xff0c;打开如下。 一、工具 十六进制编辑器010 editor kali系统文件分离工具binwalk或者foremost 维吉尼亚密码 STEGHIDE图片隐写工具 文章所需的软件下载地址 ARCHPR压缩包密码破解…...

类之间的关系

1、类关系 继承、实现、依赖、组合、聚合 继承&#xff1a;一个类继承另一个类&#xff1b; 实现&#xff1a;一个类实现另一个接口&#xff1b; 依赖&#xff1a;一个类作为另一个的局部变量&#xff0c;方法的参数&#xff0c;临时对象等&#xff1b; 组合&#xff1a;一个类…...

【蓝图】p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统

p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统 p40对象引用、变量有效性p41实现键盘控制物体自转创建bool值控制旋转实现通过键盘控制自转 p42p43简单点名系统Get All Actors Of Class&#xff08;获得场景中所有该类的actor演员&#xff09;getFor Each L…...

vscode设置远程登录和免密登录

首先&#xff0c;我们去官网下载VScode 安装过程比较简单&#xff0c;大家自行安装即可&#xff0c;注意建议安装在除C盘外的其他盘中。 安装完成后&#xff0c;打开我们下载好的VScode&#xff0c;点击左侧的Extensions选项&#xff0c;搜索Remote&#xff0c;Install第一项R…...

今日头条面试真题及答案,软件测试工程师面试秘籍

试题1&#xff0e;在浏览器地址栏里输入一个网址&#xff0c;接下来会发生什么&#xff1f; 答案&#xff1a;发生的操作如下。 &#xff08;1&#xff09;浏览器查找该网址的IP地址。 &#xff08;2&#xff09;浏览器根据解析得到的IP地址向Web服务器发送一个HTTP请求。 &am…...

JavaScript Windows 浏览器对象模型

Window 对象 BOM 的核心就是 window 对象所有浏览器都支持 window 对象。它表示浏览器窗口。所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。全局变量是 window 对象的属性。全局函数是 window 对象的方法。HTML DOM 的 document 也是 window 对象的属…...

【uniapp 获取缓存及清除缓存】

小程序及H5 获取缓存&#xff1a; 使用uniapp中的wx.getStorageInfoSync()方法可以获取当前小程序或H5应用的本地缓存信息&#xff0c;如下所示&#xff1a; let storageInfo uni.getStorageInfoSync() console.log(storageInfo)其中&#xff0c;storageInfo是一个对象&…...

【vim 学习系列文章 2 - vim 常用插件配置】

文章目录 1.1 vim 常用插件1.1.1 vim 插件 Pathogen 管理1.1.2 vim 常用插件推荐1.1.3 vim Leaderf1.1.4 vim ripgrep 工具1.1.5 vim Leaderf 配合 rg1.1.6 vim autocmd 配置 1.2 其它类型文件 vimrc 配置1.2.1 System Verilog vimrc 配置 上篇文章&#xff1a;vim 学习系列文章…...

【外卖系统】修改菜品

需求分析 在菜品管理列表页面点击修改按钮&#xff0c;跳转到修改页面&#xff0c;在修改页面回显菜品相关信息并进行修改&#xff0c;在最后点击确定按钮完成修改操作 代码设计 页面发送ajax请求&#xff0c;请求服务端获取分类数据&#xff0c;用于菜品分类下拉框中数据显…...

C++ 性能评测工程:基于 Google Benchmark 的 C++ 函数级性能基准测试方法论

各位技术同仁&#xff0c;下午好&#xff01;今天&#xff0c;我们将深入探讨一个在C开发中至关重要的话题&#xff1a;C 函数级性能基准测试。尤其是在追求极致性能的C世界里&#xff0c;仅仅依靠经验和直觉来优化代码是远远不够的。我们需要一套科学、严谨的方法论来量化和评…...

【WEB模型】CS架构BS架构HTMLCSSJS

一、CS架构 - Client/Server 客户端/服务器pc安装软件&#xff1a;安卓应用、ios应用需要安装专门软件才能用&#xff0c;软件直接跟服务器通信开发成本高&#xff0c;各个平台都有对应的开发工程师好处&#xff1a;功能强大二、BS架构 - Browser/Server 浏览器/服务器不需要安…...

OpenClaw未来展望:Qwen3-14B与本地自动化的5个进化方向

OpenClaw未来展望&#xff1a;Qwen3-14B与本地自动化的5个进化方向 1. 从工具到伙伴&#xff1a;OpenClaw的现状与定位 去年冬天&#xff0c;当我第一次在本地MacBook上部署OpenClaw时&#xff0c;它还是个需要手动配置JSON文件才能调用本地模型的"半成品"。如今看…...

别等宕机才后悔!UPS蓄电池定期巡检,这4点才是核心!

&#xff5c;机房里设备林立&#xff0c;大多数人把目光聚焦在服务器、精密空调上。但其实&#xff0c;潜伏在机房角落的“隐形杀手”&#xff0c;往往是看起来默默无闻的UPS蓄电池。今天我们不谈复杂的技术参数&#xff0c;只用大白话讲清楚&#xff1a;为什么蓄电池必须定期巡…...

3分钟搞定Windows软件安装难题:winget-install终极解决方案

3分钟搞定Windows软件安装难题&#xff1a;winget-install终极解决方案 【免费下载链接】winget-install Install WinGet using PowerShell! Prerequisites automatically installed. Works on Windows 10/11 and Server 2019/2022. 项目地址: https://gitcode.com/gh_mirror…...

StreamlabsArduinoAlerts:嵌入式设备接入Twitch直播事件

1. StreamlabsArduinoAlerts 库深度解析&#xff1a;嵌入式设备接入 Twitch 直播事件的完整实现方案 StreamlabsArduinoAlerts 是一个专为资源受限嵌入式平台设计的轻量级 C 库&#xff0c;其核心目标是让 Arduino、ESP8266、ESP32、Particle 及基于 ATmega/STM32 的 MCU 能够直…...

实时信号处理中的滤波器选型实战指南:从需求分析到性能优化

实时信号处理中的滤波器选型实战指南&#xff1a;从需求分析到性能优化 【免费下载链接】gnuradio GNU Radio – the Free and Open Software Radio Ecosystem 项目地址: https://gitcode.com/gh_mirrors/gn/gnuradio 一、需求分析&#xff1a;明确滤波器设计目标 在开…...

终极指南:如何用res-downloader一键下载全网无水印资源

终极指南&#xff1a;如何用res-downloader一键下载全网无水印资源 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 你是否经常…...

终极指南:如何用ImageToSTL将任何图片变成3D打印模型

终极指南&#xff1a;如何用ImageToSTL将任何图片变成3D打印模型 【免费下载链接】ImageToSTL This tool allows you to easily convert any image into a 3D print-ready STL model. The surface of the model will display the image when illuminated from the left side. …...

掌握5个核心配置技巧:OpenCore-Configurator从入门到专家

掌握5个核心配置技巧&#xff1a;OpenCore-Configurator从入门到专家 【免费下载链接】OpenCore-Configurator A configurator for the OpenCore Bootloader 项目地址: https://gitcode.com/gh_mirrors/op/OpenCore-Configurator OpenCore-Configurator&#xff08;简称…...