不管做什么或者实现什么功能,必定会有实现需求的步骤,简单理解就是在某个状态下做某事,这就很符合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条评论
快来发表一下你的评论吧 !