嵌入式Linux设备驱动开发之:按键驱动程序实例
11.6按键驱动程序实例
11.6.1按键工作原理
LED和蜂鸣器是最简单的GPIO的应用,都不需要任何外部输入或控制。按键同样使用GPIO接口,但按键本身需要外部的输入,即在驱动程序中要处理外部中断。按键硬件驱动原理图如图11-7所示。在图11-7的4×4矩阵按键(K1~K16)电路中,使用4个输入/输出端口(EINT0、EINT2、EINT11和EINT19)和4个输出端口(KSCAN0~KSCAN3)。
图11.7按键驱动电路原理图
按键驱动电路使用的端口和对应的寄存器如表11-18所示。
表11.18 按键电路的主要端口
管脚 | 端口 | 输入/输出 | 管脚 | 端口 | 输入/输出 | |
KEYSCAN0 | GPE11 | 输出 | EINT0 | EINIT0/GPF0 | 输入/输出 | |
KEYSCAN1 | GPG6 | 输出 | EINT2 | EINT2/GPF2 | 输入/输出 | |
KEYSCAN2 | GPE13 | 输出 | EINT11 | EINT11/GPG3 | 输入/输出 | |
KEYSCAN3 | GPG2 | 输出 | EINT19 | EINT19/GPG11 | 输入/输出 |
因为通常中断端口是比较珍贵且有限的资源,所以在本电路设计中,16个按键复用了4个中断线。那怎么样才能及时而准确地对矩阵按键进行扫描呢?
某个中断的产生表示,与它所对应的矩阵行的4个按键中,至少有一个按键被按住了。因此可以通过查看产生了哪个中断,来确定在矩阵的哪一行中发生了按键操作(按住或释放)。例如,如果产生了外部2号线中断(EINT2变为低电平),则表示K7、K8、K9和K15中至少有一个按键被按住了。这时候4个EINT端口应该通过GPIO配置寄存器被设置为外部中断端口,而且4个KSCAN端口的输出必须为低电平。
在确定按键操作所在行的位置之后,我们还得查看按键操作所在列的位置。此时要使用KSCAN端口组,同时将4个EINT端口配置为通用输入端口(而不是中断端口)。在4个KSCAN端口中,轮流将其中某一个端口的输出置为低电平,其他3个端口的输出置为高电平。这样逐列进行扫描,直到按键所在列的KSCAN端口输出为低电平,此时按键操作所在行的EINT管脚的输入端口的值会变成低电平。例如,在确认产生了外部2号中断之后,进行逐列扫描。若发现在KSCAN1为低电平时(其他端口输出均为高电平),GPF2(EINT2管脚的输入端口)变为低电平,则可以断定按键K8被按住了。
以上的讨论都是在按键的理想状态下进行的,但实际的按键动作会在短时间(几毫秒至几十毫秒)内产生信号抖动。例如,当按键被按下时,其动作就像弹簧的若干次往复运动,将产生几个脉冲信号。一次按键操作将会产生若干次按键中断,从而会产生抖动现象。因此驱动程序中必须要解决去除抖动所产生的毛刺信号的问题。
11.6.2按键驱动程序
首先按键设备相关的数据结构的定义如下所示:
/*butt_drv.h*/
……
typedefstruct_st_key_info_matrix/*按键数据结构*/
{
unsignedcharkey_id;/*按键ID*/
unsignedintirq_no;/*对应的中断号*/
unsignedintirq_gpio_port;/*对应的中断线的输入端口地址*/
unsignedintkscan_gpio_port;/*对应的KSCAN端口地址*/
}st_key_info_matrix;
typedefstruct_st_key_buffer/*按键缓冲数据结构*/
{
unsignedlongjiffy[MAX_KEY_COUNT];/*按键时间,5s以前的铵键作废*/
unsignedcharbuf[MAX_KEY_COUNT];/*按键缓冲区*/
unsignedinthead,tail;/*按键缓冲区头和尾*/
}st_key_buffer;
……
linux操作系统文章专题:linux操作系统详解(linux不再难懂)linux相关文章:linux教程
蜂鸣器相关文章:蜂鸣器原理
评论