全功能按键程序,支持消抖,长按,组合按键,按两次,三次,四次等

******************* main.c
while(1)
{
if (key_mode == '0')
cur_key = get_key();          // 支持延迟消抖,可重复输入按键
else
cur_key = get_key_func();  // 按键并等待按键释放,支持长按和多次按键,需打开key.c中的函数定义
//            cur_key = get_key_release();// 支持延迟消抖,并等待按键释放,支持长按
if (cur_key != NO_KEY)
{
PutChar(cur_key);
PutString("\n\r");
PutString("This Key's ID is: ");
}
}
}
******************* key.h
#ifndef __DEF_H
#define __DEF_H
typedef unsigned char  INT8U;
typedef unsigned int    INT16U;
typedef unsigned long  INT32U;
typedef signed char    INT8S;
typedef signed int      INT16S;
typedef signed long    INT32S;
typedef float          FP32;                    /* Single precision floating point                    */
typedef double          FP64;                    /* Double precision floating point                    */
typedef unsigned char  BOOL;
typedef unsigned char  BYTE;
typedef unsigned int    WORD;
#ifndef  FALSE
#define  FALSE                  0
#endif
#ifndef  TRUE
#define  TRUE                  1
#endif
void delay_N_ns(INT16U n);
#endif /* #ifndef __DEF_H */
#ifndef __KEY_H
#define __KEY_H
#include <msp430x14x.h>
//#define __KEY_IDPT
#define __KEY_ARRAY
//#define __KEY_USE_TIMER                          // 使用定时器定时检测按键
#define NO_KEY                  0                  // 无按键
#define KEY_DELAY_BASE          30                  // 消抖延迟时间基数
#define KEY_DITHERLESS_DELAY    100                // 按键消抖延迟时间
#define KEY_HOLD_TIME          30                  // 按键按住多少时间开始重复
#define KEY_REPEAT_TIME        5                  // 按键长按后的重复时间
#define KEY_LONGHOLD_TIME      50                  // 按键按住多少时间开始算长按
#define KEY_HOLD_MAX            200                // 按键按住算超长按
#define KEY_TIME_MAX            8000                // 总计数次数
//#define KEY_TIME_MAX            KEY_DITHERLESS_DELAY*100
#define KEY_DELAY_CHECK        0
#define KEY_LOOP_CHECK          1
/
/ 按键状态定义
#define FSM_NOKEY          0  // 按键状态,无按键
#define FSM_KEY_DOWN        1  // 按键状态,按下
#define FSM_KEY_SURE_HOLD  2  // 按键状态,一直按住
#define FSM_KEY_UP          3  // 按键状态,松开
// ---------------------------- __KEY_IDPT ---------------------------
// Independent key defines and functions
#ifdef __KEY_IDPT
#define KEY_PORT_NUM    4                        // 按键数 4
#define KEY_PORT_VAL    0x0F                      // 对应的IO有效位置
#define KEY_PORT_MAX    0x08                      // 最高有效位
#define KEY_POR
T_MIN    0x01                      // 最低有效位
#define KEY_PORT_FUNC  {P1SEL &= ~KEY_PORT_VAL;} // 设置为IO模式
#define KEY_PORT_DIR    {P1DIR |= KEY_PORT_VAL;}  // 设置为输入
键盘映射
#define KEY_PORT_IN    (~P1IN &  KEY_PORT_VAL)  // 读取输入值,低电平有效
void  init_key();
#endif // #ifdef __KEY_IDPT
// ---------------------------- end of __KEY_IDPT --------------------
// ---------------------------- __KEY_ARRAY ---------------------------
// Key array defines and functions
#ifdef __KEY_ARRAY
/
/ Key Row defines
#define KEY_ROW_NUM    4                        // 行数
#define KEY_ROW_VAL    0xF0                      // 行对应的IO有效位置
#define KEY_ROW_MAX    0x80                      // 行最高有效位
#define KEY_ROW_MIN    0x10                      // 行最低有效位
#define KEY_ROW_FUNC    {P1SEL &= ~KEY_ROW_VAL;}  // P5.4~P5.7设置为IO模式
#define KEY_ROW_DIR    {P1DIR |= KEY_ROW_VAL;}  // P5.4~P5.7设置为行扫描输出
#define KEY_ROW        P1OUT                    // 行扫描输出端口
// Key col defines
#define KEY_COL_NUM    4                        // 列数
#define KEY_COL_VAL    0x0F                      // 列对应的IO有效位置
#define KEY_COL_MAX    0x08                      // 列最高有效位
#define KEY_COL_MIN    0x01                      // 列最低有效位
#define KEY_COL_FUNC    {P1SEL &= ~KEY_COL_VAL;}  // P1.0~P1.3设置为IO模式
#define KEY_COL_DIR    {P1DIR &= ~KEY_COL_VAL;}  // P1.0~P1.3设置为列扫描输入
#define KEY_COL        P1IN                      // 列扫描输入端口
#define KEY_COL_1      0x01                      // 1列对应的IO位置
#define KEY_COL_2      0x02                      // 2列对应的IO位置
#define KEY_COL_3      0x04                      // 3列对应的IO位置
#define KEY_COL_4      0x08                      // 4列对应的IO位置
//如果按键的行列在同一个IO口组,则可以用一句话进行端口初始化
#define KEY_PORT_VAL    (KEY_ROW_VAL | KEY_COL_VAL) // 也可以直接修改定义值为数字
#define KEY_PORT_FUNC  {P5SEL &= ~KEY_VAL;}      // P1.0~P1.7设置为IO模式
void  init_keypad();
#define key_pressed    keypad_pressed  //单独使用阵列键盘时,函数直接等同
// 同时使用独立按键和阵列键盘,需再定义以下函数(修改对应函数中key_pressed())
//INT8U keypad_pressed();
//INT8U check_keypad();
//INT8U get_keypad();
#endif /* #ifdef __KEY_ARRAY */
// ---------------------------- end of __KEY_ARRAY -------------------
// ---------------------------- __KEY_USE_TIMER ----------------------
// 使用定时器支持按键长按,定时(或者循环)消抖,组合按键
#ifdef __KEY_USE_TIMER
// 使用定时器支持按
键长按,定时(或者循环)消抖,组合按键
typedef struct
{
INT8U  key_check_mode;  // 是否在循环中检测按键的标志KEY_DELAY_CHECK或KEY_LOOP_CHECK
INT8U  key_pre_value;  // 时间计数
INT8U  key_state;      // 按键状态机状态
//        INT16U key_dly_cnt;    // 按键消抖延迟计数
INT16U key_hold_cnt;    // 按键按下后保持计数2015北京高考英语
INT16U key_repeat_cnt;  // 按键按下后重复次数计数
} struct_KeyInfo;
/*
#define _KEY_NONE      0
#define _KEY_REENTER    1
#define _KEY_NO_REENTER 2
typedef struct
{
WORD PreKey;                            //上次检测到的键
BYTE KeyState;                          //按键状态机状态
WORD SameKeyCntr;                      //同一键检测到按下的次数
WORD CurKey;                            //当前检测到的键, 用于处理长按的情况
BYTE (*KeyDownCallBack)(WORD, WORD);    //键确认按下的回调函数指针
void (*KeyUpCallBack)(WORD);            //键抬起的回调函数指针
} struct_KeyInfo;
*/
// ---------------------------- else of __KEY_USE_TIMER
#else
// 不使用定时器检测按键,但支持按键按下和松开,按键长按等功能
typedef struct
{
INT8U  key_check_mode;  // 是否在循环中检测按键的标志KEY_DELAY_CHECK或KEY_LOOP_CHECK
INT8U  key_pre_value;  // 时间计数
INT8U  key_state;      // 按键状态机状态
INT16U key_dly_cnt;    // 按键消抖延迟计数
INT16U key_hold_cnt;    // 按键按下后保持计数
INT16U key_repeat_cnt;  // 按键按下后重复次数计数
} struct_KeyInfo;
#endif // #ifdef __KEY_USE_TIMER
// ---------------------------- end of __KEY_USE_TIMER ---------------
extern  struct_KeyInfo  key_info1;  // 可以定义多套按键
INT8U  read_key();                        // 读键,并根据映射返回键值
BOOL    key_pressed();                      // 检测是否有按键按下
INT8U  check_key(INT8U, struct_KeyInfo *); // 检测按键键值
INT8U  get_key();                  // 支持延迟消抖,可重复输入按键
INT8U  get_key_release();          // 支持延迟消抖,并等待按键释放,支持长按
INT8U  get_key_func();            // 按键并等待按键释放,支持长按和多次按键
#endif /* #ifndef __KEY_H */
*******************key.c
//--------------------------------------------------------------------------
//独立按键和阵列式按键,不支持同时按键
//返回按键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 >= K

本文发布于:2024-09-21 13:35:41,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/722307.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:按键   消抖   检测
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议