2023.08.01 驱动开发day8

驱动层

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>#define LED_ON  _IO('l', 1)
#define LED_OFF _IO('l', 0)struct class *cls;
struct device *dev;
struct device_node *dev_irq, *dev_led;
unsigned int major;
unsigned int irqno1, irqno2, irqno3;
struct gpio_desc *gpiono1, *gpiono2, *gpiono3;//中断处理函数
irqreturn_t myirq_handler(int irq, void *dev)
{if(irq == irqno1) {gpiod_set_value(gpiono1, !gpiod_get_value(gpiono1));}else if(irq == irqno2) {gpiod_set_value(gpiono2, !gpiod_get_value(gpiono2));}else if(irq == irqno3) {gpiod_set_value(gpiono3, !gpiod_get_value(gpiono3));}return IRQ_HANDLED;
}int mycdev_open(struct inode *inode, struct file *file)
{int a = inode->i_rdev;  //获取当前设备文件对应的设备号file->private_data = (void *)MINOR(a);  //将次设备号保存到当前文件的file结构中return 0;
}long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{unsigned int a = (unsigned int)file->private_data;switch(a){case 0:switch(cmd){case LED_ON:gpiod_set_value(gpiono1, 1);break;case LED_OFF:gpiod_set_value(gpiono1, 0);break;}break;   case 1:switch(cmd){case LED_ON:gpiod_set_value(gpiono2, 1);break;case LED_OFF:gpiod_set_value(gpiono2, 0);break;}break; case 2:switch(cmd){case LED_ON:gpiod_set_value(gpiono3, 1);break;case LED_OFF:gpiod_set_value(gpiono3, 0);break;}break;                          }return 0;
}struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,
};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, "myled");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备节点信息int i;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_irq = of_find_node_by_path("/myirq");if(dev_irq == NULL){printk("解析irq设备树节点失败\n");return -EFAULT;}dev_led = of_find_node_by_path("/leds");if(dev_led == NULL){printk("解析led设备树节点失败\n");return -EIO;}printk("解析设备树节点成功\n");// 申请gpio_desc对象并设置输出为低电平gpiono1 = gpiod_get_from_of_node(dev_led, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);if(IS_ERR(gpiono1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono1);}gpiono2 = gpiod_get_from_of_node(dev_led, "led2-gpios", 0, GPIOD_OUT_LOW, NULL);if(IS_ERR(gpiono1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono1);}gpiono3 = gpiod_get_from_of_node(dev_led, "led3-gpios", 0, GPIOD_OUT_LOW, NULL);if(IS_ERR(gpiono1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono1);}printk("申请gpio对象成功\n");//根据设备树节点解析出软中断号sirqno1 = irq_of_parse_and_map(dev_irq, 0); //按键1索引号为0if(!irqno1){printk("解析软中断号失败\n");return -ENXIO;}irqno2 = irq_of_parse_and_map(dev_irq, 1);if(!irqno2){printk("解析软中断号失败\n");return -ENXIO;}irqno3 = irq_of_parse_and_map(dev_irq, 2);if(!irqno3){printk("解析软中断号失败\n");return -ENXIO;}printk("解析软中断号成功 irqno123=%d,%d,%d\n",irqno1,irqno2,irqno3);//注册中断ret = request_irq(irqno1, myirq_handler, IRQF_TRIGGER_FALLING, "key1", NULL);if(ret){printk("注册中断失败\n");return ret;}ret = request_irq(irqno2, myirq_handler, IRQF_TRIGGER_FALLING, "key2", NULL);if(ret){printk("注册中断失败\n");return ret;}ret = request_irq(irqno3, myirq_handler, IRQF_TRIGGER_FALLING, "key3", NULL);if(ret){printk("注册中断失败\n");return ret;}printk("注册中断成功\n");return 0;
}static void __exit mycdev_exit(void)
{//注销中断free_irq(irqno1, NULL);free_irq(irqno2, NULL);free_irq(irqno3, NULL);//灭灯gpiod_set_value(gpiono1, 0);gpiod_set_value(gpiono2, 0);gpiod_set_value(gpiono3, 0);//释放gpio编号gpiod_put(gpiono1);gpiod_put(gpiono2);gpiod_put(gpiono3);//销毁节点信息int i;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");

应用层 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>#define LED_ON  _IO('l', 1)
#define LED_OFF _IO('l', 0)int main(int argc,const char * argv[])
{int sel;int fd1 = open("/dev/myled0", O_RDWR);if(fd1 < 0){perror("open");printf("%s : %s : %d\n", __FILE__, __func__, __LINE__);return -1;}int fd2 = open("/dev/myled1", O_RDWR);if(fd2 < 0){perror("open");printf("%s : %s : %d\n", __FILE__, __func__, __LINE__);return -1;}int fd3 = open("/dev/myled2", O_RDWR);if(fd3 < 0){perror("open");printf("%s : %s : %d\n", __FILE__, __func__, __LINE__);return -1;}while(1){printf("1> LED1 ON\n");printf("2> LED1 OFF\n");printf("3> LED2 ON\n");printf("4> LED2 OFF\n");printf("5> LED3 ON\n");printf("6> LED3 OFF\n");printf("请选择功能>>>");scanf("%d", &sel);getchar();switch(sel){case 1:ioctl(fd1, LED_ON); break;case 2:ioctl(fd1, LED_OFF);break;case 3:ioctl(fd2, LED_ON); break;case 4:ioctl(fd2, LED_OFF);break;case 5:ioctl(fd3, LED_ON); break;case 6:ioctl(fd3, LED_OFF);break;}}close(fd1);close(fd2);close(fd3);return 0;
}

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

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

相关文章

明日展望:算法备案法规的发展趋势

在数字化日益普遍的世界里&#xff0c;算法在我们生活的各个方面扮演着重要角色&#xff0c;从为我们推荐下一部要看的电影&#xff0c;到决定我们的信贷审批。然而&#xff0c;随着算法的影响力越来越大&#xff0c;关于如何对其进行合理、公正的管理和备案的问题也变得愈发重…

RestTemplate、WebClient与HttpInterface

RestTemplate、WebClient与HttpInterface SpringBoot中集成了很多轻量级的Http客户端 RestTemplate:普通开发WebClient:响应式编程开发HttpInterface:声明式编程 响应式编程介绍 响应式编程&#xff08;Reactive Programming&#xff09;是一种编程范式&#xff0c;用于处理…

如何在免费版 pycharm 中使用 github copilot (chatGPT)?

起因 在 vscode 中使用了 github copilot 以后&#xff0c;感觉这个人工智能还不错。 但 vscode 对于 python 项目调试并不是特别方便&#xff0c;所以想在 Pycharm 中也能使用同一个 github 账号&#xff0c;用上 copilot 的功能。 不需要等待&#xff0c;安装即用&#xff…

【Web 表单】与用户数据打交道-1(mdn笔记)

0. Web 表单指南 我们将介绍 Web 表单的各个方面&#xff1a;HTML 结构、样式、验证表单数据&#xff0c;以及提交数据到服务器。 基本指南 你的第一个表单 第一次创建 HTML 表单的经验&#xff0c;包括设计一个简单表单、使用正确的 HTML 元素实现它、通过 CSS 添加一些非常简…

从vue3速学react

单位老项目vue2,新项目vue3,业务已经熟练使用vue了&#xff0c;空余时间自学下react&#xff0c;写个博客记录下 react没有双向绑定&#xff0c;用的是jsx语法&#xff0c;useState后面是初始化值&#xff0c;需要改变data的时候&#xff0c;需要用定义的setXXX来改变XXX值&am…

【Spring Cloud一】微服务基本知识

系列文章目录 微服务基本知识 系列文章目录前言一、系统架构的演变1.1单体架构1.2分层架构1.3分布式架构1.4微服务架构1.5分布式、SOA、微服务的异同点 二、CAP原则三、RESTfulRESTful的核心概念&#xff1a; 四、共识算法 前言 在实际项目开发过程中&#xff0c;目前负责开发…

Ruff代码分析

Ruff是一个用 Rust 语言编写的高性能的 Python 静态代码分析工具&#xff0c;比其它分析工具快几个数量级&#xff08;10-100 倍&#xff09;&#xff0c;而且功能也很全面。 即 Linter&#xff0c;用于检查代码中的语法错误、编码规范问题、潜在的逻辑问题和代码质量问题等&a…

Golang 中实现实时聊天通讯

客户端代码 package mainimport ("fmt""log""net/url""os""os/signal""time""github.com/gorilla/websocket" )func main() {interrupt : make(chan os.Signal, 1)signal.Notify(interrupt, os.Interr…

webpack5 学习之路

1.视频 01-课程介绍_哔哩哔哩_bilibili 2.配套资料 依赖环境 | 尚硅谷 Web 前端之 Webpack5 教程 3.webpack 官方文档 入口起点(entry points) | webpack 中文文档 4.vue cli 官方文档 介绍 | Vue CLI 挖矿&#xff1a;Coding Tree

lombok

lombok lombok是一个简化java代码编写的工具类&#xff0c;可以简化javabean的编写&#xff0c;可以通过注解的方式消除代码中的构造方法&#xff0c;getter/setter等代码&#xff0c;简化类的编写。 Lombok原理分析 Lombok核心在于对注解的解析上。JDK5引入了注解的同时&…

ES派生类的prototype方法中,不能访问super的解决方案

1 下面的B.prototype.compile方法中&#xff0c;无法访问super class A {compile() {console.log(A)} }class B extends A {compile() {super.compile()console.log(B)} }B.prototype.compile function() {super.compile() // 报错&#xff0c;不可以在此处使用superconsole.…

Spring?Boot项目如何优雅实现Excel导入与导出功能

目录 背景EasyExcel 问题分析与解决Spring Boot Excel 导入与导出 依赖引入Excel 导入 基本导入功能进阶导入功能Excel 导出 Excel 导入参数校验 开启校验 校验规则定义 Bean Validation 定义校验规则ExcelValidator 接口定义校验规则校验结果接收 异常捕获接收校验结果contro…

小研究 - 主动式微服务细粒度弹性缩放算法研究(三)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放&#xff0c;忽略了能够充分利用单台服务器资源的细粒度垂直缩放&#xff0c;从而导致资源浪费。为此&#xff0c;本文设计了主动式微服务细粒度弹性缩放算法…

SDWAN组网案例——跨国游戏公司

XYZ Game Studios是一家国际知名的游戏开发公司&#xff0c;其游戏产品广受欢迎&#xff0c;拥有全球范围的玩家基础。由于游戏的在线特性和全球用户分布&#xff0c;XYZ Game Studios面临着跨国游戏服务器之间的网络连接和稳定性问题。他们希望提供更稳定、高效的游戏体验&…

使用 Go 语言实现二叉搜索树

原文链接&#xff1a; 使用 Go 语言实现二叉搜索树 二叉树是一种常见并且非常重要的数据结构&#xff0c;在很多项目中都能看到二叉树的身影。 它有很多变种&#xff0c;比如红黑树&#xff0c;常被用作 std::map 和 std::set 的底层实现&#xff1b;B 树和 B 树&#xff0c;…

Total Variation loss

Total Variation loss 适合任务 图像复原、去噪等 处理的问题 图像上的一点点噪声可能就会对复原的结果产生非常大的影响&#xff0c;很多复原算法都会放大噪声。因此需要在最优化问题的模型中添加一些正则项来保持图像的光滑性&#xff0c;图片中相邻像素值的差异可以通过…

使用 Webpack 优化前端开发流程

在现代前端开发中&#xff0c;构建工具的选择和优化流程的设计至关重要。Webpack 是一个功能强大的前端构建工具&#xff0c;能够优化我们的开发流程&#xff0c;提高开发效率和项目性能。本文将介绍如何使用 Webpack 来优化前端开发流程。 代码优化和资源管理也是前端项目中不…

传统计算机视觉

传统计算机视觉 计算机视觉难点图像分割基于主动轮廓的图像分割基于水平集的图像分割交互式图像分割基于模型的运动分割 目标跟踪基于光流的点目标跟踪基于均值漂移的块目标跟踪基于粒子滤波的目标跟踪基于核相关滤波的目标跟踪 目标检测一般目标检测识别之特征一般目标检测识别…

18.Netty源码之ByteBuf 详解

highlight: arduino-light ByteBuf 是 Netty 的数据容器&#xff0c;所有网络通信中字节流的传输都是通过 ByteBuf 完成的。 然而 JDK NIO 包中已经提供了类似的 ByteBuffer 类&#xff0c;为什么 Netty 还要去重复造轮子呢&#xff1f;本节课我会详细地讲解 ByteBuf。 JDK NIO…

Spring学习记录----十五、面向切面编程AOP+十六、Spring对事务的支持

目录 十五、面向切面编程AOP 15.1 AOP介绍 总结 15.2 AOP的七大术语 15.3 切点表达式 15.4 使用Spring的AOP 15.4.1 准备工作 15.4.1.1Spring AOP 基于注解之实现步骤 15.4.1.2-Spring AOP 基于注解之切点表达式 代码 运行结果&#xff1a; 代码 运行结果 通知类…