[驱动开发]gpio子系统及中断实现led亮灭

编写LED灯的驱动,使用GPIO子系统,里面添加按键的中断处理

1.应用程序发送指令控制发光二极管亮灭

2.按键1按下,led1电位反转;按键2按下,led2电位反转;按键3按下,led3电位反转 
 

//头文件
#ifndef __LED_H__
#define __LED_H__

//功能码
#define LED_ON _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)
#endif
//应用程序实现LED的亮灭
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include "led.h"
int main(int argc, const char *argv[])
{
	int a,b;
	while(1)
	{
		int fd_led = open("/dev/myled0",O_RDWR);	
		if(fd_led < 0)
		{
			printf("打开设备文件失败\n");
			exit(-1);
		}
		printf("请输入要控制的灯:1 2 3>>");
		scanf("%d",&b);
		printf("输入控制命令:0熄灭 1开灯>>>");
		scanf("%d",&a);
		switch(a)
		{
		case 1:
			ioctl(fd_led,LED_ON,&b);
			break;
		case 0:
			ioctl(fd_led,LED_OFF,&b);
			break;
		}
		close(fd_led);
	}
	return 0;
}
//驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/io.h>
#include<linux/of_irq.h>
#include<linux/interrupt.h>
#include "led.h"
/*  leds{
	led1-gpios=<&gpioe 10 0>;//10表示引脚编号  0表示默认
	led2-gpios=<&gpiof 10 0>;
	led3-gpios=<&gpioe 8 0>;
	};*/
struct device_node *dnode1;
struct device_node *dnode2;
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;
struct cdev *cdev;
int major=168;
int minor=0;
struct class *cls;
struct device *dev;
dev_t devno;
int i;
unsigned int irqno[3];      //软中断号

//中断处理函数
irqreturn_t myirq_handler(int irqno, void *dev_id)
{
	unsigned int id=(unsigned int)dev_id;
	switch(id)
	{
		case 0:
			printk("KEY1_INTERRUPT\n");
			gpiod_set_value(gpiono1,!gpiod_get_value(gpiono1));
			break;
		case 1:
			printk("KEY2_INTERRUPT\n");
			gpiod_set_value(gpiono2,!gpiod_get_value(gpiono2));
			break;
		case 2:
			printk("KEY3_INTERRUPT\n");
			gpiod_set_value(gpiono3,!gpiod_get_value(gpiono3));
			break;
	}

	return IRQ_HANDLED;
}
/*********************封装操作方法***************************/
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)
{
	int which;
	copy_from_user(&which,(void *)arg,4);
	switch(cmd)
	{
	case LED_ON:         // 亮灯
		switch(which)
		{
		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(which)
		{
		case 1:
			gpiod_set_value(gpiono1, 0);
			break;
		case 2:
			gpiod_set_value(gpiono2, 0);
			break;
		case 3:
			gpiod_set_value(gpiono3, 0);
		}
		break;
	}
	//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;
}
/***********************************************************************/

//定义一个操作方法结构体变量并初始化
struct file_operations fops =
{
	.open    =  mycdev_open,
	.release =  mycdev_close,
	.unlocked_ioctl = mycdev_ioctl,
};
static int __init mycdev_init(void)
{
	int ret,i;
	//1.申请对象空间 cdev_alloc
	cdev = cdev_alloc();
	if(cdev == NULL)
	{
		printk("申请对象空间失败\n");
		ret=-EFAULT;
		goto out1;
	}
	printk("申请对象空间成功\n");
	//2.初始化对象 cdev_init
	cdev_init(cdev,&fops);
	printk("初始化对象成功\n");
	//3.申请设备号 register_chrdev_region()或clloc_chrdev_region()
	if(major != 0)  //静态申请
	{
		ret=register_chrdev_region(MKDEV(major,minor),3,"myled");
		if(ret)
		{
			printk("申请静态设备号失败\n");
			goto out2;
		}
		printk("申请静态设备号成功major=%d\n",major);
	}
	else    //动态申请
	{
		ret=alloc_chrdev_region(&devno,minor,3,"myled");
		if(ret)
		{
			printk("申请动态设备号失败\n");
			goto out2;
		}
		major=MAJOR(devno);
		minor=MINOR(devno);
		printk("申请动态设备号成功major=%d\n",major);
	}

	//4.注册驱动对象 cdev_add()
	ret=cdev_add(cdev,MKDEV(major,minor),3);
	if(ret)
	{
		printk("注册驱动对象失败\n");
		goto out3;
	}
	printk("注册驱动对象成功\n");
	//5.向上提交目录 class_create()
	cls=class_create(THIS_MODULE,"myled");
	if(IS_ERR(cls))
	{
		printk("向上提交目录失败\n");
		ret = -PTR_ERR(cls);
		goto out4;
	}
	printk("向上提交目录成功\n");
	//6.向上提交设备信息 device_create()
	for(i=0;i<3;i++)
	{
		dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
		if(IS_ERR(dev))
		{
			printk("向上提交设备节点失败\n");
			ret = -PTR_ERR(dev);
			goto out5;
		}
	}
	printk("向上提交设备信息成功\n");
	// 根据设备树节点的路径解析设备树信息
	dnode1 = of_find_node_by_path("/leds");
	if (dnode1 == NULL)
	{
		printk("解析设备树节点led失败\n");
		return -EFAULT;
	}
	printk("解析设备树节点led成功\n");
	// 申请gpio_desc对象并设置输出为低电平
	gpiono1 = gpiod_get_from_of_node(dnode1, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);
	if (IS_ERR(gpiono1))
	{
		printk("申请gpio1对象失败\n");
		return -PTR_ERR(gpiono1);
	}
	printk("申请gpio1对象成功\n");
	gpiono2 = gpiod_get_from_of_node(dnode1, "led2-gpios", 0, GPIOD_OUT_LOW, NULL);
	if (IS_ERR(gpiono2))
	{
		printk("申请gpio2对象失败\n");
		return -PTR_ERR(gpiono2);
	}
	printk("申请gpio2对象成功\n");
	gpiono3 = gpiod_get_from_of_node(dnode1, "led3-gpios", 0, GPIOD_OUT_LOW, NULL);
	if (IS_ERR(gpiono3))
	{
		printk("申请gpio3对象失败\n");
		return -PTR_ERR(gpiono3);
	}
	printk("申请gpio3对象成功\n");

	// 根据设备树节点的路径解析设备树信息
	dnode2 = of_find_node_by_path("/myirq");
	if (dnode2 == NULL)
	{
		printk("解析设备树节点myirq失败\n");
		return -EFAULT;
	}
	printk("解析设备树节点myirq成功\n");
	for(i=0;i<3;i++)
	{
		//获取软中断号
		irqno[i]=irq_of_parse_and_map(dnode2,i);
		if(!irqno[i])
		{
			printk("软中断号irqno[%d]获取失败\n",i);
			return -ENXIO;
		}
		printk("软中断号获取成功irqno[%d]=%d\n",i,irqno[i]);

		//注册中断
		ret=request_irq(irqno[i],myirq_handler,IRQF_TRIGGER_FALLING,"key",(void *)i);
		if(ret)
		{
			printk("注册驱动失败\n");
			return ret;
		}
		printk("key%d中断注册成功\n",i);
	}
	return 0;
out5:
	for(--i;i>=0;i--)
	{
		//销毁上面提交的设备信息
		device_destroy(cls,MKDEV(major,i));
	}
	class_destroy(cls);
out4:
	cdev_del(cdev);
out3:
	unregister_chrdev_region(MKDEV(major,minor),3);
out2:
	kfree(cdev);
out1:
	return ret;
}
static void __exit mycdev_exit(void)
{
	// 灭灯
	gpiod_set_value(gpiono1, 0);
	gpiod_set_value(gpiono2, 0);
	gpiod_set_value(gpiono3, 0);
	// 释放gpio编号
	gpiod_put(gpiono1);
	gpiod_put(gpiono2);
	gpiod_put(gpiono3);
	//注销中断
	for(i=0;i<3;i++)
	{
		free_irq(irqno[i],NULL);
	}
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python-网络爬虫.BS4

BS4 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库&#xff0c; 它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方 式。 Beautiful Soup 4 官方文档&#xff1a;https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/ 帮助手册&…

devops(前端)

1.前言 前端的打包流程和后端的流程是一样的&#xff0c;只是打包的环境和制作的镜像有所不同&#xff0c;前端需要使用nodejs环境打包&#xff0c;镜像也是使用nginx镜像&#xff0c;因为用的是k8s的pod运行镜像&#xff0c;还需要使用configmap挂载nginx的配置&#xff0c;一…

CDH基于Kerberos开启身份验证实践总结

CDH基于Kerberos开启身份验证实践总结 前言简介Kerberos是什么Kerberos解决什么问题 Kerberos基本概念Kerberos认证流程Kerberos基本配置principalkeytabkrb5.confkdc.confkadm5.aclkerberos数据库 访问示例数据库访问信息 其他kerberos常用命令[Git Bash支持make命令](https:/…

【计算机网络】11、网络连通性:ping、traceroute、nslookup

文章目录 一、ping1.1 禁 ping 二、traceroute三、nslookup3.1 非交互模式3.2 交互模式 注意&#xff0c;测试网络连通性时&#xff0c;有的机器无法 ping 通&#xff0c;但可能 telnet 能通。不要因为无法 ping 通就放弃尝试。 一、ping 1.1 禁 ping 禁 ping 是通过忽略 IC…

SpringBoot 统⼀功能处理

目录 前言 1.⽤户登录权限效验 1.1、最初⽤户登录效验 1.2、Spring AOP ⽤户统⼀登录验证的问题 1.3、Spring 拦截器 了解 创建一个 Spring 拦截器 的流程 1、 创建自定义拦截器&#xff0c;实现 HandlerInterceptor 接⼝的preHandle&#xff08;执⾏具体⽅法之前的预处理…

day17 | 654.最大的二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

文章目录 一、最大的二叉树二、合并二叉树三、二叉搜索树中的搜索四、验证二叉搜索树 一、最大的二叉树 654.最大的二叉树 构建二叉树的题目&#xff0c;都用前序遍历。 因为我们一定要先构建根节点&#xff0c;才能继续向后构建。 递归函数的参数和返回值&#xff1a; Tree…

【MyBatis】MyBatis把空字符串转换成0的问题处理方案(96)

先看问题: Postman入参: MyBatis采用map循环插入: // Mapper接口层void addPar(Param(value "question") Map<String, Object> paramMap);<!-- 新增&#xff1a;参数 --><insert id"addPar" parameterType"map">INSERT IGNO…

小研究 - JVM 垃圾回收方式性能研究(一)

本文从几种JVM垃圾回收方式及原理出发&#xff0c;研究了在 SPEC jbb2015基准测试中不同垃圾回收方式对于JVM 性能的影响&#xff0c;并通过最终测试数据对比&#xff0c;给出了不同应用场景下如何选择垃圾回收策略的方法。 目录 1 引言 2 垃圾回收算法 2.1 标记清除法 2.2…

构建语言模型:BERT 分步实施指南

学习目标 了解 BERT 的架构和组件。了解 BERT 输入所需的预处理步骤以及如何处理不同的输入序列长度。获得使用 TensorFlow 或 PyTorch 等流行机器学习框架实施 BERT 的实践知识。了解如何针对特定下游任务(例如文本分类或命名实体识别)微调 BERT。为什么我们需要 BERT? 正…

使用docker部署Wordpress

文章目录 1.创建网络2.创建volume存储3.拉取镜像4.创建mysql容器mysql修改密码 5.创建wordpress容器6.访问localhost:80就可以直接使用啦 1.创建网络 docker network create --subnet172.18.0.0/24 pro-net2.创建volume存储 # mysql 存储 docker volume create volume_mysql…

怎么才能远程控制笔记本电脑?

为什么选择AnyViewer远程控制软件&#xff1f; 为什么AnyViewer是远程控制笔记本电脑软件的首选&#xff1f;以下是选择AnyViewer成为笔记本电脑远程控制软件的主要因素。 跨平台能力 AnyViewer作为一款跨平台远程控制软件&#xff0c;不仅可以用于从一台Windows电…

如何制作VR全景地图,VR全景地图可以用在哪些领域?

引言&#xff1a; 随着科技的迅速进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正逐渐渗透到各个领域。VR全景地图作为其中的重要应用之一&#xff0c;为人们提供了身临其境的全新体验。 一.什么是VR全景地图&#xff1f; VR全景地图是一种利用虚拟现实技术&…

PHP8的数据类型-PHP8知识详解

在PHP8中&#xff0c;变量不需要事先声明&#xff0c;赋值即声明。 不同的数据类型其实就是所储存数据的不同种类。在PHP8.0、8.1中都有所增加。以下是PHP8的15种数据类型&#xff1a; 1、字符串&#xff08;String&#xff09;&#xff1a;用于存储文本数据&#xff0c;可以使…

【LeetCode每日一题】——1572.矩阵对角线元素的和

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 矩阵 二【题目难度】 简单 三【题目编号】 1572.矩阵对角线元素的和 四【题目描述】 给你一…

HTML5网页设计小案例:网页导航栏的设计

什么是导航栏&#xff0c;按我的理解就是位于网页顶部或者侧边一组链接或者按钮&#xff0c;用来指导大家找到网页的不同板块&#xff0c;大家可以一目了然的找到自己想看的板块内容。今天我们设计一个位于网页顶部的的导航栏。按我的生活经验来说&#xff0c;网页的顶部导航栏…

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查

Django学习记录&#xff1a;使用ORM操作MySQL数据库并完成数据的增删改查 数据库操作 MySQL数据库pymysql Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。 安装第三方模块 pip install mysqlclientORM可以做的事&#xff1a; 1、创建、修改、删除数据库中的…

网络安全进阶学习第八课——信息收集

文章目录 一、什么是信息收集&#xff1f;二、信息收集的原则三、信息收集的分类1.主动信息收集2.被动信息收集 四、资产探测1、Whois查询#常用网站&#xff1a; 2、备案信息查询#常用网站&#xff1a; 3、DNS查询#常用网站&#xff1a; 4、子域名收集#常用网站&#xff1a;#常…

Linux编辑器 - vim使用

1.vim的基本概念 Vim是一个广泛使用的文本编辑器&#xff0c;它是在Unix和Linux系统中常用的命令行文本编辑器之一。 vim的主要三种模式 ( 其实有好多模式&#xff0c;目前掌握这 3 种即可 ), 分别是 命令模式 &#xff08; command mode &#xff09;、 插入模式 &#xff0…

html学习5(表单)

1、表单是一个包含表单元素的区域&#xff0c;用于收集用户的输入信息。 2、表单元素是允许用户在表单中输入内容&#xff0c;比如&#xff1a;文本域&#xff08;textarea&#xff09;、下拉列表&#xff08;select&#xff09;、单选框&#xff08;radio-buttons&#xff09…

MySQL篇

文章目录 一、MySQL-优化1、在MySQL中&#xff0c;如何定位慢查询?2、SQL语句执行很慢, 如何分析呢&#xff1f;3、了解过索引吗&#xff1f;&#xff08;什么是索引&#xff09;4、索引的底层数据结构了解过嘛 ?5、什么是聚簇索引什么是非聚簇索引 ?6、知道什么是回表查询嘛…
最新文章