关于状态机的一个极度确切的描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。
有限状态机FSM思想广泛应用于硬件控制电路设计,也是软件上常用的一种处理方法(软件上称为FMM--有限消息机)。它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上判断事件,变连续处理为离散数字处理,符合计算机的工作特点。同时,因为有限状态机具有有限个状态,所以可以在实际的工程上实现。但这并不意味着其只能进行有限次的处理,相反,有限状态机是闭环系统,有限无穷,可以用有限的状态,处理无穷的事务。
在这次GD32测试体验中,楼主对按键的状态采集以及相应状态下的LED指示动作都充分采用了状态机的编程思想,具体的就让代码来说话吧:
按键扫描头文件:定义了按键状态及相关标志位的宏定义
#ifndef _KEYSCANDRIVE_H #define _KEYSCANDRIVE_H #define KEY_DOWN 0 #define KEY_DOWN_UP 1 extern uint8 KeyStateFlag; /* 按键状态 标志*/ extern uint8 KEY_State; /* 按键状态 begin */ #define Keystate0 0 //未按下 #define Keystate1 1 //发现按下 #define Keystate2 2 //稳定按下 #define Keystate3 3 //释放 /* 按键状态 end */ extern void KeyStateScan(void); /*按键扫描状态机*/ #endif
按键扫描的函数主体:
#include "includes.h"
uint8 KeyStateFlag; /* 按键状态 标志*/
uint8 KEY_State;
/****************************************************************************
*函数名称:void KeyStateScan(void)
*函数功能: 矩阵按键扫描状态机 ,对应按键控制LED
*日期:2015 4 2
*版本:V1.0
*作者:yrj
****************************************************************************/
void KeyStateScan(void)
{
switch (KeyStateFlag)
{
case Keystate0: /*未按下*/
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)== TRUE) /*未按下*/
{ KeyStateFlag = Keystate0; }
else /* 按下 */
{ KeyStateFlag = Keystate1; }
break;
case Keystate1: /*发现按下*/
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE) /*未按下*/
{ KeyStateFlag = Keystate0; }
else /* 按下 */
{ KeyStateFlag= Keystate2; }
break;
case Keystate2: /*稳定按下*/
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE) /*未按下*/
{ KeyStateFlag= Keystate0; }
else /* 按下 */
{
KeyStateFlag= Keystate3; //保持
KEY_State=KEY_DOWN; /* 按键按下 */
}
break;
case Keystate3: /*释放*/
{
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE) /*未按下*/
{
KeyStateFlag= Keystate0;
KEY_State=KEY_DOWN_UP; /* 按键按下并抬起*/
}aaa
}
break;
default:
{KeyStateFlag= Keystate0;}
break;
}
}
main函数主体:
void main(void)
{
bsp_init( );
while(1)
{
KeyStateScan( ); /* 按键状态扫描 */
switch(KEY_State)
{
case KEY_DOWN :
LED_ON(); break;
case KEY_DOWN_UP :
LED_OFF(); break;
default :break;
}
}
}
我要赚赏金
