本文共 7674 字,大约阅读时间需要 25 分钟。
程序可以分成两部分来看:
第一部分:按键侦测,主要包括中断的初始化、中断处理、按键去抖、等待按键松开,侦测
完成返回按键键值。
第二部分:按键事件处理,主要包括,将案件事件保存至循环链表(其实就是一个数组,可
以循环保存数据)、将案件事件反馈给应用程序(Read函数)。
其中涉及到的数据结构有以下几个:
第一个数据结构:设备驱动结构
struct KEY_DEV
{
};
所以这个结构体里面各个变量分工是这样的:
unsigned int tkeystatus[KEY_NUM]:
当有中断触发的时候,先在tkeystatus[KEY_NUM]这里的对应位置记为
“待定(KEYSTATUS_X)”,当延时20ms后如果通过读IO口的方式发现该端口仍然处于低电平,那么就认为确实有按下这个按键,那么在tkeystatus[KEY_NUM]这里的对应位置记为“按下(KEYSTATUS_DOWN)”
unsigned char tbuf[MAX_KEY_BUF]:
按键缓冲区,当确认某一个按键被按下后,将按键编号(看你喜欢怎么标识某一个按键啦,随便定义,只要能区分就行了)记录在这里。
unsigned int head,tail;
指向缓冲区里面数据的头尾,比如:
当Read函数来读数据的时候就判断Head和Tail是不是指向同一个地方,如果指向同一个地方就表示无数据可读,反之,则把数据读出。
Wq:
等待队列,当应用程序的Read采用阻塞方式读取的时候,如果当前没按键按下,那么就不能让Read函数返回,所以就用一个等待队列把Read函数挂起来(Read函数),当有数据可读的时候再把队列上的Read函数唤醒(keyEvent函数)。
第二个数据结构:
static struct timer_list g_tkey_timer[KEY_NUM]; //6个按键去抖计时器
主要用于计时函数,比如去抖、等待按键松开等。
第三个数据结构:
struct KEY_INFO
{
};
很简单明了的结构体,一看就知道啦,所以不多说咯!
下面开始讲程序架构
第一部分:按键侦测。
1、
本程序所有按键都是采用中断低电平触发方式。
第二部分:按键事件处理
主要负责按键记录以及与应用层沟通,当应用层调用Read函数的时候,如果在缓冲区有数据则马上反馈,如果无数据则判断应用层是否用阻塞方式读取,如果阻塞方式读取则将Read函数挂起,否则返回。
涉及函数一:keyEvent()记录按键事件到缓冲区。
涉及函数二:key_read()很明白啦…^_^
完整驱动代码:
|