状态机入门第二式:if 判断变化无穷
要点: 用if else…else if结构的组合来描述状态流程图。
什么是状态流程图?我不想多解释,因为就那么个简单的东西,说多了反而神秘兮兮的。状态流程图你可以简单粗暴的认为,他就是流程图,等你用得多了,你就渐渐明白为啥多了“状态”二字;如果你后来或者先前学过状态图,那么很快你就会明白状态流程图比状态图“高级”了多少。
1、 不管怎么说,你可以先为你要处理的事物画一个流程图。如果流程图都不会画,就
不用凑热闹了。
2、 接下来,把流程图上每一个方框或者判断筐都“简单粗暴”地看成一个状态。
3、 将每一个状态用if结构表示出来
- if (<状态标志>) {
- //! 状态代码
- …
- }
4、 自己看着办,合并多余的状态,优化优化代码。
范例:
- //! 首先将布尔量的状态标志压缩在一个字节里面以节省内存开支
- typedef union {
- uint8_t Value;
- uint8_t Byte;
- struct {
- unsigned BIT0:1;
- unsigned BIT1:1;
- unsigned BIT2:1;
- unsigned BIT3:1;
- unsigned BIT4:1;
- unsigned BIT5:1;
- unsigned BIT6:1;
- unsigned BIT7:1;
- } Bits;
- }byte_t;
-
- #define FSM_ACTION_FLAG s_tbState.Bits
- #define FSM_STOP_ALL_ACTIONS() do {s_tbState.Value = 0;}while(0)
- #define FSM_START (0 == s_tbState.Value)
- #define FSM_STATE_A FSM_ACTION_FLAG.BIT0
- #define FSM_STATE_B FSM_ACTION_FLAG.BIT1
- …
- #define FSM_STATE_H FSM_ACTION_FLAG.BIT7
-
- bool fsm_example_B( <形参列表> ) {
- static byte_t s_tbState = {0}; //!< 定义状态变量
-
- if (FSM_START) { //!< 起始状态
- //! 这里放置状态机初始化的代码
- …
- FSM_STATE_A = true; //!< 进入状态B,start装台自动结束
- }
-
- if (FSM_STATE_A) { //!< 一个典型的简单状态
- //! 这里放置状态A的代码或者
- …
- //! 这里放置某些条件以开启别的状态
- if (<某些条件>) {
- //! 这里做一些“进入”下一个状态之前的准备工作
- FSM_STATE_B = true; //!< 开启下一个状态
- FSM_STATE_A = false; //!< 结束当前状态
- }
- }
-
- if (FSM_STATE_B) { //!< 一个典型的监视状态
- …
- //! 这里检测某些条件
- if (<某些条件>) {
- //! 这里做一些“开启”某个状态的准备工作
- FSM_STATE_C = true; //!< 开启某一个状态而不结束当前状态
- FSM_STATE_D = true; //!< 你当然可以一次触发多个状态
- …
- } else if (<某些条件>) {
- //! 满足某些条件以后关闭当前状态
- FSM_STATE_B = false;
- }
- }
- …
- if (FSM_STATE_F) { //!< 一个典型的子状态机调用
- if (!fsm_example_a(<实参列表>)) { //!< 等待子状态机返回false
- //!子状态机运行完成,进入下一状态
- …
- FSM_STATE_F = false; //!< 结束当前状态
- FSM_STATE_x = true; //!< 进入下一状态x代表某个字母
- }
- }
-
- if (FSM_STATE_H) { //!< 一个典型的中止状态
- //!< 某些状态机的操作,比如释放某些资源
- …
- FSM_STOP_ALL_ACTIONS(); //!< 复位状态机
- return false; //!< 返回false表示状态机结束
- }
-
- return true; //!< 返回true表示状态机保持运行
- }
总结: 从范例可知,这种状态机非常灵活,通过布尔变量的开启和关闭,你可以自由的控制某些状态的开启。同一时刻可能有多个状态是激活的。这种结构几乎可以翻译任何流程图。具体还有很多好处,可以在使用中体会。
|