驱动开发day8(基于GPIO子系统编写LED驱动,编写应用程序进行测试,设置定时器,5秒钟打印一次hello world)

头文件:

#ifndef __HEAD_H__
#define __HEAD_H__#define LED_ON _IOW('l', 1,int)
#define LED_OFF _IOW('l', 0,int)
#endif

c文件

#include <stdlib.h>
#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 "head.h"
int main(int argc, char const *argv[])
{char buf[20] = "";int a, b;int fd = open("/dev/myled0", O_RDWR);if (fd < 0){printf("打开设备文件失败\n");return -1;}while (1){printf("请输入要实现的功能 1(关灯) 0(开灯):");scanf("%d", &a);switch (a){case 0:ioctl(fd, LED_ON);break;case 1:ioctl(fd, LED_OFF);break;}}close(fd);return 0;
}

驱动文件:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include "head.h"
int major;
char kbuf[20] = "";
struct class *cls;
struct device *dev;
struct device_node *dnode;
unsigned int gpionu1;
unsigned int gpionu2;
unsigned int gpionu3;
struct timer_list mytimer;
//int ret;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//自定义点灯函数
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_ON:gpio_set_value(gpionu1, 1);gpio_set_value(gpionu2, 1);gpio_set_value(gpionu3, 1);break;case LED_OFF:gpio_set_value(gpionu1, 0);gpio_set_value(gpionu2, 0);gpio_set_value(gpionu3, 0);break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};
//定时器处理函数
void mytimer_function(struct timer_list *timer)
{//打印一次hello worldprinkt("hellow world\n");//再次启用定时器mod_timer(timer,jiffies+(5*HZ));
}
static int __init mycdev_init(void)
{// 字符驱动设备注册major = register_chrdev(0, "myled", &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");// 解析设备树节点信息dnode = of_find_node_by_path("/myled");if (dnode == NULL){printk("解析设备树节点失败\n");return -ENXIO;}printk("解析设备树节点成功\n");// 获取LED1 GPIO编号gpionu1 = of_get_named_gpio(dnode, "led1-gpio", 0);if (gpionu1 < 0){printk("获取LED1GPIO编号失败\n");return -ENXIO;}// 获取LED2 GPIO编号gpionu2 = of_get_named_gpio(dnode, "led2-gpio", 0);if (gpionu2 < 0){printk("获取LED2GPIO编号失败\n");return -ENXIO;}// 获取LED3 GPIO编号gpionu3 = of_get_named_gpio(dnode, "led3-gpio", 0);if (gpionu3 < 0){printk("获取LED3GPIO编号失败\n");return -ENXIO;}// 申请LED1 GPIO编号int ret = gpio_request(gpionu1, NULL);if (ret){printk("申请LED1 GPIO编号失败");return -ENXIO;}printk("申请LED1 GPIO编号成功:%d\n", gpionu1);// 申请LED2 GPIO编号ret = gpio_request(gpionu2, NULL);if (ret){printk("申请LED2 GPIO编号失败");return -ENXIO;}printk("申请LED2 GPIO编号成功:%d\n", gpionu2);// 申请LED3 GPIO编号ret = gpio_request(gpionu3, NULL);if (ret){printk("申请LED3 GPIO编号失败");return -ENXIO;}printk("申请LED3 GPIO编号成功:%d\n", gpionu3);// 设置LED1 GPIO输出ret = gpio_direction_output(gpionu1, 0);if (ret){printk("LEd1 GPIO输出设置失败\n");return -1;}// 设置LED2 GPIO输出ret = gpio_direction_output(gpionu2, 0);if (ret){printk("LEd2 GPIO输出设置失败\n");return -1;}// 设置LED3 GPIO输出ret = gpio_direction_output(gpionu3, 0);if (ret){printk("LEd3 GPIO输出设置失败\n");return -1;}//初始化定时器对象timer_setup(&mytimer,mytimer_function,0);mytimer.expires=jiffies+(5*HZ);//定时5s//注册定时器add_timer(&mytimer);return 0;
}
static void __exit mycdev_exit(void)
{// 设置灯灭gpio_set_value(gpionu1, 0);gpio_set_value(gpionu2, 0);gpio_set_value(gpionu3, 0);//注销定时器del_timer(&mytimer);// 释放GPIO编号gpio_free(gpionu1);gpio_free(gpionu2);gpio_free(gpionu3);// 销毁设备节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);// 注销字符设备驱动unregister_chrdev(major, "myled");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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

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

相关文章

云起无垠典型案例入选《2023软件供应链安全洞察》报告

近日&#xff0c;历时6个月&#xff0c;由ISC编制的《2023软件供应链安全洞察》报告&#xff08;以下简称《报告》&#xff09;正式对外发布。《报告》围绕软件供应链安全现状、技术内核、治理指南、落地实践展开&#xff0c;以期为行业从业者提供有价值的信息和洞见&#xff0…

1.1 计算机安全概念

思维导图&#xff1a; 前言&#xff1a; 第1章: 计算机与网络安全概念笔记 1. 学习目标 了解保密性、完整性和可用性的关键安全需求。了解OSI的X.800安全架构。识别和举例说明不同的安全威胁和攻击。掌握安全设计的基本准则。熟悉攻击面和攻击树的使用。了解与密码标准相关的…

2024年最新水果音乐制作软件FL Studio21需要多少钱呢?

水果&#xff0c;全称Fruity Loop Studio&#xff0c;简称FL Studio。是一款全能的音乐制作软件&#xff0c;经过二十多年的演化更迭&#xff0c;其各项功能非常的先进。其开创性的Pat\song模式&#xff0c;也为初学者的学习提供了便利。那么水果音乐制作软件FL Studio21需要多…

PostgreSQL基于Patroni方案的高可用启动流程分析

什么是Patroni 在很多生产环境中&#xff0c;分布式数据库以高可用性、数据分布性、负载均衡等特性&#xff0c;被用户广泛应用。而作为高可用数据库的解决方案——Patroni&#xff0c;是专门为PostgreSQL数据库设计的&#xff0c;一款以Python语言实现的高可用架构模板。该架构…

博彦科技:以金融为起点,凭借创新技术平台真打实干

【科技明说 &#xff5c; 重磅专题】 成立于1995年的博彦科技&#xff0c;已有28年左右的发展历程。 我没有想到&#xff0c;博彦科技也对AIGC领域情有独钟。博彦科技自研的数字人产品SaaS平台&#xff0c;可以接入包括百度文心一言、阿里通义千问等AI大模型产品。可见&#…

2023-10 最新jsonwebtoken-jjwt 0.12.3 基本使用

导入依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.12.3</version></dependency>包括了下面三个依赖, 所以导入上面一个就OK了 <dependency><groupId>io.jsonwe…

前端、HTTP协议(重点)

什么是前端 前端是所有跟用户直接打交道的都可以称之为是前端 比如&#xff1a;PC页面、手机页面、平板页面、汽车显示屏、大屏幕展示出来的都是前端内容 能够用肉眼看到的都是前端 为什么要学前端 学了前端以后我们就可以做全栈工程师(会后端、会前端、会DB、会运维等) 咱…

actual combat 21——华为云从零开始项目部署(附nginx转发域名方式)

一、IP地址方式&#xff1a; 后端&#xff1a; 确保项目本地跑通建立并运行华为云流水线 前端&#xff1a; 打包&#xff08;测试环境&#xff09;手动上传 nginx&#xff1a; 配置一下即可 华为云&#xff1a; 安全组&#xff1a;暴露后端网关端口安全组&#xff1a;暴…

036-第三代软件开发-系统时间设置

第三代软件开发-系统时间设置 文章目录 第三代软件开发-系统时间设置项目介绍系统时间设置演示效果QML 实现小伙伴自创 TumblerQt 家 Tumbler C 端实现 总结一下 关键字&#xff1a; Qt、 Qml、 Time、 时间、 系统 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;…

Flink Data Sink

本专栏案例代码和数据集链接: https://download.csdn.net/download/shangjg03/88477960 1. Data Sinks 在使用 Flink 进行数据处理时,数据经 Data Source 流入,然后通过系列 Transformations 的转化,最终可以通过 Sink 将计算结果进行输出,Flink Data Sinks 就是用于定义…

【杂记】Ubuntu20.04装系统,安装CUDA等

装20.04系统 安装系统的过程中&#xff0c;ROG的B660G主板&#xff0c;即使不关掉Secure boot也是可以的&#xff0c;不会影响正常安装&#xff0c;我这边出现问题的主要原因是使用了Ventoy制作的系统安装盘&#xff0c;导致每次一选择使用U盘的UEFI启动&#xff0c;就会跳回到…

QTcpServer简单的TCP服务器连接

1、简介 简单实现控制TCP服务器获取连接的套接字。点击断开服务器即可关闭所有连接&#xff0c;最大连接数量为5个。 声明源文件 #include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {//设置固定大小setFixedSize(1024,600);b…

状态机图和活动图

在面向对象软件分析过程中&#xff0c;状态机图和活动图用于建立软件的动态模型&#xff0c;主要描述系统随时间变化的行为。 1.状态图 1.1概念 状态图用来描述对象状态和事件之间的关系&#xff0c;强调一个实体基于事件反应的动态行为。状态图适合用于表述在不同用例之间的…

【windows 脚本】netsh命令

netsh 是 Windows 操作系统中的一个命令行工具&#xff0c;用于配置和管理网络设置。它提供了一系列的命令和参数&#xff0c;可以用于配置网络接口、防火墙、路由表等网络相关的设置。以下是一些常用的 netsh 命令和用法&#xff1a; 配置静态IP&#xff0c;IP地址、子网掩码和…

【电路笔记】-交流波形和交流电路理论

交流波形和交流电路理论 文章目录 交流波形和交流电路理论1、概述2、交流发电2.1 涡轮发电2.2 变压器 3、交流功率3.1 RMS值3.2 功率分配 4、总结 当谈论电流或电压时&#xff0c;这些信号可以分为两大类&#xff1a;直流和交流。 DC 状态为“直流电”&#xff0c;该定义重新组…

Webpack简介及打包演示

Webpack 是一个静态模块打包工具&#xff0c;从入口构建依赖图&#xff0c;打包有关的模块&#xff0c;最后用于展示你的内容 静态模块&#xff1a;编写代码过程中的&#xff0c;html&#xff0c;css&#xff0c; js&#xff0c;图片等固定内容的文件 打包过程&#xff0c;注…

深度学习_1 介绍;安装环境

深度学习 学习自李沐老师的课程。笔记主要以总结老师所讲解的内容以及我个人的想法为主&#xff0c;侵删&#xff01; 课程链接&#xff1a;课程安排 - 动手学深度学习课程 (d2l.ai) 介绍 AI地图&#xff1a; 我们以前写的非 AI 类程序基本都是人自己去想会遇到什么样的问题…

2023年9月电子学会Python等级考试试卷(五级)答案解析

青少年软件编程(Python)等级考试试卷(五级) 一、单选题(共25题,共50分) 1. 阅读以下代码,程序输出结果正确的选项是?( ) def process_keywords(keywords_list): unique_keywords = list(set(keywords_list)) sorted_keywords = sorted(unique_keywords) …

LVS-DR模式+keepalived+nginx+tomcat实现动静分离、负载均衡、高可用实验

实验条件&#xff1a; test2——20.0.0.20——主服务器——ipvsadm、keepalived服务 test3——20.0.0.30——备服务器——ipvsadm、keepalived服务 nginx5——20.0.0.51——后端真实服务器1&#xff08;tomcat的代理服务器&#xff09;——nginx服务 nginx6——20.0.0.61—…

Echarts渲染不报错但是没有内容

&#x1f525;博客主页&#xff1a; 破浪前进 &#x1f516;系列专栏&#xff1a; Vue、React、PHP ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 问题&#xff1a;在开发项目的时候使用了Echarts但是好端端的忽然就不渲染了 感觉很无语啊&#xff0c;毕竟好好的就不渲染了&am…