当前位置:
文档之家› 单片机基于状态机和任务队列的程序设计
单片机基于状态机和任务队列的程序设计
4.结论及实际应用效果 合理的程序框架对于一个软件项目的重要性是不言而喻的。它体现了一个项
目规划的合理性、清晰性,使开发过程中软件的编制更加模块化,更便利了后期 的软件功能扩展及维护。而文中基于状态机和任务队列的程序框架便能够满足以 上的各种需求。笔者在 XXXXXX 股份有限公司开发高低压固态软起动器软件中便 利用了此项技术,该类产品的软件性能及实时性在公司内部都经过了大量的严格 验证,通过实验证明完全达到了预期的效果,并且产品在客户现场的使用中也获 得了极大的成功。
case STATE2: if(条件满足) { … TaskState = STATE3; //进入下一个状态 } Break; . .
case STATEN: if(条件满足) { … TaskState = STATE1; //回到状态 1 } Break;
Default: TaskState = STATE1; //回到状态 1 Break;
}
2.2 任务队列实现原理[2] 在已划分的多个任务中,有些任务的实时性要求较高,而有些较低。对于实
时性要求较低的任务,我们就可以用任务队列来管理他们。当一个低实时性要求 的任务被触发时(被中断或其他任务触发),我们可以将它放入队列中,让其等 待其他先入队的任务执行完毕后再执行。这样就有效的避免了多个实时性要求低 的任务在主循环一次全被执行的现象,从而为单片机腾出更多的时间处理实时性 要求较高的任务。下面通过一个例子来描述任务队列的应用:
#define Task1 1 #define Task2 2 #define Task3 3 unsigned char PopTaskFromQueue(void);//读取队列中的任务
void PushTaskInQueue(unsigned char TaskID); //把任务放入队列
void main(void)
if(3 秒钟执行一次) PushTaskInQueue(Task3);
} 上面的程序通过宏定义为每个任务定义了一个 ID 号,通过在定时器中断函 数中设立时基,每 1 秒、2 秒、3 秒分别触发一次 Task1、Task2、Task3。而 PushTaskInQueue 和 PopTaskFromQueue 函数在这个触发过程中以任务 ID 号为标 识,组织着任务的触发和执行。对于 PushTaskInQueue 和 PopTaskFromQueue 函 数的实现我们可以查阅相关数据结构类的书籍,在此就不赘述。
{
…
while(1)
{
DoOtherTask(); //其他高实时性要求的任务
switch(PopTaskFromQueue())//读取队列中的任务 ID,根据出列的
{
任务 ID 来决定要执行的任务
case Task1:
DoTask1();break;
case Task2:
DoTask2();break;
参考文献 [1]普拉塔(Prata S) C Primer Plus(第 5 版) [M] 北京:人民邮电出版社 2005 年 [2]周航慈 嵌入式系统软件设计中的数据结构 [M] 北京:北京航空航天大学出版社 2008 年
1.引言 随着半导体技术的发展,单片机的集成规模越来越大,时钟频率也越来越高,
单片机机已广泛应用于仪器仪表,家用电器,医用设备,工控设备等领域。同时 单片机需要实现的功能更复杂,任务数量也更多了。虽然目前大部分 32 单片机 已经可以跑微内核嵌入式实时系统,但考虑到系统开发的周期、成本及实时性, 有时设计一个合理的程序框架往往能达到事半功倍的效果。本文将介绍一种基于 状态机和任务队列的程序设计思想。
3.基于状态机和任务队列的程序框架 上面已经介绍了状态机和任务队列的实现原理,接下来将介绍如何合理利用
状态机和任务队列来规划整个程序的框架。 在规划整体程序框架前,可以根据其功能要求并结合底层硬件模块的不同将
整个软件系统分为多个任务。比如在某个项目中,可以划分为按键检测任务、串 口 1 通信任务、串口 2 通信任务、电量采集换算任务、IO 输入输出任务、及人 机交互显示界面任务等。
case Task3:
DoTask3();break;
…
default:break;
}
}
}
interrupt TimerISR(void) //定时器中断函数,用来做任务触发时基 {
if(1 秒钟执行一次) PushTaskInQueue(Task1);
if(2 秒钟执行一次) PushTaskInQueue(Task2);
2.状态机和任务队列实现原理 2.1 状态机实现原理
每个任务的执行往往可以划分为多个状态,这样我们就可以把每个任务看成 状态机一样,在每个状态中一步步的切换。程序在每个状态中通过各种条件判断 语句可以知道该状态的执行是否完成,如果完成则切换状态到下一个状态,反之 则使该任务继续停留在此状态,接着程序跳出该任务转而执行其他任务去了。这 样我们就可以保证任务的执行只需进行简单条件判断即可,而不需让程序一直运 行在此任务中,占用宝贵的时间。对于任务的状态划分我们可以通过画流程图来 实现,如图 1 所示。
在每个任务划分明确以后,按照上述讲的状态机实现原理把每个任务分为多 个状态,然后再用编程语言按照状态机的流程编写出每个任务。这样就完成了一 个任务模块的编制。
最后根据任务的实时性需求,对于实时性要求最高的任务可以放入中断中执 行,对于实时性要求比较高的或放入中断中执行时间过长的任务可以放入程序的 主循环中,对于实时性要求不高的任务则状态的条件?
状态 2 是否满足进入下一个
状态的条件?
状态 N 任务执行完毕 ,回
到状态 1
用 C 语言开发单片机程序时[1],实现状态机最好的方式是通过采用 switch 语句。程序的实现思路如下:
Switch(TaskState) {
case STATE1: if(条件满足) { … TaskState = STATE2; //进入下一个状态 } Break;
单片机基于状态机和任务队列的程序设计
张强 ucos_hqu@ XXXX 股份有限公司 XX 000000 摘要:基于状态机和任务队列的程序设计思想,是将系统划分为多个任务,将每个任务尽量 多的划分为多个状态,这样可以大大减少每次执行该任务的时间。同时把实时性要求不高的 任务放进任务队列中进行“排队”,等候其前面的任务执行完毕后再执行。而实时性要求最 高的事件则可以放在中断中执行。 关键字:单片机、状态机、任务队列、程序框架