电子说
按键的实现逻辑(包括长按、短按、双击等),在交互之中的用户体验尤为重要,机智云GoKit_STM32按键的实现逻辑,在我见过的按键模块中算不错的一个了!
上期我们分享了机智云串口的环形buff,相信大家在看了思维导图之后对整个协议的结构有了很好的理解,今天我们重点分析下机智云的按键处理机制。
在主程序main.c中,我们看到有2个定义
keyTypedef_tsingleKey[2];
keysTypedef_tkeys;
这个就是按键结构体的相关定义了,我们先来看下singleKey[2],这是一个数组,类型为keyTypedef_t,我们看看具体定义:
__packed typedefstruct
{
uint8_tkeyNum;
uint32_tkeyRccPeriph;
GPIO_TypeDef *keyPort;
uint32_tkeyGpio;
gokitKeyFunction shortPress;
gokitKeyFunction longPress;
}keyTypedef_t;
结构体包括第几个按键、所属按键时钟、Port、Gpio、短按回调函数与长按回调函数,gokitKeyFunction是一个函数指针类型的定义,使用回调的好处就是一次性定义好,之后按下去所做的事情直接在回调函数中写就可以了,结构比较明了。
接下来再看看keysTypedef_t的定义
__packed typedefstruct
{
uint8_tkeyNum;
keyTypedef_t*singleKey;
}keysTypedef_t;
这个比较简单,定义了一个按键数量与 keyTypedef_t *类型的一个指针。然后我们看两者怎么联系的。
首先通过keyInitOne将按键0的相关信息定义到singleKey[0] 中,然后keys.keyNum++,之后将相关信息也定义到singleKey[1]中,之后将singleKey数组的指针赋值给 keys.singleKey ,之后通过keys就可以轻松调用2个按键的各项功能了。
在下面的keyParaInit中,实际初始化了按键IO的各项参数,最后有一个定时器的初始化函数。timer2Init();主要初始化了定时器2,从预分频与自动重装初值我们判断出定时器1ms中断一次,那么每1ms中断一次做什么呢?我们追踪到定时器2的中断函数,
我们看到,中断中只做了一件事,按键句柄,我们具体看
keyHandle((keysTypedef_t*)&keys),
首先是读取按键值,这个比较重点,也是精髓,我们进去看看,里面会对keyCountTime进行累加10次,用来消抖,确定之后去得到按键真正的值
PRESS_KEY1与PRESS_KEY2定义如下
#define PRESS_KEY1 0x01
#define PRESS_KEY2 0x02
之后返回的readKey便是按键的值,函数返回值赋给keyPress,接下来便是一个状态机。
具体的过程为:
开始keyState为0,第一个10ms进来,如果检测到keyPress!=0,证明有按键按下,将keyState状态更新为1,keyPrev = keyPress;并将keyPress赋值给上一次的按键值。下一个10ms的时候我们进去状态1的地方执行,分为2步,
1、如果当前获取到的状态与上次一样,认为按键确实按下了,将状态更新为2,同时将哪个按键以及按键按下的值赋给keyReturn,通过这个就可以明确哪个按键按下了。
2、如果当前获取到的状态与上次不一样,认为是按键抖动,不进行响应。
第三个10ms来之后,进去状态2(假如不是抖动),也是分2步
1、如果按键不等于上次的状态(按下),则认为按键松开,认为一次按下完成,状态清零,返回按键值。
2、如果状态与上次还是一样,则认为一直在按着按键,就可以做长按功能了。返回按键值。
如果进去长按了,则将状态更新为3。
第四个10ms到来之后,进去状态3,用于判断长按之后的松手状态。就不多说了。
之后,通过keyReturn & KEY_UP判断短按,keyReturn & KEY_LONG判断长按,之后通过回掉函数进去相应的函数执行,这里的一个好处就是通过指针keys就可以调用所有的回调函数指针。
好,就先分析到这里,相信大家对按键部分的代码都有一个比较详细的了解了,但还是要一个一个分析,达到为我所用的地步,方可真正学会其中的精髓。觉得好的话可以下面点赞哦,你们的点赞是我最大的动力!
全部0条评论
快来发表一下你的评论吧 !