驱动:gpio子系统

通过GPIO子系统接口完成LED驱动的编写,编写应用程序控制灯亮灭(流水灯)

 驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include "led.h"unsigned int major;//主设备号
struct class *cls;//类指针
struct device *dev;//设备指针
struct device_node *np; // 设备树节点指针
// struct property *pp;//属性指针
int gpiono[3]; // gpio编号
char kbuf[128] = {};/*************************************封装各种操作方法*******************************************/
int mycdev_open(struct inode *inode, struct file *file)
{unsigned int minor;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);minor = MINOR(inode->i_rdev);file->private_data = (void *)minor;return 0;
}ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff_t)
{unsigned long ret;if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_to_user(ubuf, kbuf, size);if (ret){printk("copy_to_user filad\n");return ret;}return 0;
}ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t)
{unsigned long ret;if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_from_user(kbuf, ubuf, size);if (ret){printk("copy_from_user filad\n");return ret;}return 0;
}long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_ON:switch ((unsigned int)file->private_data){case 0: // LED1控制gpio_set_value(gpiono[0], 1);break;case 1: // LED2控制gpio_set_value(gpiono[1], 1);break;case 2: // LED3控制gpio_set_value(gpiono[2], 1);break;default:break;}break;case LED_OFF:switch ((unsigned int)file->private_data){case 0: // LED1控制gpio_set_value(gpiono[0], 0);break;case 1: // LED2控制gpio_set_value(gpiono[1], 0);break;case 2: // LED3控制gpio_set_value(gpiono[2], 0);break;default:break;}break;default: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,.read = mycdev_read,.write = mycdev_write,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};int all_led_init(void)
{int i;for (i = 0; i < 3; i++){gpiono[i] = of_get_named_gpio(np, "led-gpios", i); // 通过属性名字获取gpio编号if (gpiono[i] < 0){printk("get gpio failed\n");return -1;}printk("get gpio success,gpio=%d\n", gpiono[i]);// 申请解析到的gpio编号if (gpio_request(gpiono[i], NULL) < 0){printk("request gpio failed\n");return -1;}// 设置gpio为输出模式,默认输出低电平if (gpio_direction_output(gpiono[i], 0)){printk("set gpio output failed\n");return -1;}printk("set gpio output success\n");}return 0;
}static int __init mycdev_init(void)
{// int i,len;// np = of_find_node_by_name(NULL,"mynode");/**********字符设备驱动注册**********/int i;major = register_chrdev(0, "led", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功 major=%d\n", major);// 向上提交设备类cls = class_create(THIS_MODULE, "led");if (IS_ERR(cls)){printk("class_create falie\n");unregister_chrdev(major, "led");return PTR_ERR(cls);}printk("class_create success\n");// 向上提交设备信息for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "led%d", i);if (IS_ERR(dev)){printk("device_create filed\n");class_destroy(cls);unregister_chrdev(major, "led");return PTR_ERR(dev);}printk("device_create success\n");}// 通过路径查找设备树节点np = of_find_node_by_path("/leds"); if (np == NULL){printk("find node failed\n");return -1;}printk("find node success\n");all_led_init();return 0;
}static void __exit mycdev_exit(void)
{int i;for (i = 0; i < 3; i++){gpio_free(gpiono[i]); // 释放gpiodevice_destroy(cls, MKDEV(major, i));//注销设备}// 将设备类注销class_destroy(cls);/*注销设备驱动*/unregister_chrdev(major, "led");printk("unregister_chrdev success\n");
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用程序

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include "led.h"int stop_thread = 0; // 全局变量,用于控制线程停止
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void *led_ctl(void *arg)
{int *fd = (int *)arg;while (1){pthread_mutex_lock(&mutex);if (stop_thread){pthread_mutex_unlock(&mutex);break;}pthread_mutex_unlock(&mutex);ioctl(fd[0], LED_ON);ioctl(fd[1], LED_OFF);ioctl(fd[2], LED_OFF);sleep(1);ioctl(fd[0], LED_OFF);ioctl(fd[1], LED_ON);ioctl(fd[2], LED_OFF);sleep(1);ioctl(fd[0], LED_OFF);ioctl(fd[1], LED_OFF);ioctl(fd[2], LED_ON);sleep(1);}return NULL;
}int main(int argc, char const *argv[])
{int a,i;int fd[3];pthread_t tid;fd[0] = open("/dev/led0", O_RDWR);if (fd[0] < 0){perror("open");exit(1);}fd[1] = open("/dev/led1", O_RDWR);if (fd[1] < 0){perror("open");exit(1);}fd[2] = open("/dev/led2", O_RDWR);if (fd[2] < 0){perror("open");exit(1);}printf("open success\n");while (1){printf("请输入控制操作:0(关闭) 1(打开)\n");printf("请输入:");scanf("%d", &a);switch (a){case 0:{pthread_mutex_lock(&mutex);stop_thread = 1; // 设置全局变量,通知线程停止pthread_mutex_unlock(&mutex);pthread_join(tid, NULL);for(i=0;i<3;i++){ioctl(fd[i], LED_OFF);printf("i=%d\n",i);}}break;case 1:{pthread_mutex_lock(&mutex);stop_thread = 0; // 重置全局变量pthread_mutex_unlock(&mutex);if (pthread_create(&tid, NULL, led_ctl, fd) != 0){perror("pthread_create");exit(1);}}break;default:break;}}for(i=0;i<3;i++){close(fd[i]);}return 0;
}

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

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

相关文章

Django-Vue 学习-VUE

主组件中有多个Vue组件 是指在Vue.js框架中&#xff0c;主组件是一个父组件&#xff0c;它包含了多个子组件&#xff08;Vue组件&#xff09;。这种组件嵌套的方式可以用于构建复杂的前端应用程序&#xff0c;通过拆分功能和视图&#xff0c;使代码更加模块化、可复用和易于维…

MATLAB基础学习相关知识

MATLAB安装参考&#xff1a;抖音-记录美好生活 MATLAB基础知识学习参考&#xff1a;【1小时Matlab速成教程-哔哩哔哩】 https://b23.tv/CnvHtO3 第1部分&#xff1a;变量定义和基本运算 生成矩阵&#xff1a; % 生成矩阵% 直接法% ,表示行 ;表示列 a [1,2,3;4,5,6;7,8,9];%…

TypeScript - 数据类型 - 声明变量

TypeScript 是一种强类型的 JavaScript 超集&#xff0c;它引入了静态类型检查和类型注解。基础类型是 TypeScript 中最基本的类型&#xff0c;用于定义变量的类型。 一、数据类型 常用基本类型&#xff1a;boolean 、number 、string 常用&#xff0c;都是小写 1.布尔类型&…

有序任务规划的局限性

有序任务规划的局限性&#xff08;Limitation of Ordered-Task Planning&#xff09; 1. 任务前向分解&#xff08;TFD&#xff09;的限制 TFD&#xff08;Task Forward Decomposition&#xff09;是一种 基于完全有序方法&#xff08;Totally Ordered Methods&#xff09;的任…

MATLAB学习之旅:数据插值与曲线拟合

在MATLAB的奇妙世界里,我们已经走过了一段又一段的学习旅程。从基础的语法和数据处理,到如今,我们即将踏入数据插值与曲线拟合这片充满魅力的领域。这个领域就像是魔法中的艺术创作,能够让我们根据现有的数据点,构建出更加丰富的曲线和曲面,从而更好地理解和描述数据背后…

ASP.NET Core 下载文件

本文使用 ASP .NET Core&#xff0c;适用于 .NET Core 3.1、.NET 5、.NET 6和.NET 8。 另请参阅&#xff1a; 如何在将文件发送到浏览器后自动删除该文件。 如何将文件从浏览器上传到服务器。 如何在 ASP.NET Core 应用程序中从 URL/URI 下载文件。 如果使用.NET Framework&am…

Part 3 第十二章 单元测试 Unit Testing

概述 第十二章围绕单元测试展开&#xff0c;阐述了单元测试的实践与重要性&#xff0c;通过对比其他测试类型&#xff0c;突出其特点&#xff0c;还介绍了单元测试的最佳实践、避免的反模式以及与测试替身相关的内容&#xff0c;为编写高质量单元测试提供指导。 章节概要 1…

SpringCloud-Eureka初步使用

什么是REST是一组用于规范资源在网络中转移的表现形式软件架构设计风格.简单来说就是客户端和服务器之间的一种交互形式 什么是RESTful,满足了REST风格的接口或者程序,RESTful API是其中的接口,spring中提供了RestTemplate这个类,他强制执行了REST的规范,包括使用HTTP协议的状…

Linux 高级篇 日志管理、定制自己的Linux系统、备份与恢复

一、日志管理 &#xff08;1&#xff09;基本介绍 日志文件是重要的系统信息文件&#xff0c;记录了如用户登录、系统启动、系统安全、邮件及各种服务等相关重要系统事件在安全方面&#xff0c;日志也至关重要&#xff0c;它能记录系统日常发生的各类事情&#xff0c;可用于检…

SpringMVC 请求参数接收

目录 请求 传递单个参数 基本类型参数传递 未传递参数 ?传递参数类型不匹配 传递多个参数 传递对象 后端参数重命名 传递数组 传递集合 传递JSON数据 JSON是什么 JSON的优点 传递JSON对象 获取URL中的参数 文件上传 在浏览器与程序进行交互时&#xff0c;主要…

深度学习之图像回归(一)

前言 图像回归任务主要是理解一个最简单的深度学习相关项目的结构&#xff0c;整体的思路&#xff0c;数据集的处理&#xff0c;模型的训练过程和优化处理。 因为深度学习的项目思路是差不多的&#xff0c;主要的区别是对于数据集的处理阶段&#xff0c;之后模型训练有一些小…

23. AI-大语言模型-DeepSeek简介

文章目录 前言一、DeepSeek是什么1. 简介2. 产品版本1. 类型2. 版本3. 参数规模与模型能力 3. 特征4. 三种访问方式1. 网页端和APP2. DeepSeek API 二、DeepSeek可以做什么1. 应用场景2. 文本生成1. 文本创作2. 摘要与改写3. 结构化生成 3. 自然语言理解与分析1. 语义分析2. 文…

京东cfe滑块 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 headers {"accept&qu…

什么是事务?并发事务引发的问题?什么是MVCC?

文章目录 什么是事务&#xff1f;并发事务引发的问题&#xff1f;什么是MVCC&#xff1f;1.事务的四大特性2.并发事务下产生的问题&#xff1a;脏读、不可重复读、幻读3.如何应对并发事务引发的问题&#xff1f;4.什么是MVCC&#xff1f;5.可见性规则&#xff1f;参考资料 什么…

火语言RPA--Excel插入空行

【组件功能】&#xff1a;在Excel内指定的位置插入空行 配置预览 配置说明 在第n行之前 支持T或# 填写添加插入第n行之前行号。 插入n行 支持T或# 插入多少行。 Sheet页名称 支持T或# Excel表格工作簿名称。 示例 Excel插入空行 描述 在第3行之后插入3行。 配置 输…

【算法基础】--前缀和

前缀和 一、一维前缀和示例模板[寻找数组的中心下标 ](https://leetcode.cn/problems/tvdfij/description/)除自身以外的数组乘积和可被k整除的子数组 一、一维前缀和 前缀和就是快速求出数组某一个连续区间内所有元素的和。 示例模板 已知一个数组arr&#xff0c;求前缀和 …

buuctf-[极客大挑战 2019]Knife题解

一个很简单的web题&#xff0c;进入界面 网页名还加白给的shell&#xff0c;并且给的提示也很明显&#xff0c;给了一个一句话木马再加上菜刀&#xff0c;很怀疑是一个webshell题&#xff0c;那么直接打开蚁剑测试连接拿shell 用提示的一句话木马的密码&#xff0c;测试链接发现…

基于YOLO11深度学习的半导体芯片缺陷检测系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

零食店收银pos源码

各位零食店老板&#xff0c;你是否还在为以下问题头疼&#xff1f; 连锁门店越来越多&#xff0c;管理起来力不从心&#xff1f;散装称重商品收银效率低&#xff0c;顾客排队抱怨&#xff1f;线上订单激增&#xff0c;库存混乱&#xff0c;配送跟不上&#xff1f;营销活动花样少…

DeepSeek 冲击(含本地化部署实践)

DeepSeek无疑是春节档最火爆的话题&#xff0c;上线不足一月&#xff0c;其全球累计下载量已达4000万&#xff0c;反超ChatGPT成为全球增长最快的AI应用&#xff0c;并且完全开源。那么究竟DeepSeek有什么魔力&#xff0c;能够让大家趋之若鹜&#xff0c;他又将怎样改变世界AI格…