一. 什么是状态机
我们以生活中的小区的停车系统为例:停车杆一般没车的是不动的(初态),有车来的时候需要抬杆(状态1),车通过需要放杆(状态2),如果在放杆的过程中突然有车,又需要抬杆(状态3)。。。就是说我们需要将不同的情况划分为不同的状态,每个状态对应相应的操作。
这只是状态机的一个很简单的举例。如果单个状态也是一个状态机的话,那么就会形成状态机套状态机,有点类似于C++里的父类和子类。其实在我们日常的程序设计中,处处都有状态机的影子,不管是我们嵌入式编程,游戏开发,服务端开发等等都要用到。
网上关于状态机的介绍很多,如果有想详细了解的可以去找找相关资料。
二. 用状态机的思想实现按键扫描
按键有按下和松开的状态,还有长按和短按的状态,以及单个按键和组合按键的状态等等。我们来看看如何用状态机的思想实现它,这里会有两种处理方式,第一种是利用一个定时器中断,每隔ms扫描一次;第二种是直接在while(1)循环里检测是否有按键按下。处理的思路都差不多,下面看看实现的代码。
/**********************************key.c*********************************/
//读取按键对应的管脚电平
static u16 GetKey(keysTypedef_t *keyS)
{
uint8_t i = 0;
uint16_t readKey = 0;
//GPIO Cyclic scan
for(i = 0; i < keys.keyTotolNum; i++)
{
if(!HAL_GPIO_ReadPin((GPIO_TypeDef*)keyS->singleKey[i].keyPort,keyS->singleKey[i].keyGpio))
{
G_SET_BIT(readKey, keyS->singleKey[i].keyNum); //读取到按键电平,设置对应的按键返回值为1
}
}
return readKey;
}
// 判断按键是否按键按下,是长按还是短按
uint16_t readKeyValue(keysTypedef_t *keyS)
{
static uint8_t keyCheck = 0; //当前按键的值
static uint8_t keyState = 0;
stati