没有合适的资源?快使用搜索试试~ 我知道了~
怎么能把按键处理玩出花?按键处理作为一个基础入门实验,大部分人在刚接触单片机的时候都会自己写一份,开始我们利用延时消抖,后来发现在大的工程当中,延时消抖在没有加入操作系统来调度的情况下,无疑是一种很浪费资源的做法。再后来我们开了定时器去扫描,确实比较靠谱,但是一但设计到复杂的组合按键,长按短按双击等,就需要我们去费很大的功夫去进行逻辑判断。 在网上看到了很多很棒的方法,即把底层寄存器的配置抽离出来,采用状态机思想去进行逻辑判断,可以有效地实现各种复杂的按键处理。借鉴这种思想,完成了自己的按键处理函数。这里直接上代码,再讲解。 .h 头文件: #ifndef __KEY_H #define __
资源详情
资源评论
资源推荐
超屌的按键处理方式(类思想,状态机,高移植性)超屌的按键处理方式(类思想,状态机,高移植性)
怎么能把按键处理玩出花?按键处理作为一个基础入门实验,大部分人在刚接触单片机的时候都会自己写一份,开始我们利用延时消抖,后来发现在大的工程
当中,延时消抖在没有加入操作系统来调度的情况下,无疑是一种很浪费资源的做法。再后来我们开了定时器去扫描,确实比较靠谱,但是一但设计到复杂的
组合按键,长按短按双击等,就需要我们去费很大的功夫去进行逻辑判断。
在网上看到了很多很棒的方法,即把底层寄存器的配置抽离出来,采用状态机思想去进行逻辑判断,可以有效地实现各种复杂的按键处理。借鉴这种思想,完
成了自己的按键处理函数。这里直接上代码,再讲解。
.h 头文件:头文件:
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
/**********************************************************************/
#define KEY0_RCCclock RCC_AHB1Periph_GPIOE
#define KEY0_PinPort GPIOE
#define KEY0_WhichPin GPIO_Pin_2
#define KEY0_PinStatus GPIO_PuPd_UP //上拉
#define KEY0_shortPress Key0_ShortCallback
#define KEY0_longPress Key0_LongCallback
#define KEY1_RCCclock RCC_AHB1Periph_GPIOE
#define KEY1_PinPort GPIOE
#define KEY1_WhichPin GPIO_Pin_3
#define KEY1_PinStatus GPIO_PuPd_UP //上拉
#define KEY1_shortPress Key1_ShortCallback
#define KEY1_longPress Key1_LongCallback
/**********************************************************************/
#define KEY_MAXNUM 4 //最大按键数
#define KEY_TIMER_MS 2 //扫描时间间隔
#define KEY_DELAY_MS 10 //消抖完成标志位
#define KEY_PRESS_STATUS 0 //即按下标志位
#define KEY_LONG_STATUS (1000/KEY_DELAY_MS*3) //即按下3s及判定为长按
#define KEY_DOUBLE_HIT_MAX (100/KEY_DELAY_MS*3) //连击判定时间最大值为300ms
//#define KEY_DOUBLE_HIT_MIN (100/KEY_DELAY_MS*1) //连击判定事件最小值为100ms
/**********************************************************************/
#define KEY_NODOWN 0x0000 //无按键按下
#define KEY_DOWN 0x1000 //有按键按下
#define KEY_UP 0x2000 //按键短按标志位
#define KEY_LIAN 0x4000 //按键连按标志位
#define KEY_LONG 0x8000 //按键长按标志位
/**********************************************************************/
/*
这三个函数的作用分别是:
1、设置a某一位的值 G_SET_BIT
2、清楚a某一位的值 G_CLEAR_BIT
3、获得a某一位的值 G_IS_BIT_SET
*/
#define G_SET_BIT(a,b) (a |= (1 << b))
#define G_CLEAR_BIT(a,b) (a &= ~(1 << b))
#define G_IS_BIT_SET(a,b) (a & (1 << b))
/**********************************************************************/
//定义了一个回调指针,即根据发生的事件,
typedef void (*KeyCallback_Pointer) (void);
/**********************************************************************/
//单个按键对象结构体
__packed typedef struct
{
uint8_t Key_Num;//共有多少个按键对象
uint32_t Key_RccPeriphConfig;//按键对象时钟
GPIO_TypeDef* KeyPort;//按键所在IO口组
uint32_t Key_WhichPin;//第几个IO引脚
GPIOPuPd_TypeDef Key_PinStatus;//IO引脚的状态
KeyCallback_Pointer shortPress;//定义一个函数指针指向短按回调函数
KeyCallback_Pointer longPress;//定义一个函数指针指向长按回调函数
}keyTypeDef_t;//单个按键对象结构体!
/**********************************************************************/
//多个按键对象结构体(总)
__packed typedef struct
{
u8 KeyTotolNum; //按键总数累计
keyTypeDef_t* singleKey;//按键对象的指针!
}keysTypeDef_t;//多个按键对象结构体!
/**********************************************************************/
//双击枚举!
typedef enum {Keyd_Wait_Flag = 0,Keyd_End_Flag = 1,Keyd_IDLE_Flag = 2}keyd_Status;
//双击结构体!
typedef struct
{
keyd_Status Keyd_Flag;
uint16_t First_KeyVal;
uint16_t Key_Double_Hit_Count;
}Keyd_t;
/**********************************************************************/
extern u32 key_down;//声明外部变量,表示按键长短按及哪一个按键
extern keysTypeDef_t keys;
extern Keyd_t keyd;
void Key_Init(void);
void Key0_ShortCallback(void);
void Key0_LongCallback(void);
void Key1_ShortCallback(void);
void Key1_LongCallback(void);
void Key_Scan_TimeConfig(void);
uint16_t keyGet(keysTypeDef_t* keys_t);
void Key_Handle_Task(void);
#endif
最上面的和KEY0/KEY1处理有关的宏定义即是把底层抽离的方式之一,在移植的过程中,只需要修改宏定义即可完成对不同的IO口的初始化。而有关按键处理
的函数我们并不需要去做处理,初始化按键处理后,只需要去判断 u32 key_down的不同的位,即可获得当前按键的各种状态。这里说一下key_down这个变
量,我假定最多按键处理为4个,那么32位便以4分区,可以分成8各区域,那么每个区域即可标识不同的状态位,这里可以根据项目需求去做更改这个变量的
不同位。
/
key_down 共有共有32位,这里把它分割成不同的区域:位,这里把它分割成不同的区域:
0-3 : 预留区域,这里最多定义预留区域,这里最多定义4个按键,哪个为个按键,哪个为1表示状态表示状态“绑定绑定”在哪个按键上面在哪个按键上面
4-7 : 短按判断区,这里最多判断短按判断区,这里最多判断4个,哪个按键在触发短按事件,哪个位置个,哪个按键在触发短按事件,哪个位置1
8-11 : 长按判断区,这里最多判断长按判断区,这里最多判断4个,哪个按键在触发长按事件,哪个位置个,哪个按键在触发长按事件,哪个位置1
12-15 : 连击判断区,这里最多判断连击判断区,这里最多判断4个,哪个按键在触发连击事件,哪个位置个,哪个按键在触发连击事件,哪个位置1
/
从宏定义可以看出,这里是把按键这个事件当成一个类,类对应到单片机上每个按键IO口时,即为实例化了一个按键对象。我们需要几个按键,就去实例化几
个IO口即可。每个对象都有两个函数指针,当对应状态产生时,即可调用初始化过程中的函数指针指向的函数。这里编程思想比较类似于C++,只是没有区分
共有私有之类的数据部分。函数指针即为公共接口,需要自己去编写。这里我虽然在初始化时规定了指向,但是并没有编写接口(回调)函数,而是直接判断
key_down 的相应位去判断按键状态。
.C 工程文件:工程文件:
#include "key.h"
#include "delay.h"
#include "stdio.h"
/*
key_down 共有32位,这里把它分割成不同的区域:
0-3 : 预留区域,这里最多定义4个按键,哪个为1表示状态“绑定”在哪个按键上面
4-7 : 短按判断区,这里最多判断4个,哪个按键在触发短按事件,哪个位置1
8-11 : 长按判断区,这里最多判断4个,哪个按键在触发长按事件,哪个位置1
12-15 : 连击判断区,这里最多判断4个,哪个按键在触发连击事件,哪个位置1
*/
u32 key_down = 0;//按键状态标志位,所以的操作都是为了改变这个全局变量
#define GPIO_KEY_NUM 2 //定义按键成员个数
keyTypeDef_t singKey[GPIO_KEY_NUM]; //定义单个按键成员数组指针
keysTypeDef_t keys; //定义总的按键模块结构
Keyd_t keyd; //双击结构体
uint8_t keyCountTime = 0;
uint16_t keyGet(keysTypeDef_t* keys_t)
{
uint8_t i = 0;
uint16_t readKey = 0;
//循环读取判断键值
for(i = 0;i KeyTotolNum ; i++) //初始化了几个按键,则扫描几次
{
if(KEY_PRESS_STATUS == GPIO_ReadInputDataBit(keys_t->singleKey[i].KeyPort,keys_t->singleKey[i].Key_WhichPin))
{
G_SET_BIT(readKey,keys_t->singleKey[i].Key_Num);//Key_Num即为每个按键对象的“序号”
}
}
return readKey;
}
//采用状态机思想,将按键形态分割成不同状态
uint16_t readKeyValue(keysTypeDef_t* keys_t)
{
static uint8_t keyCheck = 0;
static uint8_t keyState = 0;
static uint8_t keydCheck = 0; //双击补偿量,每点击一次按键,则重置为0,这个值过大则表示
static uint16_t keyLongCheck = 0; //长按事件检测标志位
static uint16_t keyPrev = 0; //上一次的键值
uint16_t keyPress = 0;
uint16_t keyReturn = 0;
keyCountTime += KEY_TIMER_MS; //每当进入一次中断,便自增2ms
if(keyCountTime >= KEY_DELAY_MS) //消抖完成
剩余6页未读,继续阅读
weixin_38696196
- 粉丝: 9
- 资源: 872
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 内部讲师评选方案.doc
- 培训师职业训练教材《教学媒体应用技能训练》.doc
- 培训之网络写作指南.doc
- 培训师职业技能训练教材《良好心理素质养成与心理辅导技能训》.doc
- HR师认证复习资料-人力资源规划.ppt
- 关于如何对待工作的一些建议(ppt 45页).ppt
- 培训导师.ppt
- 管理领导力与激励.ppt
- 培训导师的职责与任务.ppt
- 培训艺术与技术(教材).ppt
- 企业内部培训师培训分享资料.ppt
- 培训与开发(ppt 157页).ppt
- 人力资源培训教材-人员招募与甄选(PPT 24页).ppt
- 巧妙处理听众的问题.ppt
- 企业培训讲师形象.ppt
- 人力资源培训教材-如何设计发展空间(PPT 26页).ppt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0