不管做什么或者实现什么功能,必定会有实现需求的步骤,简单理解就是在某个状态下做某事,这就很符合C语言面向过程的特点,个人认为面向对象其实是面向过程的封装,封装的好处自然就是符合人的思维,以及便于后续的修改移植工作。
| 简单的状态机
相信读者们刚入门学习单片机的时候,应该比较常使用标志位来触发任务运行,这就是简单的状态机。
// 主函数 int main() { int flag = 0; while (1) { if( flag == 0 ) { task_A(); } else if( flag == 1 ) { task_B(); } else if( flag == 2 ) { task_C(); } ...... } }
往往判断语句太多不利于阅读,那就需要对上面的代码进行优化:
// 主函数 int main() { int flag = 0; while (1) { switch (flag) { case 0x00: task_A(); break; case 0x01: task_B(); break; case 0x02: task_C(); break; ...... default: break; } } }
| 封装状态机
在项目中使用状态机往往需要封装一下,避免全局变量标志到处飞就不好修改和维护项目,最好的方法就是高内聚低耦合。
void test(void) { static state; if( state == 0 ) { if( !task_A() ) { state = 1; } } else if( state == 1 ) { if( !task_B() ) { state = 2; } } else if( state == 2 ) { if( !task_C() ) { state = 0; } } } int main() { while (1) { test(); } }
| 附件
简单写个小demo,加深一下对状态机的理解,这些状态都是面向有限的状态而言。
#include "stdio.h" #include "stdint.h" typedef struct { uint8_t flag; }task_struct; // 触发任务 void task_open(task_struct *task) { if (!task->flag) { task->flag = !task->flag; } } // 关闭任务 void task_close(task_struct *task) { if (task->flag) { task->flag = !task->flag; } } // 任务初始化 void task_init(void) { /* 初始化 */ // printf("test init "); } // 任务处理 void task_handle(void) { printf("test handle "); } // 轮训任务 void task_A(task_struct *task, uint8_t type) { if (!task->flag) { task_init(); } else { if (!type) { /* 单次执行 */ task_handle(); /* 关闭任务 */ task_close(task); } else { /* 循环执行 */ task_handle(); } } } int main() { task_struct taskA; task_open(&taskA); while (1) { task_A(&taskA, 0); } }
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !