位,并将相关消抖动的和连击时间的宏定义改小即可。然后在主程序类似下面这样写即可 if( KeyTime ) //定时扫描时间到 {
KeyValue = u8_ReadKey_f() ; }
具体的工作就交给您去完成啦。
看看效果: 按键单击
连发时候的截图
至此,关于单个按键的学习就告一段落了,您是否已经明白了。如果您还不明白,那么把这个程序好好的看看,并画下流程图,分析分析。估计您就会恍然大悟。关键是思路要转换过来。 下面我们来看看多个按键的情况吧
一般情况下,如果多个按键每个都直接接在单片机的I/O上的话会占用很多的I/O资源。比较合理的一种
做法是,按照行列接成矩阵的形式。按键接在每一个的行列的相交处。这样对于m行n列的矩阵,可以接的按键总数是m*n。这里我们以常见的4*4矩阵键盘来讲解矩阵键盘的编程。
上图就是矩阵键盘的一般接法。
这里我们要介绍一种快速的键盘扫描法:线反转法(或者称为行列翻转法)。具体流程如下。首先,让单片机的行全部输出0,列全部输出1,读取列的值(假设行接P3口的高四位,列接低四位)。即P3= 0x0f ; 此时读列的值,如果有键按下,则相应的列读回来的值应该为低。譬如此时读回来的值为 0x0e ; 即按键列的位置已经确定。这时反过来,把行作为输入,列作为输出,即P0 = 0xf0 ;此时再读行的值,如果按键仍然被按下,则相应的行的值应该为低,如果此时读回来的值为0xe0,则确定了行的位置 。说到这里,您应该笑了,知道了一个按键被按下的行和列的位置,那么就可以肯定确定它的位置了。我们把读回来的行值和列值进行或运算。即 0xe0 | 0x 0e 即 0xee。那么0xee就是我们按下的按键的键值了。怎么样。只需几步就可以判断所有的键值,简单吧。下面再结合一个例子具体看看。 /****************************************** * 此模块所需相关支持库 *
******************************************/ #include\
#define uint8 unsigned char #define uint16 unsigned int
/**************************************** * 与硬件连接相关的定义及宏定义和操作宏 *
*****************************************/
#define KEYBOARD P3 //键盘连接到单片机上的端口位置
#define READ_ROW_ENLABLE KEYBOARD = 0x0f ; //读端口之前先把相应口置位(由基本51单片机特性决定的)
#define READ_COL_ENLABLE KEYBOARD = 0xf0 ; // 根据实际硬件连接情况修改
/***************************************** * 模块内相关的宏定义及常数宏 *
******************************************/ #define NOKEY 0xff //定义无键按下时的返回值 #define DELAY_COUNT 2 //消抖时间常数
/***************************************** * 此模块所需的全局或者外部变量 *
*****************************************/ bit bdata StartScan = 0 ;//此变量需放在定时中断中置位
/***************************************** * 按键扫描函数,按下去后经去抖,确定按下 * * 则返回键值0~15;无键按下则返回0xff ; * * 此函数需要定时器的支持(去抖....) *
*****************************************/ uint8 u8_KeyBoardScan_f() {
static uint8 DelayCount = 0 ; uint8 KeyValueRow = 0 ; uint8 KeyValueCol = 0 ; uint8 KeyValue = 0 ;
if( StartScan ) //开始扫描,StartScan在定时中断中置位 {
StartScan = 0 ; //清除开始扫描标志位,避免多次重复执行扫描程序 //读入按键状态前先向相应端口写1(由基本51单片机硬件结构决定) READ_ROW_ENLABLE
if( ( KEYBOARD & 0x0f ) != 0x0f ) //判断是否有键按下 {
DelayCount++;
if( DelayCount <= DELAY_COUNT ) //有键按下则判断延时去抖的时间是否达到
{
return NOKEY ; }
else //消除了抖动 {
if( ( KEYBOARD & 0x0f ) != 0x0f ) //再次判断是否按键真的按下 {
DelayCount = 0 ; //确定按下后,延时去抖计时器清0 KeyValueRow = KEYBOARD & 0x0f ; //取得行码
//准备读列,先向相应端口写1(由基本51单片机硬件结构决定)
READ_COL_ENLABLE
if ( (KEYBOARD & 0xf0) != 0xf0 ) //反转,读列码 {
KeyValueCol = KEYBOARD & 0xf0 ; //取得列码
//合并取得的行码和列码,即是相应按键的键值 switch( KeyValueCol | KeyValueRow) {
case 0x77 : KeyValue = 0 ; break ; case 0xb7 : KeyValue = 1 ; break ; case 0xd7 : KeyValue = 2 ; break ; case 0xe7 : KeyValue = 3 ; break ; case 0x7b : KeyValue = 4 ; break ; case 0xbb : KeyValue = 5 ; break ; case 0xdb : KeyValue = 6 ; break ; case 0xeb : KeyValue = 7 ; break ; case 0x7d : KeyValue = 8 ; break ; case 0xbd : KeyValue = 9 ; break ; case 0xdd : KeyValue = 10 ;break ; case 0xed : KeyValue = 11 ;break ; case 0x7e : KeyValue = 12 ;break ; case 0xbe : KeyValue = 13 ;break ; case 0xde : KeyValue = 14 ;break ; case 0xee : KeyValue = 15 ;break ; default : return NOKEY ; }
return KeyValue ;
相关推荐: