状态机程序
基于时间状态机是在一个定时器的协调下周期扫描执行各个任务:步骤如下:
一 首先定义一个回调函数的结构体:包含计时计数器,延时时间,空类型的指针(做函数参数用),以及一个指针函数(注意参数和返回值)
二 用自定义的数据类型顶一个指针数组:最后一项指针函数为NULL.
三 用单片机的一个定时器作为系统的协调中心:心跳=基本定时,延时值都为心跳的整数倍,在定时器ISR中逐个对结构体的计数器加1
四 在主函数中在不等于指针数组最后一项的情况下逐个比较其计时计数器的值与延时值是否相等,相等则开始执行回调函数。
注意事项:
1指针数组的各个延时值之间最好不能是整数倍的情况,因为这样容易造成并发可能使系统负荷不均匀。
2 将状态机查询放在主函数中进行,不必另起一个函数,因为反复的调用函数,栈太深,入栈出栈开销大。
3 状态机程序在调试各模块时很有用,结构也很清晰。
4 状态机中有一个重要的原则就是不用delay(t)这种阻塞函数:可以用另外一个自由永不停止定时器作为超时计数器(基本定时1ms),在定义一个u32的全局变量作为当前的计数值,每个状态处理时先读当前计数器的值,在需要时间触发条件的地方与当前值进行差值比较,超时则触发否则return退出。这样一来状态机就有伪并发的特点不会阻塞效率低了。但如果遇到18B20等时序严格的us级延时还是要死等的。
二 基于时间的状态机:
傻孩子的状态机 simple fsm:利用掩码结构体实现了私有保护,利用高级宏的操作编写的状态机C脚本。
核心是记录断点位置,然后从断点恢复运行。
Protothread或者叫Coroutine,主要就是提供continuation point。即函数从yield返回后,下次调用会接着yeild的下一句执行。目的之一是简化代码结构,增强可读性;
如果使用可移植的switch来实现,那么限制超多,不能用switch了;如果使用GNU的computed goto来实现,则没有这个限制;
但是不管是什么实现,都需要注意,如果你希望函数的auto变量保存上次的值的话,必须声明成static,这才是这类在C语言中实现coroutine类机制的本质限制。