本文设计了一种基于分层设计的小家电控制板通用程序框架。分层设计有以下优点:
(1)降低系统复杂度。由于每层都是相对独立的,每层可以单独实现。
(2)隔离变化。通过分层设计,可以把变化的部分独立出来,让它们的变化不会给其他部分带来大的影响。
(3)具有良好的程序可移植性。
(4)具有良好的程序可维护性。
本文的程序框架以市电过零中断20ms,作为程序运行的滴答时钟。在主循环里每到20ms,执行一次,每次主程序循环一次的时间要小于20ms,且尽可能小,保证程序能及时响应。本文的分层设计,定义了三层架构;
第一层:系统层,位于程序最顶层。
第二层:任务层,系统层下的工作任务分配,位于程序中间层。
第三层:执行层,任务层下的执行过程,位于程序最底层。
图1 分层结构图
本文分层设计的实现过程:
1.针对小家电产品,系统层一般定义为四种事务:待机,开机,工作,告警。对于不同的小家电产品功能需求,系统层的事务定义可以适当裁剪或者增加。当接收到外部事件触发时,可以从一种事务切换到另一种事务。外部事件可以是按键,也可以是程序的事务处理,比如在工作事务,检测到异常,可以跳转到告警事务。
2.每种系统层的事务又有多个任务组成,以系统层下的工作事务为例,可以分为任务1,任务2,…,任务N。任务的切换一般是顺序切换,也就是执行完当前任务后,就跳转到下一任务。在任务层,当接收到外部事件触发时,可以返回到系统层。
3.每个任务下又可以分为多个执行过程,比如执行过程1,执行过程2,…,执行过程N。执行过程的切换和任务的切换类似,也是顺序切换。在执行层,当接收到外部事件触发时,可以返回到任务层或者系统层。
图2 小家电产品分层结构图
主程序代码框架:
Sys_State,Task_State,Exec_State分别对应系统层,任务层,执行层变量,程序运行中通过获取该三个变量的值,可知道程序当前运行在哪个状态下,具有良好的程序的可维护性。
bit time20ms;
unsigned char Sys_State; //对应系统层
unsigned char Task_State; //对应任务层
unsigned char Exec_State; //对应执行层
void Sys_Standy(void);
void Sys_PowerOn(void);
void Sys_Work(void);
void Sys_Alarm(void);
while(1)
{
if (time20ms)
{
time20ms = 0;
switch(Sys_State)
{
case 待机:
Sys_Standy();
break;
case 开机:
Sys_PowerOn();
break;
case 工作:
Sys_Work();
break;
case 告警:
Sys_Alarm();
break;
default:
break;
}
}
}
系统层下的工作事务代码框架
void Work_Task1(void);
void Work_Task2(void);
...
void Work_TaskN(void);
void Sys_Work(void)
{
switch(Task_State)
{
case 任务1:
Work_Task1();
break;
case 任务2
Work_Task2();
break;
...
case 任务N:
Work_TaskN();
break;
default:
break;
}
}
工作事务下的任务1代码框架
void Work_Task1_Exec1(void);
void Work_Task1_Exec2(void);
...
void Work_Task1_ExecN(void);
void Work_Task1(void)
{
switch(Exec_StateState)
{
case 执行过程1:
Work_Task1_Exec1();
break;
case 执行过程2:
Work_Task1_Exec2();
break;
...
case 执行过程N:
Work_Task1_ExecN();
break;
default:
break;
}
}
从示例代码可以看出,每一层的代码结构类似,都是基于状态机的编程。在设计过程中,需要定义好每一层的状态。当然并不是所有的系统层下都有任务层和执行层,任务层和执行层可以都没有,也可以只有任务层,这需要根据具体的小家电产品的功能需求来设计。任务层可以理解成当前系统层下有哪几个任务,执行层可以理解为完成某个任务有哪几个过程步骤。小家电产品的功能一般是顺序执行的过程,我们可以将功能细分成各个任务,每个任务在细分成各个执行过程。