资料介绍
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 按键电路的主要端口
管 脚端 口输入/输出管 脚端 口输入/输出
KEYSCAN0GPE11输出EINT0EINIT0/GPF0输入/输出
KEYSCAN1GPG6输出EINT2EINT2/GPF2输入/输出
KEYSCAN2GPE13输出EINT11EINT11/GPG3输入/输出
KEYSCAN3GPG2输出EINT19EINT19/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 */
……
typedef struct _st_key_info_matrix /* 按键数据结构 */
{
unsigned char key_id; /* 按键ID */
unsigned int irq_no; /* 对应的中断号 */
unsigned int irq_gpio_port; /* 对应的中断线的输入端口地址*/
unsigned int kscan_gpio_port; /* 对应的KSCAN端口地址 */
} st_key_info_matrix;
typedef struct _st_key_buffer /* 按键缓冲数据结构 */
{
unsigned long jiffy[MAX_KEY_COUNT]; /* 按键时间, 5s以前的铵键作废*/
unsigned char buf[MAX_KEY_COUNT]; /* 按键缓冲区 */
unsigned int head,tail; /* 按键缓冲区头和尾 */
} st_key_buffer;
……
下面是矩阵按键数组的定义,数组元素的信息(一个按键信息)按照0行0列,0行1列,…,3行2列,3行3列的顺序逐行排列。
static st_key_info_matrix key_info_matrix[MAX_COLUMN][MAX_ROW] =
{
{{10, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11}, /* 0行0列 */
{11, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6},
{12, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13},
{16, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2}},
{{7, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11}, /* 1行0列 */
{8, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6},
{9, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13},
{15, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2}},
{{4, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11}, /* 2行0列 */
{5, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6},
{6, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13},
{14, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2}},
{{1, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11}, /* 3行0列 */
{2, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6},
{3, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13},
{13, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2}},
};
下面是与按键相关的端口的初始化函数。这些函数已经在简单的GPIO字符设备驱动程序里被使用过。此外,set_irq_type()函数用于设定中断线的类型,在本实例中通过该函数将4个中断线的类型配置为下降沿触发式。
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 按键电路的主要端口
管 脚端 口输入/输出管 脚端 口输入/输出
KEYSCAN0GPE11输出EINT0EINIT0/GPF0输入/输出
KEYSCAN1GPG6输出EINT2EINT2/GPF2输入/输出
KEYSCAN2GPE13输出EINT11EINT11/GPG3输入/输出
KEYSCAN3GPG2输出EINT19EINT19/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 */
……
typedef struct _st_key_info_matrix /* 按键数据结构 */
{
unsigned char key_id; /* 按键ID */
unsigned int irq_no; /* 对应的中断号 */
unsigned int irq_gpio_port; /* 对应的中断线的输入端口地址*/
unsigned int kscan_gpio_port; /* 对应的KSCAN端口地址 */
} st_key_info_matrix;
typedef struct _st_key_buffer /* 按键缓冲数据结构 */
{
unsigned long jiffy[MAX_KEY_COUNT]; /* 按键时间, 5s以前的铵键作废*/
unsigned char buf[MAX_KEY_COUNT]; /* 按键缓冲区 */
unsigned int head,tail; /* 按键缓冲区头和尾 */
} st_key_buffer;
……
下面是矩阵按键数组的定义,数组元素的信息(一个按键信息)按照0行0列,0行1列,…,3行2列,3行3列的顺序逐行排列。
static st_key_info_matrix key_info_matrix[MAX_COLUMN][MAX_ROW] =
{
{{10, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11}, /* 0行0列 */
{11, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6},
{12, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13},
{16, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2}},
{{7, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11}, /* 1行0列 */
{8, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6},
{9, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13},
{15, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2}},
{{4, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11}, /* 2行0列 */
{5, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6},
{6, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13},
{14, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2}},
{{1, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11}, /* 3行0列 */
{2, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6},
{3, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13},
{13, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2}},
};
下面是与按键相关的端口的初始化函数。这些函数已经在简单的GPIO字符设备驱动程序里被使用过。此外,set_irq_type()函数用于设定中断线的类型,在本实例中通过该函数将4个中断线的类型配置为下降沿触发式。
下载该资料的人也在下载
下载该资料的人还在阅读
更多 >
- 细说嵌入式驱动程序设计
- 嵌入式Linux驱动程序开发
- 基于嵌入式Linux的人机交互接口设备驱动程序的研究和实现
- 嵌入式Linux系统的驱动原理和使用ARM Linux实现SPI驱动程序的说明 11次下载
- 嵌入式Linux设备驱动程序开发基础知识总结免费下载 13次下载
- 嵌入式Linux的中断驱动程序设计 3次下载
- 嵌入式Linux下的LCD驱动程序设计方案解析 0次下载
- 嵌入式Linux字符设备驱动的设计与应用
- 嵌入式Linux字符设备驱动的设计与应用
- 基于嵌入式Linux的步进电机驱动程序设计
- 基于嵌入式LINUX下CAN设备驱动程序设计
- 嵌入式Linux网络驱动程序的开发及实现原理
- 嵌入式USB从设备驱动程序设计
- 嵌入式通信设备驱动程序设计标准化
- 嵌入式Linux设备驱动开发
- 如何写一个Linux设备驱动程序 4314次阅读
- 设计嵌入式驱动程序有什么窍门 2508次阅读
- 设计嵌入式驱动程序有哪些小窍门 2553次阅读
- 米尔科技LINUX设备驱动程序教程 1965次阅读
- 嵌入式Linux内核的驱动程序开发是怎样的 1415次阅读
- 基于PXA255开发板外围字符设备的嵌入式Linux字符设备驱动设计与应用 1138次阅读
- 基于嵌入式Linux下的I2C设备驱动的总体思路与框架设计 3671次阅读
- 基于嵌入式Linux内核的系统设备驱动程序开发设计 1113次阅读
- 嵌入式系统开发中驱动程序设计的5个方法盘点 3057次阅读
- 可动态安装的Linux设备驱动程序 957次阅读
- 基于嵌入式Linux的无线视频监控系统设计 3004次阅读
- 嵌入式驱动的构造分析总结 4503次阅读
- 基于FPGA嵌入式系统的设备驱动开发 2259次阅读
- Xilinx设备的驱动程序 7967次阅读
- PCI驱动程序开发实例 6701次阅读
下载排行
本周
- 1TPS54202H降压转换器评估模块用户指南
- 1.02MB | 7次下载 | 免费
- 2华瑞昇CR215芯片数字万用表原理图
- 0.21 MB | 1次下载 | 3 积分
- 3SMD LED选型目录 灯珠手册
- 5.36 MB | 1次下载 | 免费
- 4Tiva C系列DK-TM4C129X入门指南
- 1.69MB | 1次下载 | 免费
- 5电涌保护器(SPD)的选择、安装以及装配
- 4.57 MB | 1次下载 | 免费
- 6时源芯微EMC前车灯案例
- 458.59 KB | 1次下载 | 免费
- 7bq25890、bq25892双级联充电器EVM(PWR692)用户指南
- 2.02MB | 1次下载 | 免费
- 8TPS54426降压转换器评估模块用户指南
- 847.7KB | 次下载 | 免费
本月
- 1ADI高性能电源管理解决方案
- 2.43 MB | 156次下载 | 免费
- 22024PMIC市场洞察
- 2.23 MB | 63次下载 | 免费
- 3开关电源设计原理手册
- 1.83 MB | 30次下载 | 免费
- 4智能门锁原理图
- 0.39 MB | 28次下载 | 免费
- 5OAH0428最新规格书(中文)
- 2.52 MB | 15次下载 | 7 积分
- 6ST7789V2单芯片控制器/驱动器英文手册
- 3.07 MB | 9次下载 | 1 积分
- 7LTH7充电电路和锂电池升压5V输出电路原理图
- 0.04 MB | 7次下载 | 免费
- 8TPS54202H降压转换器评估模块用户指南
- 1.02MB | 7次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935119次下载 | 10 积分
- 2开源硬件-PMP21529.1-4 开关降压/升压双向直流/直流转换器 PCB layout 设计
- 1.48MB | 420061次下载 | 10 积分
- 3Altium DXP2002下载入口
- 未知 | 233084次下载 | 10 积分
- 4电路仿真软件multisim 10.0免费下载
- 340992 | 191367次下载 | 10 积分
- 5十天学会AVR单片机与C语言视频教程 下载
- 158M | 183334次下载 | 10 积分
- 6labview8.5下载
- 未知 | 81581次下载 | 10 积分
- 7Keil工具MDK-Arm免费下载
- 0.02 MB | 73807次下载 | 10 积分
- 8LabVIEW 8.6下载
- 未知 | 65987次下载 | 10 积分
评论
查看更多