驱动开发(中断)
头文件:
#ifndef __LED_H__
#define __LED_H__#define PHY_LED1_MODER 0X50006000
#define PHY_LED1_ODR 0X50006014
#define PHY_LED1_RCC 0X50000A28#define PHY_LED2_MODER 0X50007000
#define PHY_LED2_ODR 0X50007014
#define PHY_LED2_RCC 0X50000A28#define PHY_LED3_MODER 0X50006000
#define PHY_LED3_ODR 0X50006014
#define PHY_LED3_RCC 0X50000A28
//风扇
#define PHY_FAN_MODER 0X50006000
#define PHY_FAN_ODR 0X50006014
#define PHY_FAN_RCC 0X50000A28
//蜂鸣器
#define PHY_BUZZER_MODER 0X50003000
#define PHY_BUZZER_ODR 0X50003014
#define PHY_BUZZER_RCC 0X50000A28
//马达
#define PHY_MOTOR_MODER 0X50007000
#define PHY_MOTOR_ODR 0X50007014
#define PHY_MOTOR_RCC 0X50000A28
//功能码
#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)
#define FAN_ON _IO('f',1)
#define FAN_OFF _IO('f',0)
#define BUZZER_ON _IO('b',1)
#define BUZZER_OFF _IO('b',0)
#define MOTOR_ON _IO('m',1)
#define MOTOR_OFF _IO('m',0)
#endif
应用层程序:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"
int main(int argc, char const *argv[])
{char buf[128] = {0};int led1_fd, led2_fd, led3_fd;// 打开led设备文件led1_fd = open("/dev/mycdev0", O_RDWR);if (led1_fd < 0){printf("打开led1设备文件失败\n");exit(-1);}led2_fd = open("/dev/mycdev1", O_RDWR);if (led2_fd < 0){printf("打开led2设备文件失败\n");exit(-1);}led3_fd = open("/dev/mycdev2", O_RDWR);if (led3_fd < 0){printf("打开led3设备文件失败\n");exit(-1);}int a, b;while (1){printf("请选择要控制的器件: 1(led灯1) 2 (led灯2) 3 (led灯3) ");scanf("%d", &a);printf("请输入指令:0(关闭) 1 (打开)");scanf("%d", &b);switch (b){case 1:switch (a){case 1:ioctl(led1_fd, LED_ON, a);break;case 2:ioctl(led2_fd, LED_ON, a);break;case 3:ioctl(led3_fd, LED_ON, a);break;}break;case 0:switch (a){case 1:ioctl(led1_fd, LED_OFF, a);break;case 2:ioctl(led2_fd, LED_OFF, a);break;case 3:ioctl(led3_fd, LED_OFF, a);break;}break;}}close(led1_fd);close(led2_fd);close(led3_fd);return 0;
}
驱动程序:
#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 <linux/slab.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include "head.h"
struct cdev* mycdev;
struct class* cls;
struct device* dev_d;
unsigned int major = 500;
unsigned int minor = 0;
dev_t devno;
char kbuf[128] = {0};
wait_queue_head_t wq_head;
int condition = 0;
struct device_node *dev,*led_dev;
unsigned int irqno1,irqno2,irqno3;
struct gpio_desc* gpiono1,*gpiono2,*gpiono3;
// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{int a = inode->i_rdev;file->private_data = (void *)MINOR(a);printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mychrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ unsigned int a;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);a = (unsigned int)file->private_data;switch(a){case 0:if(cmd == LED_ON){gpiod_set_value(gpiono1,1);}else{gpiod_set_value(gpiono1,0);}break;case 1:if(cmd == LED_ON){gpiod_set_value(gpiono2,1);}else{gpiod_set_value(gpiono2,0);}break;case 2:if(cmd == LED_ON){gpiod_set_value(gpiono3,1);}else{gpiod_set_value(gpiono3,0);}break;}return 0;
}
irqreturn_t myirq_handler(int irq,void *dev)
{gpiod_set_value(gpiono1,!gpiod_get_value(gpiono1));return IRQ_HANDLED;
}
irqreturn_t myirq2_handler(int irq,void *dev)
{gpiod_set_value(gpiono2,!gpiod_get_value(gpiono2));return IRQ_HANDLED;
}
irqreturn_t myirq3_handler(int irq,void *dev)
{gpiod_set_value(gpiono3,!gpiod_get_value(gpiono3));return IRQ_HANDLED;
}
//对设备文件进行操作的结构体
struct file_operations fops = {.open = mycdev_open,//打开.unlocked_ioctl = mychrdev_ioctl,//硬件功能的选择.release = mycdev_close,//关闭
};
static int __init mycdev_init(void)
{int i;major = register_chrdev(0,"mycdev",&fops);if(major<0){printk("注册设备驱动失败\n");return major;}printk("注册设备驱动成功major=%d\n",major);//************自动申请设备节点*********************//1、向上提交目录cls = class_create(THIS_MODULE, "mycdev");if(IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");// 2、向上提交设备节点信息for (i = 0; i < 3; i++){dev_d = device_create(cls, NULL, MKDEV(major, i), NULL, "mycdev%d", i);if (IS_ERR(dev_d)){printk("提交led设备信息失败\n");return -PTR_ERR(dev_d);}}printk("提交设备信息成功\n");/***********************************///解析设备树的节点int ret;dev = of_find_node_by_name(NULL,"myirq");if(dev == NULL){printk("解析设备树节点失败\n");return -EIO;}printk("解析myirq设备树节点成功\n");led_dev = of_find_node_by_name(NULL,"leds");if(led_dev == NULL){printk("解析led设备树节点失败\n");return -EIO;}printk("解析led设备树节点成功\n");gpiono1 = gpiod_get_from_of_node(led_dev,"led1-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono1);}gpiono2 = gpiod_get_from_of_node(led_dev,"led2-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono2)){printk("申请gpio2对象失败\n");return -PTR_ERR(gpiono2);}gpiono3 = gpiod_get_from_of_node(led_dev,"led3-gpios",0,GPIOD_OUT_LOW,NULL);if(IS_ERR(gpiono3)){printk("申请gpio3对象失败\n");return -PTR_ERR(gpiono3);}//根据设备树节点解析出软中断号irqno1 = irq_of_parse_and_map(dev,0);if(!irqno1){printk("解析led1软中断号失败\n");return -ENXIO;}printk("解析软led1中断号成功irqno=%d\n",irqno1);irqno2 = irq_of_parse_and_map(dev,1);if(!irqno2){printk("解析led2软中断号失败\n");return -ENXIO;}printk("解析led2软中断号成功irqno=%d\n",irqno2);irqno3 = irq_of_parse_and_map(dev,2);if(!irqno3){printk("解析led3软中断号失败\n");return -ENXIO;}printk("解析led3软中断号成功irqno=%d\n",irqno3);//注册中断ret = request_irq(irqno1,myirq_handler,IRQF_TRIGGER_FALLING,"key1",NULL);if(ret){printk("key1软中断号注册失败\n");return ret;}printk("key1软中断号注册成功\n");ret = request_irq(irqno2,myirq2_handler,IRQF_TRIGGER_FALLING,"key2",NULL);if(ret){printk("key2软中断号注册失败\n");return ret;}printk("key2软中断号注册成功\n");ret = request_irq(irqno3,myirq3_handler,IRQF_TRIGGER_FALLING,"key3",NULL);if(ret){printk("key3软中断号注册失败\n");return ret;}printk("key3软中断号注册成功\n");return 0;
}
static void __exit mycdev_exit(void)
{int i;//灭灯gpiod_set_value(gpiono1,0);//释放gpio编号gpiod_put(gpiono1);//灭灯gpiod_set_value(gpiono2,0);//释放gpio编号gpiod_put(gpiono2);//灭灯gpiod_set_value(gpiono3,0);//释放gpio编号gpiod_put(gpiono3);//注销中断号free_irq(irqno1,NULL);free_irq(irqno2,NULL);free_irq(irqno3,NULL);//销毁节点信息for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}//销毁目录信息class_destroy(cls);//注销字符设备驱动unregister_chrdev(major,"mycdev");}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
相关文章:

驱动开发(中断)
头文件: #ifndef __LED_H__ #define __LED_H__#define PHY_LED1_MODER 0X50006000 #define PHY_LED1_ODR 0X50006014 #define PHY_LED1_RCC 0X50000A28#define PHY_LED2_MODER 0X50007000 #define PHY_LED2_ODR 0X50007014 #define PHY_LED2_RCC 0X50000A28#def…...
TypeScript最新语法总结
注意注意!!!本文介绍的是最新的TypeScript4的重要语法 第一部分:TypeScript的简介 TypeScript 是由微软开发的一款开源的编程语言,TypeScript 是 Javascript 的超集,遵循最新的 ES6、ES5 规范,…...

sentinel组件
目录 定义 4.加SentinelResource,blockHander是超过阈值之后执行的函数 5.设置阈值 6.springboot集成sentinel 定义 1.sentinel知道当前流量大小,在浏览器和后端之间加sentinel控制流量,避免大批量的瞬时请求都达到服务上,将服务压垮 2.…...

26 MFC序列化函数
文章目录 Serialize对于存储文件的序列化 Serialize Serialize 是一个在 MFC (Microsoft Foundation Classes) 中常用的函数或概念。它用于将对象的数据进行序列化和反序列化,便于在不同的场景中保存、传输和恢复对象的状态。 在 MFC 中,Serialize 函数…...

GC 深入(小白,对gc有一个进一步的了解)
垃圾回收器的搭配 一般固定 一般这年轻代垃圾回收器,老年代垃圾回收器,如上图搭配着使用 1.8呢默认就是最后边那哥俩 jvm调优 一个就是增加吞吐量 一个就是减少STW的时间。 三色标记算法(理解根可达算法) 并发的可达性分析 有…...
CSS前端面试
文章目录 rem、em、vh、px各自代表的含义?盒模型poison 定位属性flex属性让元素水平垂直居中页面适配的方法有哪些 rem、em、vh、px各自代表的含义? px:绝对单位,页面按精确像素展示 em:相对单位,基准点为…...
VB+SQL餐饮管理系统设计与实现
第一章 前言 1.1 绪论 当今世界已进入了在计算机信息管理领域中激烈竞争的时代,应用计算机已经变得十分普遍了,如同我们离不开的自行车、汽车一样。我们应该承认,谁掌握的知识多,信息量大,信息处理速度快,批量大,谁的效率就高,谁就能够在各种竞争中立于不败之地。随着…...

React入门学习笔记2
jsx语法规则 定义虚拟DOM时,不要写引号。标签中混入JS表达式时要用{ }。样式的类名指定不要用class,要用className。内联样式,要用style{{key:value}}的形式去写。只有一个根标签标签必须闭合标签首字母 )若小写字母开头…...

Palo Alto Networks® PA-220R 下一代防火墙 确保恶劣工况下的网络安全
一、主要安全功能 1、每时每刻在各端口对全部应用进行分类 • 将 App-ID 用于工业协议和应用,例如 Modbus、 DNP3、IEC 60870-5-104、Siemens S7、OSIsoft PI 等。 • 不论采用何种端口、SSL/SSH 加密或者其他规避技术,都会识别应用。 • 使用…...

架构训练营学习笔记:5-2 负载均衡架构
多级负载架构 设计关键点 性能需求、维护复杂度之间做取舍。 一可以去掉F5、LVS : F5 是成本较高,LVS 是复杂,对于性能没那么高需求,可以去掉。 二 去掉ng: 服务网关服务 适应于初创公司快速验证,内部的 小系统…...

二叉树的性质、前中后序遍历【详细】
1. 树概念2.二叉树的概念1.2二叉树的性质 3.二叉树遍历3.2前序遍历3.2 中序遍历3.3 后序遍历 1. 树概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合,有二叉树,N叉树等等。 子树…...

涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果: 这个确实有点意思,但是这是 CSS 能够完成的? 没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现࿰…...

单片机中断系统
单片机中断系统 中断的概念: CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);待CPU将事…...

二、JVM-深入运行时数据区
深入运行时数据区 计算机体系结构 JVM的设计实际上遵循了遵循冯诺依曼计算机结构 CPU与内存交互图: 硬件一致性协议: MSI、MESI、MOSI、Synapse、Firely、DragonProtocol 摩尔定律 摩尔定律是由英特尔(Intel)创始人之一戈登摩尔(Gordon Moore)提出来…...
随机验证码vue实现,登录验证码随机验证码数字和字母类型的
1、组件 <!--loginCode登录验证码组件--> <template> <canvas id"canvasCode" :width"contentWidth" :height"contentHeight" /> </template> <script> export default { name: LoginCode, props: { identif…...

xlrd与xlwt操作Excel文件详解
Python操作Excel的模块有很多,并且各有优劣,不同模块支持的操作和文件类型也有不同。下面是各个模块的支持情况: .xls.xlsx获取文件内容写入数据修改文件内容保存样式调整插入图片xlrd√√√xlwt√√√√√xlutils√√√√xlwings√√√√√…...

A Survey of Embodied AI: From Simulators to Research Tasks 论文阅读
论文信息: 题目:A Survey of Embodied AI: From Simulators to Research Tasks 作者:Jiafei Duan, Samson Yu 来源:arXiv 时间:2022 Abstract 通过评估当前的九个具体人工智能模拟器与我们提出的七个功能࿰…...

spark-sql数据重复之File Output Committer问题
前言 我们先来回顾下之前介绍过的三种Committer:FileOutputCommitter V1、FileOutputCommitter V2、S3A Committer,其基本代表了整体的演进趋势。 核心代码讲解详细参照:Spark CommitCoordinator 保证数据一致性 OutputCommitter commitTask…...

面试热题(前中序遍历构建树)
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 题目中是给定两个数组,一个是存放这颗树的前序遍历的数组,一个是存放这棵树的…...
美术:贴图
游戏模型制作流程,SP和BP根据情况来选择软件对UV进行处理 3Dmax 制作模型和动画(橘肉)RizomUV 对模型进行展UV(橘皮)Substance Painter 纹理手绘(给橘皮制定想要的皮肤)BodyPaint 3D 纹理手绘&a…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...