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

本文主要是介绍基于GPIO子系统编写LED驱动,编写应用程序进行测试,设置定时器,5秒钟打印一次hello world,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

设备树添加的代码

 myled{led-gpios=<&gpioe 10 0>, <&gpiof 10 0>, <&gpioe 8 0>;   };

头文件

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

驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include "head.h"//定义变量,字符设备驱动对象
struct cdev *cdev;
//定义变量,主设备号、次设备号、设备号
unsigned int major = 0;
unsigned int minor = 0;
dev_t devno;
//定义变量,向上提交目录信息返回值
struct class *cls;
//定义变量,向上提交设备节点信息返回值
struct device *dev;
//定义变量,解析设备节点信息
struct device_node *dnode;
//定义变量,保存GOIO的对象信息的结构体指针
struct gpio_desc *gpiono[3];
//定义变量,分配一个定时器对象
struct timer_list mytimer;int mycdev_open(struct inode *inode, struct file *file)
{int min = MINOR(inode->i_rdev);  //获取打开的文件的次设备号file->private_data = (void *)min;return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int which;which = (int)file->private_data;  //获取到文件的次设备号switch(which){case 0:switch(cmd){case LED_OFF:gpiod_set_value(gpiono[0], 0);break;case LED_ON:gpiod_set_value(gpiono[0], 1);break;}break;case 1:switch(cmd){case LED_OFF:gpiod_set_value(gpiono[1], 0);break;case LED_ON:gpiod_set_value(gpiono[1], 1);break;}break;case 2:switch(cmd){case LED_OFF:gpiod_set_value(gpiono[2], 0);break;case LED_ON:gpiod_set_value(gpiono[2], 1);break;}break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{return 0;
}
//操作方法结构体
struct file_operations fop ={.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};//声明注册驱动、创建设备文件的函数
int register_file(void);//GPIO子系统---led灯
int	gpio_led(void);//定时器处理函数
void timer_handel(struct timer_list *timer)
{printk("hello world\n");mod_timer(timer, jiffies+5*HZ);
}
//入口函数
static int __init mycdev_init(void)
{//调用注册驱动,创建设备文件register_file();//GPIO子系统---led灯gpio_led();//初始化定时器timer_setup(&mytimer, timer_handel, 0);mytimer.expires = jiffies+5*HZ;//注册定时器并启用add_timer(&mytimer);return 0;
}//出口函数
static void __exit mycdev_exit(void)
{//销毁设备节点int i;for(i=0; i<3;i++){device_destroy(cls, MKDEV(major, i));}//销毁目录信息class_destroy(cls);//分布注销驱动//1.注销字符设备驱动cdev_del(cdev);//2.释放设备号unregister_chrdev_region(MKDEV(major, minor), 3);//3.释放字符设备驱动对象空间kfree(cdev);//释放GPIO编号for(i=0; i<3; i++){gpiod_put(gpiono[i]);}//关闭定时器del_timer(&mytimer);
}//注册驱动,创建设备文件
int register_file(void)
{//1.申请字符设备驱动对象cdev = cdev_alloc();if(NULL == cdev){printk("申请字符设备驱动对象失败\n");goto out1;}printk("申请字符设备驱动对象成功\n");//2.初始化字符设备驱动对象cdev_init(cdev, &fop);//3.申请设备号if(0 == major){//动态申请字符设备int ret = alloc_chrdev_region(&devno, minor, 3, "mychrdev");if(ret){printk("动态申请设备号失败\n");goto out2;}major = MAJOR(devno);minor = MINOR(devno);printk("动态申请设备号成功\n");}else{//静态指定设备号int ret = register_chrdev_region(MKDEV(major, minor), 3, "mychrdev");if(ret){printk("静态指定设备号失败\n");goto out2;}printk("静态指定设备号成功\n");}//4.注册字符设备驱动对象int ret = cdev_add(cdev, MKDEV(major, minor), 3);if(ret){printk("注册字符设备驱动对象失败\n");goto out3;}printk("注册字符设备驱动对象成功\n");//5.向上提交目录信息cls = class_create(THIS_MODULE, "mychrdev");if(IS_ERR(cls)){printk("向上提交目录信息失败\n");goto out4;}printk("向上提交目录信息成功\n");//6.向上提交设备节点信息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");goto out5;}}printk("向上提交设备节点信息成功\n");return 0;out5://销毁设备节点for(;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 -1;
}//GPIO子系统---led灯
int gpio_led(void)
{//1.解析设备树节点信息dnode = of_find_node_by_path("/myled");if(NULL == dnode){printk("解析设备树节点信息失败\n");return dnode;}printk("解析设备树节点信息成功\n");//2.获取、申请GPIO编号和指定管脚输入输出方向int i;for(i=0; i<3; i++){gpiono[i] = gpiod_get_from_of_node(dnode, "led-gpios", i, GPIOD_OUT_LOW, NULL);if(IS_ERR(gpiono[i])){printk("申请GPIO编号失败\n");return -PTR_ERR(gpiono[i]);}}printk("申请GPIO编号成功\n");return 0;
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用程序代码

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "head.h"int main(int argc, const char *argv[])
{int fd1, fd2, fd3;int led_choose, on_off_choose;while(1){printf("请选择开启哪一盏灯(1 led1) (2 led2) (3 led3):");scanf("%d", &led_choose);printf("请选择关灯or开灯(0 off) (1 on):");scanf("%d", &on_off_choose);switch(led_choose){case 1:fd1 = open("/dev/myled0", O_RDWR);switch(on_off_choose){case 0:ioctl(fd1, LED_OFF);break;case 1:ioctl(fd1, LED_ON);break;}close(fd1);break;case 2:fd2 = open("/dev/myled1", O_RDWR);switch(on_off_choose){case 0:ioctl(fd2, LED_OFF);break;case 1:ioctl(fd2, LED_ON);break;}close(fd2);break;case 3:fd3 = open("/dev/myled2", O_RDWR);switch(on_off_choose){case 0:ioctl(fd3, LED_OFF);break;case 1:ioctl(fd3, LED_ON);break;}close(fd3);break;}}return 0;

这篇关于基于GPIO子系统编写LED驱动,编写应用程序进行测试,设置定时器,5秒钟打印一次hello world的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Python对PDF书签进行添加,修改提取和删除操作

《Python对PDF书签进行添加,修改提取和删除操作》PDF书签是PDF文件中的导航工具,通常包含一个标题和一个跳转位置,本教程将详细介绍如何使用Python对PDF文件中的书签进行操作... 目录简介使用工具python 向 PDF 添加书签添加书签添加嵌套书签Python 修改 PDF 书签Pytho

Java进行日期解析与格式化的实现代码

《Java进行日期解析与格式化的实现代码》使用Java搭配ApacheCommonsLang3和Natty库,可以实现灵活高效的日期解析与格式化,本文将通过相关示例为大家讲讲具体的实践操作,需要的可以... 目录一、背景二、依赖介绍1. Apache Commons Lang32. Natty三、核心实现代

如何在Ubuntu上安装NVIDIA显卡驱动? Ubuntu安装英伟达显卡驱动教程

《如何在Ubuntu上安装NVIDIA显卡驱动?Ubuntu安装英伟达显卡驱动教程》Windows系统不同,Linux系统通常不会自动安装专有显卡驱动,今天我们就来看看Ubuntu系统安装英伟达显卡... 对于使用NVIDIA显卡的Ubuntu用户来说,正确安装显卡驱动是获得最佳图形性能的关键。与Windo

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

Java使用Stream流的Lambda语法进行List转Map的操作方式

《Java使用Stream流的Lambda语法进行List转Map的操作方式》:本文主要介绍Java使用Stream流的Lambda语法进行List转Map的操作方式,具有很好的参考价值,希望对大... 目录背景Stream流的Lambda语法应用实例1、定义要操作的UserDto2、ListChina编程转成M

使用Java编写一个字符脱敏工具类

《使用Java编写一个字符脱敏工具类》这篇文章主要为大家详细介绍了如何使用Java编写一个字符脱敏工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、字符脱敏工具类2、测试工具类3、测试结果1、字符脱敏工具类import lombok.extern.slf4j.Slf4j

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too