通过platform总线驱动框架编写LED灯的驱动,编写应用程序测试,发布到CSDN

效果图

设备树代码

myplatform{compatible = "hqyj,myplatform";led1-gpio=<&gpioe 10 0>;led2-gpio=<&gpiof 10 0>;led3-gpio=<&gpioe 8 0>;           interrupt-parent = <&gpiof>;interrupts=<9 0>;reg=<0X12345678 0X400>;}; 

应用程序

#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>//创建功能码
#define LED_ON _IOW('l',1,int)  
#define LED_OFF _IOW('l',0,int)int main(int argc, char const *argv[])
{int a,b;int fd=open("/dev/myled0",O_RDWR);if(fd<0){printf("打开设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入要实现的功能\n");printf("0(关灯) 1(开灯)\n");printf("请输入>");scanf("%d",&a);printf("请输入要控制的灯\n");printf("1(LED1) 2(LED2) 3(LED3)\n");printf("请输入>");scanf("%d",&b);switch(a){case 1:ioctl(fd,LED_ON,b);break;case 0:ioctl(fd,LED_OFF,b);break;}}close(fd);return 0;
}

驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>//主设备号
int major;//用于上传目录和设备节点信息
struct class *cls;
struct device *device;// led设备号
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;// 创建功能码
#define LED_ON _IOW('l', 1, int)
#define LED_OFF _IOW('l', 0, int)// ioctl函数,用于控制led设备
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_ON:switch (arg){case 1:gpiod_set_value(gpiono1, 1);break;case 2:gpiod_set_value(gpiono2, 1);break;case 3:gpiod_set_value(gpiono3, 1);break;}break;case LED_OFF:switch (arg){case 1:gpiod_set_value(gpiono1, 0);break;case 2:gpiod_set_value(gpiono2, 0);break;case 3:gpiod_set_value(gpiono3, 0);break;}break;}return 0;
}// 定义操作方法结构体变量并赋值
struct file_operations fops = {.unlocked_ioctl = mycdev_ioctl,
};// 封装probe函数,当设备和驱动匹配成功之后执行
int pdrv_probe(struct platform_device *dev)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);// 字符设备驱动注册major = register_chrdev(0, "mychrdev", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "mychrdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");// 向上提交设备节点信息int i; // 向上提交三次设备节点信息for (i = 0; i < 3; i++){device = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);if (IS_ERR(dev)){printk("向上提交设备节点失败\n");return -PTR_ERR(dev);}}printk("向上提交设备节点成功\n");// 解析LED1的gpio编号gpiono1 = gpiod_get_from_of_node(dev->dev.of_node, "led1-gpio", 0, GPIOD_OUT_LOW, NULL);if (gpiono1 == NULL){printk("解析led1对应gpio编号失败\n");return -ENXIO;}printk("解析led1对应gpio编号成功\n");// 解析LED1的gpio编号gpiono2 = gpiod_get_from_of_node(dev->dev.of_node, "led2-gpio", 0, GPIOD_OUT_LOW, NULL);if (gpiono2 == NULL){printk("解析led2对应gpio编号失败\n");return -ENXIO;}printk("解析led2对应gpio编号成功\n");// 解析LED1的gpio编号gpiono3 = gpiod_get_from_of_node(dev->dev.of_node, "led3-gpio", 0, GPIOD_OUT_LOW, NULL);if (gpiono3 == NULL){printk("解析led3对应gpio编号失败\n");return -ENXIO;}printk("解析led3对应gpio编号成功\n");return 0;
}
// 封装remove函数,用于驱动和设备卸载时执行
int pdrv_remove(struct platform_device *dev)
{// 销毁设备节点信息device_destroy(cls, MKDEV(major, 0));// 销毁设备节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 释放gpio编号gpiod_put(gpiono1);gpiod_put(gpiono2);gpiod_put(gpiono3);// 销毁目录class_destroy(cls);// 注销字符设备驱动unregister_chrdev(major, "mychrdev");printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 构建用于匹配的设备树表
struct of_device_id oftable[] = {{.compatible = "hqyj,myplatform",},{/* end node */}, // 防止数组越界
};
// 分配驱动对象并初始化
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name = "bbbbb",.of_match_table = oftable, // 设置设备树匹配},};
// 一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

抖店商家想要抓住2024年第一波流量,你需要这样做!

大家好&#xff0c;我是电商小布。 春节假期结束了&#xff0c;我们的工作也开始走入正轨当中了。 对于停工一段时间的抖店商家来说&#xff0c;想要在年后抓住第一波流量&#xff0c;该怎么做呢&#xff1f; 简单一点说&#xff0c;还是在运营上。 一、检查店铺类目情况 …

数字电路 第一章—第三节(逻辑函数的化简方法)

一、逻辑函数的标准与或式和最简式 1、标准与或表达式 &#xff08;1&#xff09;下图给出了逻辑函数Y的标准与或表达式&#xff0c;在表达式中每一个乘积项都具有标准形式&#xff0c;这种标准形式的乘积项称为最小项。 &#xff08;2&#xff09;最小项是逻辑代数中的一个…

Windows 2008部署

创建虚拟机2008 创建之后实现远程连接 后端部署 然后解压jdk tomcat mysql jdk 配置环境变量 修改JAVA_HOME 变量名&#xff1a;JAVA_HOME 变量值&#xff1a;电脑上JDK安装的绝对路径 修改CLASSPATH 变量名&#xff1a;CLASSPATH 变量值&#xff1a;.;%JAVA…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

力扣经典题目解析--旋转图像(字节二面)

题目 原题地址: . - 力扣&#xff08;LeetCode&#xff09; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1…

基础软件之道:企业级实践与开源创新【文末送书-22】

文章目录 前言-基础软件之路&#xff1a;企业级实践及开源之路企业级实践1. 高可用性和容错性2. 安全性和隐私保护3. 自动化和DevOps实践 开源之路1. 开源操作系统2. 容器化和编排工具3. 数据库系统4. 自动化工具 基于编译器的静态代码分析与软件开发效率、质量和性能1、静态分…

Sora还太远!国产AI创作恐怖电影:《生化危机:重生》上

Sora用不上&#xff01;国产AI创作恐怖电影&#xff1a;《生化危机&#xff1a;重生》上 丧尸围城&#xff0c;世界沦陷&#xff0c;爱丽丝是拯救这个世界的最后一剂解药&#xff0c;然而。。。 《生化危机&#xff1a;重生》&#xff08;上&#xff09;电影开始地球已经被丧尸…

最长的回文串

开始想的简单了&#xff0c;确实没想到奇数字母删去一个后也能用 解法&#xff1a; 桶排序 #include<iostream> #include<vector> #include<algorithm> using namespace std; #define endl \n #define int long long signed main() {int t;cin >> t…

前后端分离vscode保险业务管理系统vue+Nodejs

本设计主要应用于完成对保险业务进行计算机化的管理。系统前台展示各种种类的保险&#xff0c;顾客可以选择登陆后买入。公司员工为管理员&#xff0c;由公司统一分配账号&#xff0c;员工用工号密码登陆。可以修改密码&#xff0c;查看、修改自己的信息。员工可处理顾客信息。…

Qt 事件

1. 事件 事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。在Qt中使用一个对象来表示一个事件&#xff0c;它继承自QEvent类。 2. 事件和信号 事件与信号并不相同&#xff0c;比如我们使用鼠标点击了一下界面上的按钮&#xff0c;那么就会产生…

DT DAY3 信号和槽

作业&#xff1a; 1> 思维导图 2> 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 btn3 new QPushButton("按钮3",this);btn3->resize(ui->btn2->width(),ui->b…

【Spring】Spring MVC

目 录 一.什么是 Spring MVC&#xff1f;1.MVC 定义2.MVC 和 Spring MVC 的关系 二.为什么要学 Spring MVC&#xff1f;三.怎么学 Spring MVC&#xff1f;1.Spring MVC 创建和连接综上连接方式&#xff1a; 2.获取参数1.传递单个参数2.获取多个参数3.获取对象4.获取表单参数5.接…

基于springboot+vue的桂林旅游景点导游平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Pyglet综合应用|推箱子游戏之关卡图片载入内存

目录 读取图片 分割图片 综合应用 本篇为之前写的博客《怎样使用Pyglet库给推箱子游戏画关卡地图》的续篇&#xff0c;内容上有相关性&#xff0c;需要阅读的请见链接&#xff1a; https://hannyang.blog.csdn.net/article/details/136209138 「推箱子」是一款风靡全球的益…

RabbitMQ学习整理————基于RabbitMQ实现RPC

基于RabbitMQ实现RPC 前言什么是RPCRabbitMQ如何实现RPCRPC简单示例通过Spring AMQP实现RPC 前言 这边参考了RabbitMQ的官网&#xff0c;想整理一篇关于RabbitMQ实现RPC调用的博客&#xff0c;打算把两种实现RPC调用的都整理一下&#xff0c;一个是使用官方提供的一个Java cli…

开源博客项目Blog .NET Core源码学习(9:Autofac使用浅析)

开源博客项目Blog使用Autofac注册并管理组件和服务&#xff0c;Autofac是面向.net 的开源IOC容器&#xff0c;支持通过接口、实例、程序集等方式注册组件和服务&#xff0c;同时支持属性注入、方法注入等注入方式。本文学习并记录Blog项目中Autofac的使用方式。   整个Blog解…

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

UTONMOS开启数智龙年,打造元宇宙游戏圈新名片

新年已过&#xff0c;全国各个城市早已客流涌动、热闹非凡。这种繁华景象不仅存在于现实世界&#xff0c;也被复刻到元宇宙的虚拟空间中。 据介绍&#xff0c;UTONMOS“源起山海-神念无界”元宇宙游戏是以原创IP玄幻神话故事“元宇宙史纪”为蓝本打造的元宇宙游戏空间&#xf…

【DataTable.js】02.DataTable参考

一、Option 1.1 Features 属性类型默认值描述autoWidthbooleantrue是否自动调节单元格宽度&#xff0c;若传入了columns.width&#xff0c;可禁用该选项orderingbooleantrue是否支持排序pagingbooleantrue是否支持分页scrollXbooleanfalse是否支持横向滚动条scrollYstring启用…

2024年必备原型设计工具盘点,助你成为设计大神

原型设计是 UI/UX 设计中至关重要的一步&#xff0c;就像用户体验中的其他环节一样&#xff0c;有无数的原型工具可以帮助你完成原型设计。 如果市场上有太多的原型设计工具让你不知所措&#xff0c;不知道选择哪一个&#xff0c;恭喜你&#xff0c;这个原型设计工具的集合是为…