驱动开发(中断)

头文件:

#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");

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

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

相关文章

Element-plus中tooltip 提示框修改宽度——解决方案

tooltip 提示框修改宽度方法&#xff1a; 在element中&#xff0c;想要设置表格的内容&#xff0c;超出部分隐藏&#xff0c;鼠标悬浮提示 可以在el-table 上添加show-overflow-tooltip属性 同时可以通过tooltip-options配置提示信息 如下图代码 <el-tableshow-overflo…

【C#学习笔记】数组和索引器

文章目录 数组单维数组多维数组交错数组 索引器类上的索引器方法1方法2 接口中的索引器 数组 数组具有以下属性&#xff1a; 数组可以是一维、多维或交错的。创建数组实例时&#xff0c;将建立纬度数量和每个纬度的长度。 这些值在实例的生存期内无法更改。数值数组元素的默认…

局域网VoIP网络电话测试

0. 环境 ubuntu18或者ubuntu22 - SIP服务器 win10 - SIP客户端1 ubuntu18 - SIP客户端2 1. SIP服务器搭建asterisk 1.0 环境 虚拟机ubuntu18 或者ubuntu22 1.1 直接安装 sudo apt-get install asterisk 1.2 配置用户信息 分为两个部分&#xff0c;第一部分是修改genera…

python——案例10:认识if、elif、else

案例10&#xff1a;认识if、elif、elsenumfloat(input("输入数值&#xff1a;")) #用户输入数字if num>0:print("正数")elif num0:print("零") else:print("负数")#输出结果如下&#xff1a;输入数值&#xff1a;-1 负数 输入数值…

高级web前端开发工程师岗位的具体内容概述(合集)

高级web前端开发工程师岗位的具体内容概述1 职责&#xff1a; 1、负责前端页面开发和维护&#xff0c;并根据需求优化产品性能、用户体验、交互效果及各种主流浏览器以及各类型移动客户端的兼容适配工作; 2、配合产品经理和UI设计师&#xff0c;通过各种前端技术手段&#xf…

Qt能跨多少个平台?Qt能支持多少个平台?

2023年8月5日&#xff0c;周日下午 目录 Qt所支持的平台更多关于Qt支持的信息 Qt所支持的平台 图中显示的平台都支持。 想要更详细的平台支持信息可以查看&#xff1a;Supported Platforms | Qt 5.15 更多关于Qt支持的信息 Qt - 支持的平台及语言

微信小程序使用editor富文本编辑器 以及回显 全屏弹窗的模式

<!--富文本接收的位置--><view class"white-box"><view class"title"><view class"yellow-fence"></view><view class"v1">教研记录</view></view><view class"add-btn"…

检查网站是HTTP那种协议与获取域名的ipv6地址

前言 最近在做HTTPS的应用&#xff0c;可能需要使用ipv6的地址做SLB&#xff0c;但是怎么检查配置正确&#xff0c;总不能每次都看日志吧&#xff0c;实际上客户端也很容易查看&#xff0c;总结工作经验。 检查HTTP协议版本 笔者想到了使用浏览器方式&#xff0c;或者抓包&a…

vim粘贴内容格式混乱解决方法

问题 复制本地文件内容后&#xff0c;咱贴到vim文本内&#xff0c;格式错乱 解决方法 打开vim配置文件 最后面加入一行 vim /etc/vimrc set pastetoggle<F11> 开发vim文件&#xff0c;进入后先按F11进入交互模式 shift insert 再次粘贴 解决

后端进阶之路——综述Spring Security认证,授权(一)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ 解决算法&#xff0c;一个专栏就够了★ ★ 架…

SQL Server数据库如何添加mysql链接服务器(Windows系统)

SQL Server数据库如何添加mysql链接服务器&#xff08;Windows系统&#xff09; 一、说明二、下载mysql的odbc驱动三、安装mysql odbc四、配置ODBC4.1 控制面板→ODBC数据源&#xff08;64位&#xff09;→双击打开4.2 添加msql odbc数据源 五、测试添加是否成功六、打开SSMS&a…

【Paper Reading】DETR:End-to-End Object Detection with Transformers

背景 Transformer已经在NLP领域大展拳脚&#xff0c;逐步替代了LSTM/GRU等相关的Recurrent Neural Networks&#xff0c;相比于传统的RNN&#xff0c;Transformer主要具有以下几点优势 可解决长时序依赖问题&#xff0c;因为Transformer在计算attention的时候是在全局维度进行…

Java基础——注解

1 概述 注解用于对Java中类、方法、成员变量做标记&#xff0c;然后进行特殊处理&#xff0c;至于到底做何种处理由业务需求来决定。 例如&#xff0c;JUnit框架中&#xff0c;标记了注解Test的方法就可以被当做测试方法进程执行 2 自定义注解 public interface 注解名称 {p…

8.1 配置环境/Linux进程管理总结/Argument/saveload Module/切片

文章目录 一、配置环境二、Linux 进程管理总结三、ArgumentParser四、Saving and Loading Models nn.ModulesWarmstarting Model Using Parameters from a Different Model五、切片&#xff01;拓展&#xff1a; 一、配置环境 github配置环境可以直接赋值到txt中&#xff0c;然…

一 关于idea如何在svn进行项目下载并运行成功

安装svn客户端 如图 安装时请选择该选项&#xff08;Will be installed on local hard drive&#xff09;并选择自己想要安装的目录路径 如图 svn安装成功 如图 注意 安装完成后&#xff0c;使用svn进行一次checkout的项目导出完成以上五步时&…

Qt应用开发(基础篇)——滑块类 QSlider、QScrollBar、QDial

一、前言 滑块类QScrollBar、QSlider和QDial继承于QAbstractSlider&#xff0c;父类主要拥有最大值、最小值、步长、当前值、滑块坐标等信息&#xff0c;滑动的时候触发包含值数据变化、滑块按下、滑块释放等信号。键盘包括左/上和右/下箭头键通过定义的singleStep改变当前值&a…

程序框架-事件中心模块-观察者模式

一、观察者模式 1.1 观察者模式定义 意图&#xff1a; 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变是&#xff0c;所有依赖于它的对象都能得到通知并自动更新。 适用性&#xff1a; 当一个对象状态的改变需要改变其他对象&#xff0c; 或实际对…

大模型使用——超算上部署LLAMA-2-70B-Chat

大模型使用——超算上部署LLAMA-2-70B-Chat 前言 1、本机为Inspiron 5005&#xff0c;为64位&#xff0c;所用操作系统为Windos 10。超算的操作系统为基于Centos的linux&#xff0c;GPU配置为A100&#xff0c;所使用开发环境为Anaconda。 2、本教程主要实现了在超算上部署LLAM…

CentOS 安装 Jenkins

本文目录 1. 安装 JDK2. 获取 Jenkins 安装包3. 将安装包上传到服务器4. 修改 Jenkins 配置5. 启动 Jenkins6. 打开浏览器访问7. 获取并输入 admin 账户密码8. 跳过插件安装9. 添加管理员账户 1. 安装 JDK Jenkins 需要依赖 JDK&#xff0c;所以先安装 JDK1.8。输入以下命令&a…

【RabbitMQ(day4)】SpringBoot整合RabbitMQ与MQ应用场景说明

一、SpringBoot 中使用 RabbitMQ 导入对应的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>配置配置文件 spring:application:name: rabbitmq-springbo…