//--------------------------------------------------------------------------
//独立按键和阵列式按键,不支持同时按键
//返回按键ASCII码
//支持按下一次有效,get_key()
//按下后重复有效,get_key()
//按下后释放按键才有效,get_key_release()或get_key_func()
//长按有效,get_key_release()或get_key_func()
//连续按下多次有效(1、2、3、4),get_key_func()
//--------------------------------------------------------------------------
#include "key.h"
//----------------------------------全局变量--------------------------------
#ifndef __KEY_USE_TIMER
struct_KeyInfo key_info1 = // 可以定义多套按键
{
KEY_LOOP_CHECK, // INT8U key_check_mode; // 检测按键的标志KEY_DELAY_CHECK或KEY_LOOP_CHECK
NO_KEY, // INT8U key_pre_value; // 时间计数
FSM_NOKEY, // INT8U key_state; // 按键状态机状态
0, // INT16U key_dly_cnt; // 按键消抖延迟计数
0, // INT16U key_hold_cnt; // 按键按下后保持计数
0 // INT16U key_repeat_cnt; // 按键按下后重复次数计数
};
#endif // #ifndef __KEY_USE_TIMER
#ifdef __KEY_IDPT
//键值映射
INT8U key_map[] = {0, '1', '2', 0, '3', 0, 0, 0, '4',
0, 0, 0, 0, 0, 0, 0};
#endif /* #ifdef __KEY_IDPT */
#ifdef __KEY_ARRAY
//键值映射
INT8U keypad_map[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
#endif /* #ifdef __KEY_ARRAY */
//--------------------------------------------------------------------------
//函数名称:delay_key
//功 能:延时
//参 数:struct_KeyInfo * pKey_Info: 按键组信息
//返回值 :无
//--------------------------------------------------------------------------
void delay_key(struct_KeyInfo * pKey_Info)
{
INT8U i, j;
if (pKey_Info->key_check_mode)
{
if (pKey_Info->key_dly_cnt < KEY_DITHERLESS_DELAY)
{
pKey_Info->key_dly_cnt++;
}
else
{
pKey_Info->key_dly_cnt = 0;
}
// key_dly_over = (key_dly_cnt == KEY_DITHERLESS_DELAY);
}
else
{
pKey_Info->key_dly_cnt = 0;
j = KEY_DITHERLESS_DELAY;
while (j-- > 0)
for (i = KEY_DELAY_BASE; i > 0; i--);
}
}
#ifdef __KEY_IDPT
//--------------------------------------------------------------------------
//函数名称:init_key
//功 能:初始化扫描键盘的IO端口
//参 数:无
//返回值 :无
//--------------------------------------------------------------------------
void init_key()
{
KEY_PORT_FUNC;
KEY_PORT_DIR;
}
//--------------------------------------------------------------------------
//函数名称:key_pressed
//功 能:检测按键
//参 数:无
//返回值 :0:无按键 1:有按键
//--------------------------------------------------------------------------
BOOL key_pressed()
{
return (KEY_PORT_IN != 0); //获取输入
// 返回0无按键按下,否则有键按下
}
INT8U read_key()
{
return (key_map[KEY_PORT_IN]);
}
#endif /* #ifdef __KEY_IDPT */
#ifdef __KEY_ARRAY
//--------------------------------------------------------------------------
//函数名称:init_keypad
//功 能:初始化扫描键盘的IO端口
//参 数:无
//返回值 :无
//--------------------------------------------------------------------------
void init_keypad()
{
KEY_COL_FUNC;
KEY_COL_DIR;
KEY_ROW_FUNC;
KEY_ROW_DIR;
KEY_ROW |= KEY_ROW_VAL; // 输出高电平
}
//--------------------------------------------------------------------------
//函数名称:key_pressed
//功 能:检测按键
//参 数:无
//返回值 :0:无按键 1:有按键
//--------------------------------------------------------------------------
BOOL keypad_pressed()
{
KEY_ROW &= ~KEY_ROW_VAL; //行输出全0,判断有无按键输入
return ((~KEY_COL & KEY_COL_VAL) != 0); //获取列输入,低有效
// 返回0无按键按下,否则有键按下
}
//--------------------------------------------------------------------------
//函数名称:read_key
//功 能:扫描键盘的IO端口,获得键值
//参 数:无
//返回值 :INT8U 按键的ASCII码
//--------------------------------------------------------------------------
INT8U read_key()
{
// 使用循环扫描和循环查询的方式
INT8U key_val;
INT8U row_cnt, col_cnt, row_scanout, col_scanin;
key_val = 0;
row_scanout = KEY_ROW_MAX; // 行从高到低按row_scanout扫描
// row_scanout = KEY_ROW_MIN; // 行从低到高按row_scanout扫描
for (row_cnt = 0; row_cnt < KEY_ROW_NUM; row_cnt++) //--行扫描
{
KEY_ROW |= KEY_ROW_VAL; //行输出全1
KEY_ROW &= (~row_scanout); //行输出中有一个为0
row_scanout >>= 1; // 行从高到低按row_scanout扫描
// row_scanout <<= 1; // 行从低到高按row_scanout扫描
if ((~KEY_COL & KEY_COL_VAL) != 0) //是否列中有一位有效,低有效
{
// col_scanin = KEY_COL_MAX; // 列从高到低col_scanin用于检测哪一位为0
col_scanin = KEY_COL_MIN; // 列从低到高col_scanin用于检测哪一位为0
for (col_cnt = 0; col_cnt < KEY_COL_NUM; col_cnt++) //--列检测
{
if ((KEY_COL & col_scanin) == 0) // 是否是该列, 等于0为是
{
// 查表获取键值
key_val = keypad_map[row_cnt * KEY_COL_NUM + col_cnt];
return (key_val); // 返回值,退出循环
}
// col_scanin >>= 1; // 列从高到低col_scanin右移1位
col_scanin <<= 1; // 列从低到高col_scanin左移1位
}
}
}
// 使用直接扫描和case查询的方式
/*
INT8U key_val;
INT8U row_cnt, row_scanout, col_scanin;
key_val = 0;
row_cnt = 0;
//行扫描
for (row_scanout = KEY_ROW_MAX; row_cnt >= KEY_ROW_MIN; row_cnt >>= 1)
// for (row_scanout = KEY_ROW_MIN; row_cnt <= KEY_ROW_MAX; row_cnt <<= 1)
{
KEY_ROW |= KEY_ROW_VAL; //行输出全1
KEY_ROW &= (~row_scanout); //行输出四位中有一个为0
col_scanin = ~KEY_COL & KEY_COL_VAL; // 列col_scanin用于检测出哪一位为0
switch (col_scanin) // 列检测,同一时刻只能有一个按键按下
{
case KEY_COL_1:
key_val = keypad_map[row_cnt * KEY_COL_NUM]; // 查表获取键值
break;
case KEY_COL_2:
key_val = keypad_map[row_cnt * KEY_COL_NUM + 1]; // 查表获取键值
break;
case KEY_COL_3:
key_val = keypad_map[row_cnt * KEY_COL_NUM + 2]; // 查表获取键值
break;
case KEY_COL_4:
key_val = keypad_map[row_cnt * KEY_COL_NUM + 3]; // 查表获取键值
break;
case default:
key_val = 0;
break;
}
row_cnt++;
}
*/
return (key_val); // 返回值
}
#endif /* #ifdef __KEY_ARRAY */
//--------------------------------------------------------------------------
//函数名称:key_callback
//功 能:按键回调函数,用于长按和重复计数
//参 数:INT8U key_holdtime: 保持计数次数
// struct_KeyInfo * pKey_Info: 按键组信息
//返回值 :无
//--------------------------------------------------------------------------
void key_callback(INT8U key_holdtime, struct_KeyInfo * pKey_Info)
{
if (pKey_Info->key_hold_cnt <= key_holdtime)
pKey_Info->key_hold_cnt++;
else
{
if (pKey_Info->key_hold_cnt <= KEY_HOLD_MAX) // 计算超长按
pKey_Info->key_hold_cnt++;
if (pKey_Info->key_repeat_cnt <= KEY_REPEAT_TIME) // 进入重复
pKey_Info->key_repeat_cnt++;
else
pKey_Info->key_repeat_cnt = 0;
}
}
//--------------------------------------------------------------------------
//函数名称:key_fsm
//功 能:检测按键状态转换机转换函数
//参 数:INT8U
全功能按键程序,支持消抖,长按,组合按键,按两次,三次,四次等
5星 · 超过95%的资源 需积分: 50 190 浏览量
2013-09-05
08:41:55
上传
评论 11
收藏 6KB RAR 举报
Arthurzss
- 粉丝: 1
- 资源: 2