1、该段程序是4*4键盘扫描程序,功能比较全,根据实际情况可在次基础上进行修改;
2、已调试通过,但没有优化;
/*********************************************************************
文件:scankey.c
用途:通用4*4按键接口驱动程序
注意:
创建:2008.5.15
修改:2008.5.15
设计:raosibin
版本:ver1.3
功能说明:每隔10MS调用一次 ,实现了组合按键功能;连_发功能
**********************************************************************/
#include "..\config.h"
/*********************************************************************
COL0 COL1 COL2 COL3
* ROW4 0 1 2 3
* ROW5 4 5 6 7
* ROW6 8 9 A B
* ROW7 C D E F
*
* 普通按键:
* 2~E:数字按键
*
* 连_发按键:
* 0:
* 1:
*
* 组合按键
* F : 引导键
* F+0:
* F+1:
* 状态机思路
* F为组合引导键
* 每10MS扫描一次键盘
* 状态0:检测是否有键按下;
* 状态1:消抖处理
* 状态2:确认按键,同状态1比较,除F引导键外相同则返回键值,
* F引导键未按下转状态3;F引导键按下转状态5;
* 状态3:计数1,(按3S,连_发判断);
* 状态4:计数2,连_发功能
* 状态5:500MS内检测是否有F引导键+其他键按下;有转状态6,没有转状态8
* 状态6:消抖处理
* 状态7:同状态6比较,确认组合按键,返回组合键值,转状态3
* 状态8:消抖处理
* 状态9:先导键为单按键,返键值,转状态3.
**********************************************************************/
//按键初始化
void key_board_int1(void)
{
KEY_DDR_ROW |= KEY_ROW_ALL; //行输出,
KEY_PORT_ROW &=~ KEY_ROW_ALL;
KEY_DDR_COL &=~ KEY_COL_ALL; //列输入,并使能内部上拉
KEY_PORT_COL |= KEY_COL_ALL;
}
void key_board_int2(void) //翻转初始化
{
KEY_DDR_ROW &=~ KEY_ROW_ALL; //行输入,并使能内部上拉
KEY_PORT_ROW |= KEY_ROW_ALL;
KEY_DDR_COL |= KEY_COL_ALL; //列输出;
KEY_PORT_COL &=~ KEY_COL_ALL;
}
unsigned char key_board_scan(void)
{
unsigned key_value_buf;
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
key_board_int2(); // 翻转扫描
KEY_PORT_COL &=~ KEY_COL_ALL;
key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW; // 读行电平,并同翻转前的结果或
return key_value_buf;
}
char read_keyboard()
{
static char key_state = 0, key_value1,key_value2,key_value3,key_value4,key_value5;
static char key_value6,key_value7,key_value8,key_value9;
static unsigned int key_time = 0;
char key_return = No_key;
switch (key_state)
{
case 0: // 判断是否有键按下
if (key_board_scan() != No_key)
{
key_state = 1; // 有按键
break; // 转消抖确认状态
}
break;
case 1: // 消抖处理
if (++key_time >= 1) // 改变判断条件可改变键盘灵敏度
{
key_value1 = key_board_scan();
if (key_value1 != No_key)
{
key_state = 2;
break;
}
key_state = 0;
break;
}
break;
case 2: // 确认按键,同状态1比较
key_value2 = key_board_scan();
if (key_value2 == key_value1) // 再次扫描,
{
if (key_value2 != 0b01110111) // 是否为引导键F,是则转状态5
{
switch (key_value2) // 与状态1的相同,确认按键
{ // 键盘编码,返回编码值
case 0b11101110:
key_return = K1_1; // 0;
break;
case 0b11101101:
key_return = K1_2; // 1
break;
case 0b11101011:
key_return = K1_3;
break;
case 0b11100111:
key_return = K1_4;
break;
case 0b11011110:
key_return = K2_1;
break;
case 0b11011101:
key_return = K2_2;
break;
case 0b11011011:
key_return = K2_3;
break;
case 0b11010111:
key_return = K2_4;
break;
case 0b10111110:
key_return = K3_1;
break;
case 0b10111101:
key_return = K3_2;
break;
case 0b10111011:
key_return = K3_3;
break;
case 0b10110111:
key_return = K3_4;
break;
case 0b01111110:
key_return = K4_1;
break;
case 0b01111101:
key_return = K4_2;
break;
case 0b01111011:
key_return = K4_3;
break;
default:
break;
}
key_state = 3; // 转入等待按键释放状态
key_time = 0; // 清0按键时间计数器
break;
}
else
{
key_state = 5;
key_time = 0;
break;
}
}
else
key_state = 0; // 两次列电平不同返回状态0,(消抖处理)
break;
case 3: // 计数1,(按3S,连_发判断)
key_value3 = key_board_scan();
if ( key_value3 == No_key)
key_state=0; // 按键已释放,转换到按键初始态
else if ((key_value3 == 0b11100111)||(key_value3 == 0b11011110)) // 改变此判断条件,可以确定
{ // 哪些键具备加速功能,3,4加速
if (++key_time >= 300) // 按键时间计数
{
key_state = 4; // 按下时间>3s,状态转换到计时2
key_time = 0; // 清按键计数器
key_return = KJ; // 输出“18”
}
break;
}
break;
case 4: // 计数2,连_发功能
key_value4 = key_board_scan();
if ( key_value4 == No_key)
key_state=0; // 按键已释放,转换到按键初始态
else if (++key_time >= 20) // 按键时间计数
{
key_time = 0; // 清按键计数器
key_return = KJ; // 输出“18”
break;
}
break;
case 5: // 检测是否有F引导键+其他键按下;有转状态6,没有转状态8
key_value5 = key_board_scan();
if (key_value5 == key_value2)
{
if (++key_time >= 50) // 500MS到了吗?未到,状态5,不断扫描,到了,状态8
{
key_state = 8;
key_time = 0;
break;
}
break;
}
else
{
key_state = 6;
break;
}
break;
case 6: // 消抖处理
key_value6 = key_board_scan();
key_state = 7;
break;
case 7: // 同状态6比较,确认组合按键,返回组合键值,转状态3
key_value7 = key_board_scan();
if (key_value7 == key_value6)
{
switch (key_value7)
{
case 0b01100110:
key_return = KF_0; // 组合按键F+0
break;
case 0b01100101:
key_return = KF_1; // 组合按键F+1
break;
}
key_state = 3;
}
break;
case 8: // 消抖处理
key_value8 = key_board_scan();
key_state = 9;
break;
case 9: // 同状态8比较,确认单按键,返键值,转状态3
key_value9 = key_board_scan();
if (key_value9 == key_value8)
{
key_return = K4_4;
key_state = 3;
break;
}
key_state = 0;
break;
default:
break;
}
return key_return;
} |
本资料转载于他站、仅供同学学习使用
|