arm学习之stm32设备树学习-中断控制led灯亮灭+字符设备指令控制led灯亮灭
中断控制led灯亮灭
驱动文件源码
led-key.c
#include<linux/init.h>
#include<linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
#include<linux/of_irq.h>
#include<linux/interrupt.h>
struct device_node *led_dev;
struct device_node *key_dev;
struct gpio_desc *gpiono_led_1;
struct gpio_desc *gpiono_led_2;
struct gpio_desc *gpiono_led_3;
unsigned int irqno_1;
unsigned int irqno_2;
unsigned int irqno_3;
irqreturn_t myirq_handler(int irq, void *dev){printk("irq=%d\n",irq);switch (irq){case 71:gpiod_set_value(gpiono_led_1,!gpiod_get_value(gpiono_led_1));break;case 72:gpiod_set_value(gpiono_led_2,!gpiod_get_value(gpiono_led_2));break;case 73:gpiod_set_value(gpiono_led_3,!gpiod_get_value(gpiono_led_3));break;} return IRQ_HANDLED;
}
static int __init mycdev_init(void){ int ret;led_dev = of_find_node_by_path("/leds");if(led_dev == NULL){printk("解析led灯设备树节点失败\n");return -EFAULT;}printk("解析led灯设备树成功\n");key_dev = of_find_node_by_path("/myirq");if(key_dev == NULL){printk("解析中断设备树节点失败\n");return -EFAULT;}printk("解析中断设备树成功\n");gpiono_led_1 = gpiod_get_from_of_node(led_dev,"led1-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_1)){printk("获取GPIO号失败\n");return -PTR_ERR(gpiono_led_1);}gpiono_led_2 = gpiod_get_from_of_node(led_dev,"led2-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_2)){printk("获取GPIO号失败\n");return -PTR_ERR(gpiono_led_2);}gpiono_led_3 = gpiod_get_from_of_node(led_dev,"led3-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_3)){printk("获取GPIO号失败\n");return -PTR_ERR(gpiono_led_3);}printk("申请GPIO编号成功\n");irqno_1 = irq_of_parse_and_map(key_dev,0);if(!irqno_1){printk("解析中断号失败\n");return -ENXIO;}printk("解析软中断号成功 irqno=%d\n",irqno_1);irqno_2 = irq_of_parse_and_map(key_dev,1);if(!irqno_2){printk("解析中断号失败\n");return -ENXIO;}printk("解析软中断号成功 irqno=%d\n",irqno_2);irqno_3 = irq_of_parse_and_map(key_dev,2);if(!irqno_3){printk("解析中断号失败\n");return -ENXIO;}printk("解析软中断号成功 irqno=%d\n",irqno_3);//注册中断ret = request_irq(irqno_1,myirq_handler,IRQF_TRIGGER_FALLING,"key1",NULL);if(ret){printk("注册中断1失败\n");return ret;}//注册中断ret = request_irq(irqno_2,myirq_handler,IRQF_TRIGGER_FALLING,"key2",NULL);if(ret){printk("注册中断2失败\n");return ret;}//注册中断ret = request_irq(irqno_3,myirq_handler,IRQF_TRIGGER_FALLING,"key3",NULL);if(ret){printk("注册中断3失败\n");return ret;}printk("注册中断成功\n");return 0;
}
static void __exit mycdev_exit(void){free_irq(irqno_1,NULL);free_irq(irqno_2,NULL);free_irq(irqno_3,NULL);gpiod_set_value(gpiono_led_1,0);gpiod_put(gpiono_led_1);gpiod_set_value(gpiono_led_2,0);gpiod_put(gpiono_led_2);gpiod_set_value(gpiono_led_3,0);gpiod_put(gpiono_led_3);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
字符设备指令控制led灯亮灭
驱动文件
led-cmd.c
#include<linux/init.h>
#include<linux/module.h>
#include<linux/io.h>
#include<linux/fs.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
struct device_node *led_dev;
struct gpio_desc *gpiono_led_1;
struct gpio_desc *gpiono_led_2;
struct gpio_desc *gpiono_led_3;
struct class *cls;
struct device *dev;
char kbuf[128]={0};
unsigned int major;//定义一个变量保存主设备号
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);long ret;ret=copy_from_user(kbuf,ubuf,size);switch (kbuf[0]){case '1':gpiod_set_value(gpiono_led_1,!gpiod_get_value(gpiono_led_1));break;case '2':gpiod_set_value(gpiono_led_2,!gpiod_get_value(gpiono_led_2));break;case '3':gpiod_set_value(gpiono_led_3,!gpiod_get_value(gpiono_led_3));break;} return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
void all_led_init(void){int ret;led_dev = of_find_node_by_path("/leds");if(led_dev == NULL){printk("解析led灯设备树节点失败\n");//return -EFAULT;}gpiono_led_1 = gpiod_get_from_of_node(led_dev,"led1-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_1)){printk("获取GPIO号失败\n");//return -PTR_ERR(gpiono_led_1);}gpiono_led_2 = gpiod_get_from_of_node(led_dev,"led2-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_2)){printk("获取GPIO号失败\n");//return -PTR_ERR(gpiono_led_2);}gpiono_led_3 = gpiod_get_from_of_node(led_dev,"led3-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono_led_3)){printk("获取GPIO号失败\n");// return -PTR_ERR(gpiono_led_3);}printk("申请GPIO编号成功\n");
}
//定义一个操作方法结构体变量并且初始化
struct file_operations fops={.open=mycdev_open,.release=mycdev_close,.read=mycdev_read,.write=mycdev_write,
};
static int __init mycdev_init(void){ //注册字符设备驱动major=register_chrdev(0,"mychrdev",&fops);if(major<0){printk("注册字符设备驱动失败\n");return major;}printk("注册字符设备驱动成功major=%d\n",major);// 向上提交目录cls = class_create(THIS_MODULE, "mycdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备节点信息dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev");if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}printk("向上提交设备节点成功\n");all_led_init();return 0;
}
static void __exit mycdev_exit(void){gpiod_set_value(gpiono_led_1,0);gpiod_put(gpiono_led_1);gpiod_set_value(gpiono_led_2,0);gpiod_put(gpiono_led_2);gpiod_set_value(gpiono_led_3,0);gpiod_put(gpiono_led_3);//注销字符设备驱动//销毁节点信息device_destroy(cls,MKDEV(major,0));//销毁目录信息class_destroy(cls);unregister_chrdev(major,"mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
应用文件
led.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{char buf[128] = {0};int fd = open("/dev/mycdev", O_RDWR);if (fd < 0){printf("打开设备文件失败\n");exit(-1);}while (1){printf("请输入控制命令:1(led1关灯/开灯)2(led2关灯/开灯)3(led3关灯/开灯)>");fgets(buf, sizeof(buf), stdin); // 从终端输入数据到bufbuf[strlen(buf) - 1] = '\0'; // 将buf末尾的'\n'切换为'\0'write(fd, buf, sizeof(buf)); }close(fd);return 0;
}相关文章:
arm学习之stm32设备树学习-中断控制led灯亮灭+字符设备指令控制led灯亮灭
中断控制led灯亮灭 驱动文件源码 led-key.c #include<linux/init.h> #include<linux/module.h> #include<linux/of.h> #include<linux/of_gpio.h> #include<linux/gpio.h> #include<linux/of_irq.h> #include<linux/interrupt.h> s…...
快速开发框架若依的基础使用详解
Hi I’m Shendi 快速开发框架若依的基础使用详解 最近在为公司制作新的项目,经过了一段时间的技术沉淀,我开始尝试接触市面上用的比较多的快速开发框架,听的最多的当属若依吧 于是就选用了若依 介绍 为什么选?目的是为了提高开发…...
RabbitMQ 教程 | 第4章 RabbitMQ 进阶
👨🏻💻 热爱摄影的程序员 👨🏻🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…...
小程序如何从分类中移除商品
有时候商家可能需要在商品分类中删除某些商品,无论是因为商品已下架、库存不足还是其他原因。在这篇文章中,我们将介绍如何从分类中移除商品。 方式一:分类管理中删除商品。 进入小程序管理后台,找到分类管理,在分…...
P1219 [USACO1.5] 八皇后 Checker Challenge
题目 思路 非常经典的dfs题,需要一点点的剪枝 剪枝①:行、列,对角线的标记 剪枝②:记录每个皇后位置 代码 #include<bits/stdc.h> using namespace std; const int maxn105; int a[maxn];int n,ans; bool vis1[maxn],vis…...
如何在不使用脚本和插件的情况下手动删除 3Ds Max 中的病毒?
如何加快3D项目的渲染速度? 3D项目渲染慢、渲染卡顿、渲染崩溃,本地硬件配置不够,想要加速渲染,在不增加额外的硬件成本投入的情况下,最好的解决方式是使用渲云云渲染,在云端批量渲染,批量出结…...
SpringCloud Gateway 在微服务架构下的最佳实践
作者:徐靖峰(岛风) 前言 本文整理自云原生技术实践营广州站 Meetup 的分享,其中的经验来自于我们团队开发的阿里云 CSB 2.0 这款产品,其基于开源 SpringCloud Gateway 开发,在完全兼容开源用法的前提下&a…...
Android studio修改app图标
步骤如下: 1.右键app名称→New→ImageAsset 2. 进行下面的配置 图源:https://blog.csdn.net/Qingshan_z/article/details/126661650 3.配置分辨率 4.图标自动保存在mipmap文件夹下 再启动就更换成功了!!! 参考&…...
<C++> 三、内存管理
1.C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";const char *pChar3 "abcd";int *ptr1…...
大模型开发(十五):从0到1构建一个高度自动化的AI项目开发流程(上)
全文共5600余字,预计阅读时间约13~20分钟 | 满满干货(附全部代码),建议收藏! 本文目标:提出一种利用大语言模型(LLMs)加快项目的开发效率的解决思路,本文作为第一部分,主要集中在如何完整的执行引导Chat模…...
HarmonyOS 开发基础(二)组件拼凑简单登录页面
一、简单登录页面 Entry Component /* 组件可以基于struct实现,组件不能有继承关系,struct可以比class更加快速的创建和销毁。*/ struct Index {State message: string Hello Worldbuild() {// https://developer.harmonyos.com/cn/docs/documentation/…...
flutter minio
背景 前端 经常需要上传文件 图片 视频等等 到后端服务器, 如果到自己服务器 一般会有安全隐患。也不方便管理这些文件。如果要想使用一些骚操作 比如 按照前端请求生成不同分辨率的图片,那就有点不太方便了。 这里介绍以下 minio,࿰…...
ChatGPT:人工智能交互的新时代
ChatGPT的背景和发展: ChatGPT是OpenAI公司在GPT-3基础上的进一步升级。GPT(Generative Pre-trained Transformer)是一种基于Transformer架构的深度学习模型,它能够处理自然语言,实现自动对话、写作等任务。而ChatGPT在…...
C. Binary String Copying - 思维
分析: 赛时我是直接模拟的,tle然后mle,补提,发现规律,每一个改变的字符串都只会对应一个需要改变的区间,例如第一个样例前两个101100 -> 011100和101100 -> 011100,对应区间在确定改变的范…...
哈工大计算机网络课程网络安全基本原理详解之:密钥分发中心与公钥认证中心
哈工大计算机网络课程网络安全基本原理详解之:密钥分发中心与公钥认证中心 在介绍密钥分发中心的概念前,先来回顾一下之前介绍的身份认证协议AP4.0:利用随机数R来避免“回放攻击”,并借助于对称加密算法来保证R的加密传输和解密&…...
md5sum
概念作用及原理 md5sum是一种常用的哈希算法,用于计算数据的MD5哈希值。MD5(Message Digest Algorithm 5)是一种广泛使用的加密散列函数,用于将任意长度的数据映射为固定长度的哈希值(通常是128位)。这个哈…...
图文档数字化:实现高效管理的几大步骤
在当今数字化时代,企业越来越意识到数字化管理对于图文档的重要性。传统的纸质文件管理往往效率低下,容易出现丢失和混乱的情况。为了提高工作效率、降低成本并确保数据安全,许多企业选择采用PDM(产品数据管理)系统来实…...
服务器磁盘占用过高分析
使用命令 du -sh查看出占用较大的目录,如下: 目录大小处理办法/usr/local/mysql/data16G转移部分文件/usr/local/nacos2.1G维持现状/logs4.4G删除部分文件/var1.9G删除部分文件 du -sh命令使用示例: du -sh /* 查看根目录各文件(夹)占用大小…...
【C语言】通讯录3.0 (文件存储版)
前言 通讯录是一种记录联系人信息的工具,包括姓名、电话号码、电子邮件地址、住址等。 文章的一二三章均于上一篇相同,可以直接看第四章改造内容。 此通讯录是基于通讯录2.0(动态增长版)的基础上进行增加文件操作功能,…...
【C#常用操作】
excel相关操作 using Excel Microsoft.Office.Interop.Excel;public Excel.Application app; public Excel.Workbooks wbs; public Excel.Workbook wb; public Excel.Worksheets wss; public Excel.Worksheet ws;/// <summary> /// 取得打开excel句柄 /// </summary…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
