基于ARM9的多行列键盘设计及其驱动实现
则下一按键将会被丢弃。应用程序则通过键盘的读函数read()从缓冲区的位置指针处起,读取所需个数的键码;完成读取操作后,还需将已被读取的键码从缓冲队列中删除,并更新缓冲区的位置指针。下面给出了本例中,实现的键盘读函数key_read()的伪代码:
ssize_t key_read(……)
{
定义并初始化变量;
if 缓冲区中可被读取的键码数大于0;
取得键码放置缓冲区的自旋锁;
计算此次读操作可读取的代码个数M(缓冲区中可读取的代码个数与程序要求个数之间的较小者);
从缓冲区位置指针开始,从缓冲区中拷贝M个的键码到用户空间缓冲区内;
更新缓冲区的位置指针和缓冲区中还剩余的键码个数;
释放自旋锁
返回此次读操作成功读取的代码个数。
Else
返回-1
}
3.3 键盘扫描程序
键盘的工作原理是通过键盘的行线和列线的状态来判断键盘中有无按键被按下。键盘扫描程序的功能就是用来判断处于按下状态的按键的具体位置及取得相应的键码值,因此扫描程序的设计是键盘驱动模块实现的核心。
键盘扫描程序的实现主要有两种,即轮询方式和中断方式[5]。在本例中,利用操作系统定时器队列与轮询扫描方式结合的方法对键盘的驱动程序进行了设计,主要是基于以下两个方面的原因。其一是AT91RM9200芯片的中断信号线是非常宝贵的硬件资源,每一组GPIO端口只配置了一根中断信号线,即32个GPIO端口共享一条信号线。这样若采用中断方式,则至少需要占用一条芯片中断信号线,对多行列的键盘,如果其所采用的GPIO端口不是来自于同一组时,就需要占用多条中断信号线。而且若其他设备使用的GPIO端口与键盘使用的GPIO口属于同一组,那么在两种设备的驱动程序设计中,必须进行中断共享,这样不仅使系统的软件设计更为复杂,且易产生中断丢失和中断竟态等问题,使设备性能受到影响。其二键盘是系统中属于一种相对低速的设备,采用轮询方式完全可以满足键盘的输入要求。
ARM-Linux操作系统提供了良好的定时器机制,因此通过简单定时器操作,就可以实现以固定间隔对键盘的状态进行扫描并对按键事件进程处理,固定间隔的大小可根据系统需求进行配置,定义器的详细操作可参见文献[1]。如前所述,键盘扫描程序的功能就是对键盘的状态进行判断和处理。若无按键按下,则扫描直接返回;若有按键按下,则对被按下键的位置进行判断,并将相应的键码值写入缓冲区中。因为本例中的键盘是为POS机配置,因此按键的准确性是至关重要,因此在扫描代码中对按键值进行了多次验证,下面是本例中使用的键盘扫描程序的伪代码:
int Scan_Keyboard()
{
定义并初始化变量;
取得键码放置缓冲区的自旋锁;
if 缓冲区中还有空;
① 依次判断各GPIO口的状态,若无低电平,则无键按下,直接退出if语句;否则,有键按下,且当前检验的GPIO口连接的行线即为按键所在的行;
② 给键盘列线连接的数据线依次送入高电平,再通过判断按键行线所在的GPIO端口的电平状态,得到按键所在的列;
延时一小段时间,以消除键盘抖动;
③ 再向给键盘列线连接的数据线全送低电平,使用代码段①再次判断是否有键按下,若有,则取得按键所在的行;
④ 同样使用代码段②重新判断按键所在的列;
⑤ 判断第一次得到的按键的行与列是否与第二次完全一样,若完全相同,则可进入下一步,否则退出if语句;
⑥ 重新向给键盘列线连接的数据线全送低电平,并判断按键是否弹起,若仍处于按下状态,则继续等待,否则根据行与列,转化为相应键值,并写入缓冲区;
if语句结束;
释放自旋锁;
函数返回 0;
}
完成驱动程序代码编写后,就可以将键盘的驱动程序加载到ARM-Linux内核中了,既可以采用静态加载方式,也可以采用动态方式进行加载。加载后,在应用程序中键盘的编程使用方式与其他字符设备一样。采用本文所述方式设计的键盘,目前已配置在笔者参与开发的POS机中交用户使用,据用户测试,键盘的输入准确率和反应时间都达到了设计要求。
4、结束语
本文以运行ARM-Linux的AT91RM9200系统为基础,提出了一种在ARM9上扩展特殊键盘的新设计方法,并对键盘扩展的硬件设计和驱动软件开发都作了详细说明。本设计方法利用数据锁存方式替代了常规的GPIO扩展,提高了系统硬件的资源利用率,这一思想也为在其他嵌入式设备扩展多行列键盘提供了一种新的设计思路。
键盘 AT91RM9200 驱动程序 ARM-Linux 相关文章:
- 单片机系统与标准PC键盘的接口模块设计(08-27)
- 柔性导电织物键盘设计(04-25)
- 矩阵键盘原理与结构(09-25)
- C51单片机矩阵键盘扫描去抖程序(09-25)
- 单片机4×4矩阵键盘设计方案(09-20)
- 基于Cortex-M0的USB密码键盘设计(04-24)