网易首页 > 网易号 > 正文 申请入驻

如何深入理解“有限状态机”的设计思想?

0
分享至

如何深入理解“有限状态机”的设计思想?

程序设计和数字电路设计中都经常会用到“有限状态机”的设计思想。

在嵌入式软件开发中,状态机编程是一个十分重要的编程思想,它也是嵌入式开发中一个常用的编程框架。掌握了状态机编程思想,可以更加逻辑清晰的实现复杂的业务逻辑功能。

1状态机思想

状态机,或称有限状态机FSM(Finite State Machine),是一种重要的编程思想。

状态机有3要素:状态、事件与响应

·状态:系统处在什么状态?

·事件:发生了什么事?

·响应:此状态下发生了这样的事,系统要如何处理?

状态机编程前,首先要根据需要实现的功能,整理出一个对应的状态转换图(状态机图),然后就可以根据这个状态转换图,套用状态机编程模板,实现对应是状态机代码了。

状态机编程主要有 3种方法:switch-case法、表格驱动法、函数指针法,本篇先介绍最简单也最易理解的switch-case法。

2状态机实例

下面以按键消抖功能,来介绍switch-case法的状态机编程思路。

2.1按钮消抖状态转换图

状态机机编程前,首先要明确的对应功能的状态机需要几个状态,本例的按键功能,只检测最基础的按下与松开状态(暂不实现长按、双击等状态),并增加对应的按钮去抖功能,因此,需要用到4个状态:

·稳定松开状态

·按下抖动状态

·稳定按下状态

·松开抖动状态

对应的状态转换图如下:

由于按键通常处于松开状态,这里让状态机的初始化状态为松开状态,然后在这4个状态中来回切换。

图中的VT代表按键检测到电平,VT=0即检测到低电平,可能是按键按下,由初始的“稳定松开”状态转为“按下抖动”状态

当持续检测到低电平(VT=0)一段时间后,认为消抖完成,由“按下抖动”状态转为“稳定按下”状态

在“按下抖动”状态时,在指定的一段时间内,再次检测到高电平(VT=1),说明确实是按钮抖动(比如按键被快速拨动了一下又弹起,或强烈震动导致的按键抖动),则由“按下抖动”状态转为“稳定松开”状态

2.2编程实现

2.2.1状态定义

对应上面的按钮状态图,可以知道需要用到4个状态:

·稳定松开状态(KS_RELEASE)

·按下抖动状态(KS_PRESS_SHAKE)

·稳定按下状态(KS_PRESS)

·松开抖动状态(KS_RELEASE_SHAKE)

这里使用枚举来定义这4个状态。为了在调试时,能够把对应状态名称以字符串的形式打印出来,这里使用宏定义的一个小技巧:

#符号+自定义的枚举名称

即可自动转变为字符串形式,再将这些字符串放到const char* key_status_name[]数组中,便可通过数组的形式访问这些状态的字符串名称形式。

此外,为了不重复书写枚举名称与对应的枚举字符串(#+枚举名称),进一步使用宏定义的方式,只定义一次状态,然后通过下面两条宏定义,实现对枚举项和枚举项对应的字符串的分别获取:

#define ENUM_ITEM(ITEM) ITEM,#define ENUM_STRING(ITEM) #ITEM,

具体是宏定义、枚举定义与枚举名称数组声明如下:

#define ENUM_ITEM(ITEM) ITEM,#define ENUM_STRING(ITEM) #ITEM,#define KEY_STATUS_ENUM(STATUS) \ STATUS(KS_RELEASE) /*稳定松开状态*/ \ STATUS(KS_PRESS_SHAKE) /*按下抖动状态*/ \ STATUS(KS_PRESS) /*稳定按下状态*/ \ STATUS(KS_RELEASE_SHAKE) /*松开抖动状态*/ \ STATUS(KS_NUM) /*状态总数(无效状态)*/ \ typedefenum{

KEY_STATUS_ENUM(ENUM_ITEM)}KEY_STATUS;constchar*key_status_name[]={

KEY_STATUS_ENUM(ENUM_STRING)};

宏定义不便理解的,可以将宏定义分别带入,转为最终的结果,理解替代后的具体形式,比如下面的宏定义带入替换示意:

/*KEY_STATUS_ENUM(STATUS) --> STATUS(KS_RELEASE) ... STATUS(KS_NUM)KEY_STATUS_ENUM(ENUM_ITEM)--> ENUM_ITEM(KS_RELEASE) ... ENUM_ITEM(KS_NUM)--> KS_RELEASE, ... KS_NUM,KEY_STATUS_ENUM(ENUM_STRING)--> ENUM_STRING(KS_RELEASE) ... ENUM_STRING(KS_NUM)--> #KS_RELEASE, ... #KS_NUM,*/

2.2.2状态机实现

下面是状态机的具体实现:

·状态机函数key_status_check在一个循环中,被每隔10ms调用一次

·定义一个g_keyStatus表示状态机所处的状态

·在每个循环中,switch根据当前的状态,执行对应状态所需要执行的逻辑

·定义一个g_DebounceCnt用于消抖时间计算,当持续进入消抖状态,每次循环(10ms)中将此值加1,持续一定次数(5次,即50ms),认为是稳定的按下或松开,消抖完成,跳转到稳定方向或稳定松开状态

·在每个状态的执行逻辑中,当检测到某些条件满足时,跳转到其它的状态

·通过状态的不断跳转,实现状态机的运行

·此外,为方便观察状态机中状态的变化,定义了一个g_lastKeyStatus表示前一状态,当状态发生变化时,可以将状态名称打印出来

KEY_STATUSg_keyStatus=KS_RELEASE;//当前按键的状态KEY_STATUSg_lastKeyStatus=KS_NUM;//上一状态intg_DebounceCnt=0;//消抖时间计数voidkey_status_check(){

switch(g_keyStatus)

//按键释放(初始状态)caseKS_RELEASE:

//检测到低电平,先进行消抖if(KEY0==0)

g_keyStatus=KS_PRESS_SHAKE;

g_DebounceCnt=0;

break;

//按下抖动caseKS_PRESS_SHAKE:

g_DebounceCnt++;

//确实是抖动if(KEY0==1)

g_keyStatus=KS_RELEASE;

//消抖完成elseif(g_DebounceCnt==5)

g_keyStatus=KS_PRESS;

printf("=====> key press\r\n");

break;

//稳定按下caseKS_PRESS:

//检测到高电平,先进行消抖if(KEY0==1)

g_keyStatus=KS_RELEASE_SHAKE;

g_DebounceCnt=0;

break;

//松开抖动caseKS_RELEASE_SHAKE:

g_DebounceCnt++;

//确实是抖动if(KEY0==0)

g_keyStatus=KS_PRESS;

//消抖完成elseif(g_DebounceCnt==5)

g_keyStatus=KS_RELEASE;

printf("=====> key release\r\n");

break;

default:break;

if(g_keyStatus!=g_lastKeyStatus)

g_lastKeyStatus=g_keyStatus;

printf("new key status:%d(%s)\r\n",g_keyStatus,key_status_name[g_keyStatus]);

}}intmain(void){

delay_init();//延时函数初始化KEY_Init();

uart_init(115200);

printf("hello\r\n");

while(1)

key_status_check();

delay_ms(10);

注:本例程需要使用一个按键,需要初始化对应的GPIO,这里不再贴代码。

2.3使用测试

将完整的代码编译后烧录到板子中,连接串口,按下与松开按键,观察串口输出信息。

我的测试输出信息如下:

前两次拨动按键模拟按钮抖动的情况,可以看到串口打印出两次从松开到按下抖动的状态切换。

然后是按下按键,再松开按键,可以看到状态的变化:松开 ->按下抖动 ->按下 ->松开抖动 ->松开

3总结

本篇介绍了嵌入式软件开发中常用的状态机编程实现,并通过按键消抖实例,以常用的switch-case形式,实现了对应的状态机编程代码实现,并通过测试,串口打印对应状态,分析状态机的状态跳转过程。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
广厦拆队倒计时!胡金秋待售,林秉圣走人,民企没钱玩不转CBA了

广厦拆队倒计时!胡金秋待售,林秉圣走人,民企没钱玩不转CBA了

林小湜体育频道
2026-07-16 21:42:51
心理学:当一个雄性认定你时,他不会追你,不会哄你,甚至连多看你一眼都不肯,但他离开你的那一天你才会发现一个细思恐极的秘密

心理学:当一个雄性认定你时,他不会追你,不会哄你,甚至连多看你一眼都不肯,但他离开你的那一天你才会发现一个细思恐极的秘密

心理观察局
2026-07-16 06:56:24
与前队友斗殴冲突,不满ESPY颁奖!NBA3届全明星中锋恐成众矢之的

与前队友斗殴冲突,不满ESPY颁奖!NBA3届全明星中锋恐成众矢之的

兵哥篮球故事
2026-07-16 21:56:09
平均每30人就有1人爆仓!韩国股市暴涨暴跌,借钱炒股的散户快疯了

平均每30人就有1人爆仓!韩国股市暴涨暴跌,借钱炒股的散户快疯了

时代周报
2026-07-16 15:51:15
中国移动所作算不算“强盗”行为?

中国移动所作算不算“强盗”行为?

追月数星
2026-07-16 22:33:14
小鹏MONA L03正式上市,售价12.38万元起

小鹏MONA L03正式上市,售价12.38万元起

界面新闻
2026-07-16 21:51:39
特朗普:感谢伊朗善意之举

特朗普:感谢伊朗善意之举

凤凰卫视
2026-07-16 10:59:04
俄媒女主持人曾言:若中国愿出兵300万,俄军很快就能打败乌克兰

俄媒女主持人曾言:若中国愿出兵300万,俄军很快就能打败乌克兰

南宗历史
2026-03-17 16:53:10
人活多少岁最合适:一、41岁走,算短命;二、50 岁离去,还是偏早;三、60 岁辞世,留有遗憾......

人活多少岁最合适:一、41岁走,算短命;二、50 岁离去,还是偏早;三、60 岁辞世,留有遗憾......

品读时刻
2026-07-10 09:07:05
发现一个现象:越是分房睡、财务上 AA 制、不干涉对方隐私的夫妻,感情越没有温度,心中隔阂太深,把婚姻过成合租

发现一个现象:越是分房睡、财务上 AA 制、不干涉对方隐私的夫妻,感情越没有温度,心中隔阂太深,把婚姻过成合租

不二大叔
2026-07-15 00:02:34
日媒推测:中国已被6场可能的战争包围,最先爆发战争的不是台海

日媒推测:中国已被6场可能的战争包围,最先爆发战争的不是台海

君笙拂兮啊
2026-07-14 07:03:32
世界杯赔率:西班牙-178,夺冠概率58%,被看好小比分战胜阿根廷

世界杯赔率:西班牙-178,夺冠概率58%,被看好小比分战胜阿根廷

林子说事
2026-07-16 16:53:36
两性心理学:女人主动跟你说“例假来了”,其实是在告诉你这两句话

两性心理学:女人主动跟你说“例假来了”,其实是在告诉你这两句话

心理观察局
2026-07-09 06:15:06
上海程序员失业被裁,老婆宁愿净身出户也要离婚,有房贷存款为0

上海程序员失业被裁,老婆宁愿净身出户也要离婚,有房贷存款为0

捣蛋窝
2026-07-15 23:47:53
女篮世青赛8强对阵局势!中国队有望爆冷突围:或掀翻世界第3冲击四强?

女篮世青赛8强对阵局势!中国队有望爆冷突围:或掀翻世界第3冲击四强?

篮球快餐车
2026-07-16 17:58:25
乌克兰新旧之争:防长费多罗夫与总司令西尔斯基的“矛盾”

乌克兰新旧之争:防长费多罗夫与总司令西尔斯基的“矛盾”

项鹏飞
2026-07-16 21:50:15
世界杯早参丨阿根廷2比1逆转英格兰,连续两届进决赛;凯恩回应球队被绝杀;亚马尔决赛迎来曾为幼时的他洗澡的梅西

世界杯早参丨阿根廷2比1逆转英格兰,连续两届进决赛;凯恩回应球队被绝杀;亚马尔决赛迎来曾为幼时的他洗澡的梅西

红星新闻
2026-07-16 07:17:13
唇语专家解读世界杯上情侣吵架因为手机上的内容吵了起来

唇语专家解读世界杯上情侣吵架因为手机上的内容吵了起来

纵拥千千晚星
2026-07-16 13:45:23
曲波:当年留洋我连脚指甲都不能自己剪;走出去后要积极融入

曲波:当年留洋我连脚指甲都不能自己剪;走出去后要积极融入

懂球帝
2026-07-11 04:50:13
为什么费多罗夫离任后,乌克兰社交媒体几乎“刷屏”了?

为什么费多罗夫离任后,乌克兰社交媒体几乎“刷屏”了?

柯义在乌克兰
2026-07-16 06:49:21
2026-07-16 23:48:49
大方老师单片机
大方老师单片机
领单片机速学资料,点我头像~
259文章数 1140关注度
往期回顾 全部

科技要闻

苹果AI终于要来了:还能追上华为豆包们吗

头条要闻

扎波罗热核电站总工遭袭身亡 被指或改变俄乌冲突性质

头条要闻

扎波罗热核电站总工遭袭身亡 被指或改变俄乌冲突性质

体育要闻

逆天6后卫神阵,图赫尔活活坑死英格兰

娱乐要闻

天下无不散宴席!白鹿官宣告别欢娱

财经要闻

韩国股市暴涨暴跌 借钱炒股的散户快疯了

汽车要闻

新一代理想L6正式上市 24.98万元 标配高阶智驾/四驱

态度原创

教育
游戏
手机
旅游
公开课

教育要闻

首批市级档案文献遗产名录公布,府学胡同小学碑刻入选

网友“泄露”PS6手柄:空盒设计嘲讽索尼

手机要闻

哈苏Phocus Mobile相机配套应用首度登陆安卓平台

旅游要闻

不必奔赴人山人海景区,瓦渡静美石林,一条古道装下几代乡愁!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版