博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Tiny4412的Linux按键输入子系统驱动的实现(二)
阅读量:4195 次
发布时间:2019-05-26

本文共 4190 字,大约阅读时间需要 13 分钟。

本文的主要内容

一、内核定时器

二、按键输入子系统驱动程序的改进

一、内核定时器

1、内核定时器,

在Linux设备驱动编程中,可以利用内核定时器来完成定时触发工作或周期性的任务。

        2、内核定时器的一般使用步骤

a、定义、初始化定时器

b、设置定时器:比如超时处理函数,超时时间

c、将定时器加入到内核的定时器链表当中

d、编写定时器超时处理函数以及修改定时器的超时时间

二、按键输入子系统的改进

1、上一节按键输入子系统驱动的缺点

在Tiny4412开发板上的按键是传统的机械按键,机械按键在按下和松开的时候会用抖动(也就是常说的毛刺),这就有可能导致按键的灵敏度下降甚至失灵。通过定时器在按键按下和松开的瞬时进行一定的延时将有助于对抖动的消除,可以有效的对按键进行消抖。

2、添加定时器相关的代码

2.1 定义一个定时器的结构体

static struct timer_list buttons_timer;
2.2 初始化、设置、注册这个定时器

init_timer(&buttons_timer);	buttons_timer.function = yl_buttons_timer_function;	add_timer(&buttons_timer);
2.3 按键中断程序

通过在按键中断程序当中来修改定时器的超时时间来对按键进行消抖,代码如下:

/* 按键中断处理程序 */static irqreturn_t yl_buttons_irq(int irq, void *devid){	gl_buttons_desc = (struct yl_buttons_desc *)devid;	/* 修改定时器的时间,向后延时10ms */	mod_timer(&buttons_timer, jiffies + HZ/100);	return IRQ_HANDLED;}
2.4 定时器超时处理函数

通过对定时器超时处理函数来判断按键是按下还是松开,上报事件和同步事件。

/* 定时器超时处理函数 */static void yl_buttons_timer_function(unsigned long arg){	struct yl_buttons_desc *buttons_desc = gl_buttons_desc;	int pinval = gpio_get_value(buttons_desc->gpio);	if(pinval == 1)	/* 判断按键是按下还是松开 */	{		/* 松开 */		input_event(buttons_dev, EV_KEY, buttons_desc->key_code, 0);		input_sync(buttons_dev);	}	else	{		/* 按下 */		input_event(buttons_dev, EV_KEY, buttons_desc->key_code, 1);		input_sync(buttons_dev);	}}
附录:本文所实现的按键输入子系统的完整代码如下所示.

/* 包含的头文件 */#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* 输入子系统需要的头文件 */#include
/** 按键映射: * XEINT26 ---- GPX3_2 * XEINT27 ---- GPX3_3 * XEINT28 ---- GPX3_4 * XEINT29 ---- GPX3_5 *//* 定义一个结构体用来对输入按键进行描述 */struct yl_buttons_desc{ int gpio; // 表示对于的按键的引脚 char *name; // 表示对应的按键请求中断时的中断名 int key_code; // 表示按键在输入子系统中对应的键值};/* 定义一个描述按键的数组 */static struct yl_buttons_desc buttons_desc[] = { {EXYNOS4_GPX3(2), "yl_buttons_L", KEY_L}, {EXYNOS4_GPX3(3), "yl_buttons_S", KEY_S}, {EXYNOS4_GPX3(4), "yl_buttons_ENTER", KEY_ENTER}, {EXYNOS4_GPX3(5), "yl_buttons_LEFTSHIFT", KEY_LEFTSHIFT},};static struct input_dev *buttons_dev; /* 定义一个输入子系统的结构体指针变量 */static struct timer_list buttons_timer; /* 定义一个定时器的结构体指针变量 */static struct yl_buttons_desc *gl_buttons_desc;/* 按键中断处理程序 */static irqreturn_t yl_buttons_irq(int irq, void *devid){ gl_buttons_desc = (struct yl_buttons_desc *)devid; /* 修改定时器的时间,向后延时10ms */ mod_timer(&buttons_timer, jiffies + HZ/100); return IRQ_HANDLED;}/* 定时器超时处理函数 */static void yl_buttons_timer_function(unsigned long arg){ struct yl_buttons_desc *buttons_desc = gl_buttons_desc; int pinval = gpio_get_value(buttons_desc->gpio); if(pinval == 1) /* 判断按键是按下还是松开 */ { /* 松开 */ input_event(buttons_dev, EV_KEY, buttons_desc->key_code, 0); input_sync(buttons_dev); } else { /* 按下 */ input_event(buttons_dev, EV_KEY, buttons_desc->key_code, 1); input_sync(buttons_dev); }}/* 入口函数 */static int __init yl_buttons_init(void){ int irq; int i; /* 1、分配一个input_dev结构体 */ buttons_dev = input_allocate_device(); if(!buttons_dev) { printk("input_allocate_device error!\n"); return -ENOMEM; } /* 2、设置input_dev结构体 */ /* 2.1、支持哪类事件 */ set_bit(EV_KEY, buttons_dev->evbit); set_bit(EV_REP, buttons_dev->evbit); /* 2.2、支持该类事件中的那些事件 */ for(i = 0; i < sizeof(buttons_desc)/sizeof(buttons_desc[0]); i++) { set_bit(buttons_desc[i].key_code, buttons_dev->keybit); } /* 3、注册input_dev结构体 */ input_register_device(buttons_dev); /* 4、中断相关的操作 */ for(i = 0; i < sizeof(buttons_desc)/sizeof(buttons_desc[0]); i++) { irq = gpio_to_irq(buttons_desc[i].gpio); request_irq(irq, yl_buttons_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, buttons_desc[i].name, (void*)&buttons_desc[i]); } /* 5、定时器相关的操作 */ init_timer(&buttons_timer); buttons_timer.function = yl_buttons_timer_function; add_timer(&buttons_timer); return 0;}/* 出口函数 */static void __exit yl_buttons_exit(void){ int irq; int i; del_timer(&buttons_timer); for(i = 0; i < sizeof(buttons_desc)/sizeof(buttons_desc[0]); i++) { irq = gpio_to_irq(buttons_desc[i].gpio); free_irq(irq, (void*)&buttons_desc[i]); } input_unregister_device(buttons_dev); input_free_device(buttons_dev);}module_init(yl_buttons_init);module_exit(yl_buttons_exit);MODULE_LICENSE("GPL");

转载地址:http://wagoi.baihongyu.com/

你可能感兴趣的文章
【JAVA-SE】流程控制语句
查看>>
【JAVA-SE】面向对象
查看>>
【JAVA-SE】数组与集合
查看>>
【JAVA-WEB】HTML
查看>>
【JAVA-WEB】CSS
查看>>
【JAVA-WEB】JavaScript
查看>>
【JAVA-WEB】JDBC
查看>>
【JAVA-WEB】JSON
查看>>
FFMPEG使用NVIDIA的GPU硬件转码
查看>>
MacOS 查看动态库链接
查看>>
ffplay 播放 raw 数据
查看>>
linux下使用ffmpeg录屏
查看>>
判断是否工作在docker环境
查看>>
Requested operation is not valid: network 'default' is not active
查看>>
Centos作为host主机部署kvm虚拟化平台
查看>>
Debian9作为host主机部署kvm虚拟化平台
查看>>
nginx四层网络代理实现
查看>>
MacOS命令行运行Chrome
查看>>
python获取当前计算机cpu数量
查看>>
ffmpeg vsync参数分析
查看>>