5.操作led

模版使用之前的hello驱动程序。
想要操作led,首先要找到原理图,查找GPIO对应的GPIO引脚
从图中能看出来LED2对应的GPIO是GPIO5_3,同时可以得知这个LED2是低电平点亮。查看cat /sys/kernel/debug/gpio可得知GPIO5_3(第四组GPIO的第三个引脚)的引脚编号是131。

确定好GPIO编号后,接下来就是要确定led驱动程序的功能,这里我希望它能开关led,以及能读取led的状态。所以可以去掉file_operations结构体中的open和release,只保留read和write。
接下来就是GPIO操作,套路如下

1.请求 GPIO: 使用gpio_request请求所需的 GPIO 引脚。

2.配置 GPIO: 请求成功后,可以配置 GPIO 的方向(输入或输出)和初始状态。
gpio_direction_input输入,gpio_direction_output输出。

3.使用 GPIO: 根据需要读写 GPIO 引脚的值。gpio_get_value读,gpio_set_value写。

4.释放 GPIO: 完成使用后,调用gpio_free函数释放该 GPIO 引脚。

 套用到我们的驱动程序中就是,在init函数中请求GPIO并设置方向为输出,在exit函数中释放GPIO,在read函数中获取GPIO的值,在write中设置GPIO的值。代码如下:

#include "asm-generic/gpio.h"
#include "asm/gpio.h"
#include "asm/uaccess.h"
#include "linux/printk.h"
#include "linux/scatterlist.h"
#include "linux/types.h"
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
#include <linux/module.h>#include <linux/uaccess.h>#define DEVICE_NAME "led_device"
#define LED2_NUM	131
#define LED2_ON		0
#define LED2_OFF	1
static struct class *led_class;
static struct device *led_device;
static int major;//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//参数含义依次为 要读取的文件指针 用户保存数据的buf 读取数据大小 文件内容的偏移量
static ssize_t led_read (struct file * filp, char __user *buf, size_t size, loff_t *offset)
{  unsigned long int ret;char value[1];value[0] = gpio_get_value(LED2_NUM) == LED2_ON ? 1 : 0;ret = copy_to_user(buf, value, 1);return 1;
}//ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//参数含义依次为 要写入的文件指针 用户要写入的数据buf 写入数据大小 文件内容的偏移量
static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{unsigned long int  ret;char value[1];ret = copy_from_user(value, buf, 1);if(1 == value[0])gpio_set_value(LED2_NUM, LED2_ON);elsegpio_set_value(LED2_NUM, LED2_OFF);return 1;
}/*构建file_operations结构体*/
static const struct file_operations led_fops = {.owner      = THIS_MODULE,.read		= led_read,.write		= led_write
};/*init函数,实现register_chrdev*/
static int __init led_init(void)
{int ret;ret = gpio_request(LED2_NUM, "LED2");if(ret < 0){printk("Failed to request GPIO:%d, ERRNO:%d\n", LED2_NUM, ret);return ret;}gpio_direction_output(LED2_NUM, LED2_OFF);//数含义依次为 主设备号,如果为0,内核会自动分配一个可用的。设备名,会在/proc/devices中显示。 file_operations结构体//注册成功就返回主设备号major = register_chrdev(0, DEVICE_NAME, &led_fops);//为这个模块创建一个名为led的类  在/sys/class/下会生成led目录led_class = class_create(THIS_MODULE, "led");if (IS_ERR(led_class)) {pr_err("failed to allocate class\n");return PTR_ERR(led_class);}//在/sys/class/led类下创建一个led设备,同时在/dev/下创建一个led节点led_device = device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");if (IS_ERR(led_device)) {pr_err("failed to allocate device\n");return PTR_ERR(led_device);}printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/*exit函数unregister_chrdev*/
static void __exit led_exit(void)
{gpio_free(LED2_NUM);//先销毁设备,后销毁类device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, DEVICE_NAME);printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}module_init(led_init);
module_exit(led_exit);
//遵循GPL协议
MODULE_LICENSE("GPL");

配套的应用程序写入1代表开灯,写入0代表关灯,没有参数代表读取led状态。
 

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>static int fd;/** ./led_test on * ./led_test off* ./led_test*/
int main(int argc, char **argv)
{int ret;char buf[1];int i;/* 2. 打开文件 */fd = open("/dev/led", O_RDWR);if (fd == -1){printf("can not open file /dev/led\n");return -1;}if (argc == 2){/* write */buf[0] = strcmp(argv[1], "on") == 0 ? 1 : 0;ret = write(fd, buf, 1);}else{ret = read(fd, buf, 1);printf("led status is %s\n", buf[0] == 1 ? "on" : "off");}close(fd);return 0;
}

上机测试如下

 

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

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

相关文章

【Oracle】Oracle语法之递归查询

目录 递归查询使用场景备注 语法相关属性解释 案例基本使用升级版-带上递归查询的属性 总结&#xff1a; 递归查询 Oracle的递归查询是指在一个查询语句中使用自引用的方式进行循环迭代查询。它可以用于处理具有层次结构的数据&#xff0c;如组织架构、产品类别等。递归查询通…

【深度学习入门篇 ⑧】关于卷积神经网络

【&#x1f34a;易编橙&#xff1a;一个帮助编程小伙伴少走弯路的终身成长社群&#x1f34a;】 大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; ) &#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

Python和C++骨髓细胞进化解析数学模型

&#x1f3af;要点 &#x1f3af; 数学模型邻接矩阵及其相关的转移概率 | &#x1f3af;蒙特卡罗模拟进化动力学 | &#x1f3af;细胞进化交叉图族概率 | &#x1f3af;进化图模型及其数学因子 | &#x1f3af;混合图模式对进化概率的影响 | &#x1f3af;造血干细胞群体的空间…

汇总国内镜像提供了Redis的下载地址

文章目录 1. 清华大学开源软件镜像站&#xff1a;2. 中国科技大学开源软件镜像&#xff1a;3. 阿里云镜像&#xff1a;4. 华为云镜像&#xff1a;5. 腾讯云镜像&#xff1a;6. 网易开源镜像站7. 官方GitHub仓库&#xff08;虽然不是镜像&#xff0c;但也是一个可靠的下载源&…

JAVA面试题--IO流

### IO流 #### 你知道BIO,NIO,AIO么&#xff1f;讲一下你的理解 BIO &#xff08;Blocking I/O&#xff09;&#xff1a;同步阻塞I/O 模式&#xff0c;以流的方式处理数据&#xff0c;数据的读取写入必须阻塞在一个线程内等待其完成。适用于连接数目比较小且固定的架构 NIO…

AI算法19-偏最小二乘法回归算法Partial Least Squares Regression | PLS

偏最小二乘法回归算法简介 算法概述 偏最小二乘法模型可分为偏最小二乘回归模型和偏最小二乘路径模型。其中偏最小二乘回归模型是一种新型的多元统计方法&#xff0c;它集中了主成分分析、典型相关分析和线性回归的特点&#xff0c;特别在解决回归中的共线性问题具有无可比拟…

# Redis 入门到精通(五)-- redis 持久化(2)

Redis 入门到精通&#xff08;五&#xff09;-- redis 持久化&#xff08;2&#xff09; 一、redis 持久化–save 配置与工作原理 1、RDB 启动方式&#xff1a;反复执行保存指令&#xff0c;忘记了怎么办&#xff1f;不知道数据产生了多少变化&#xff0c;何时保存&#xff1…

深入解析JVM内存模型:面试题及详细解答

深入解析JVM内存模型&#xff1a;面试题及详细解答 1. JVM内存模型概述1.1 面试题&#xff1a;请简述JVM内存模型的组成部分及其作用。1.1.1 详细解答 2. 垃圾收集与内存分配2.1 面试题&#xff1a;对象在JVM中的内存分配过程是怎样的&#xff1f;2.1.1 详细解答 3. 垃圾收集器…

centos清空history

centos清空history history -c && history -w

CNN之图像识别

Inception Inception网络是CNN发展史上一个重要的里程碑。在Inception出现之前&#xff0c;大部分流行CNN仅仅是把卷积层堆叠得越来越多&#xff0c;使网络越来越深&#xff0c;以此希望能够得到更好的性能。但是存在以下问题: 图像中突出部分的大小差别很大。由于信息位置的…

同学,你会用ChatGPT吗?

ChatGPT在国外走红后&#xff0c;国内的讯飞星火、文心一言以及最近备受瞩目的Kimi等AI大模型也迅速崭露头角。这些技术突破不仅展现了我国在人工智能领域的实力&#xff0c;更预示着未来工作方式的深刻变革。随着人工智能大模型的普及和应用&#xff0c;它们将如同个人电脑一样…

【typedb】例子:药物发现: studio运行

测试8:solution结果 测试1:获取名字为Q9NPB9的protein Let’s start by getting the names of the protein Q9NPB9:测试2:哪个基因编码了Q9NPB9 Now let’s see which gene encodes for protein Q9NPB9: 推理过程:

【Linux】基础I/O——FILE,用户缓冲区

1.FILE里的fd FILE是C语言定义的文件结构体&#xff0c;里面包含了各种文件信息。可以肯定的一点是&#xff0c;FILE结构体内一定封装了 fd 。为什么?来看接下来的思路分析&#xff1a; 1.使用系统接口的必然性   文件存储在磁盘上&#xff0c;属于外设。谁有权限访问…

RabbitMQ:基础篇

1.RabbitMQ是高性能的异步通讯组件 何为异步通讯 打电话就是同步通讯&#xff0c;微信聊天可以理解为异步通讯&#xff0c;不是实时的进行通讯&#xff1a;时效性差。 同步调用的缺点&#xff1a; 拓展性差&#xff08;需求不尽提&#xff09; 性能下降 级联失败 …

Ubuntu的SELinux

Ubuntu的SELinux 安装的软件包&#xff1a;selinux-policy-targeted、libselinux-utils、 policycoreutils 命令行命令 以下默认root用户输入命令 确保在下次重启时重新标记文件&#xff0c;会在根目录创建.autorelabel文件 fixfiles -F onboot状态和模式 查看当前的 SELinu…

Percolator 事务模型的理解和梳理

Percolator 事务模型 Percolator 协议是一个 2PC 协议&#xff0c;TiDB 、 CockroachDB 等都使用 Percolator 协议来做事务 Percolator 协议把数据附加额外 2 个信息以及版本的概念 如下&#xff0c;一个数据 A &#xff0c;类似以下方式表达&#xff1a; 版本datalockwrit…

Windows图形界面(GUI)-DLG-C/C++ - 静态控件(Static)

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​​​​链接点击跳转博客主页 目录 静态控件(Static) 控件样式 消息处理 实例代码 静态控件(Static) 控件样式 文本&#xff08;Text&#xff09;&#xff1a;用来显示文本信息。可以是简单的一行文本或者复杂的…

带你轻松玩转DevOps

一、DevOps详细介绍 软件开发最开始是由两个团队组成&#xff1a; 开发计划由**开发团队**从头开始设计和整体系统的构建。需要系统不停的迭代更新。**运维团队**将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。 这两个看似目标不同的团队&#xff0c;需要协同完…

HarmonyOS 开发者联盟高级认证最新题库

本篇文章包含 Next 版本更新后高级认证题库中95%的题目。 答案正确率 50-60%&#xff0c;答案仅做参考。 请在考试前重点看一遍题目&#xff0c;勿要盲目抄答案。 欢迎在评论留言正确答案和未整理的题目。 1、下面关于方舟字节码格式PREF_IMM16_v8_v8描述正确的是 16位前缀操作…

dp or 数学问题

看一下数据量&#xff0c;只有一千&#xff0c;说明这个不是数学问题 #include<bits/stdc.h> using namespace std;#define int long long const int mo 100000007; int n, s, a, b; const int N 1005;// 2 -3 // 1 3 5 2 -1 // 1 -2 -5 -3 -1 int dp[N][N]; int fun…