C语言软件程序架构设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} /***************************************************************************** ********* * FunctionName : TaskDispStatus() * Description : 工作状态显示 * EntryParameter : None * ReturnValue : None ****************************************************************************** ********/ void TaskDispStatus(void)
*********
* FunctionName : TaskDisplayClock()
* Description : 显示任务 * EntryParameter : None * ReturnValue : None ****************************************************************************** ********/ void TaskDisplayClock(void) {
// 计时器
uint8 ItvTime;
ቤተ መጻሕፍቲ ባይዱ
// 任务运行间隔时间
void (*TaskHook)(void);
// 要运行的任务函数
} TASK_COMPONENTS;
// 任务定义
在结构体变量定义后,进行初始化(按照三个功能模块设定好初始值):
static TASK_COMPONENTS TaskComps[] =
时间片轮询法
对于一个单片机程序员来说,接受一个项目,在软件设计方面,你首先需要 考虑的是如何安排你的功能函数使之达到你的项目要求。也就是说你得有个自己 的软件架构。
对于像我这种菜鸟级的程序员来说,就是采用简单的顺序执行,需要什么功 能就添加什么功能函数。这样做应付小项目非常快,但一旦项目的功能复杂,随 着函数的不断增加,程序将会变得混乱。面对大的项目,如果一定要使用这种顺 序执行法,则程序员本人应当在接手项目时,保持设计思路的清晰,设计好完整 的流程图。
4、任务处理
void TaskProcess(void)
{
uint8 i; for (i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{ if (TaskComps[i].Run)
// 时间不为 0
{ TaskComps[i].TaskHook(); TaskComps[i].Run = 0;
任务:我们现在有一个任务可以细分为三个功能模块:时钟显示、按键扫描 和工作状态显示。我们的程序应当这么进行:
1、 设计一个结构体并完成初始化 // 任务结构
typedef struct _TASK_COMPONENTS
{
uint8 Run;
// 程序运行标记:0-不运行,1 运行
uint8 Timer;
// 运行任务 // 标志清 0
}
}
}
此函数就是判断什么时候该执行哪一个任务了,实现任务的管理操作,应用者
只需要在 main()函数中调用此函数就可以了,并不需要去分别调用和处理任务函
数。
/*****************************************************************************
操作系统不是一句两句就能说得清楚的。如果你能驾驭那最好不过,如果你 对之不熟悉,就不说操作系统本身的复杂性,其移植这一块就需要花费相当多的 时间和精力。
时间片轮询法,本人也是在电子工程论坛看到 zhaojun_xf 的《浅谈单片机应 用程序架构》一文才知道这种软件架构的。下面就通过一个具体的例子来熟悉下 时间片轮询法的架构和具体应有。
3、中断服务函数
void TaskRemarks(void)
{
uint8 i;
for (i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{
if (TaskComps[i].Timer)
// 时间不为 0
{
TaskComps[i].Timer--;
// 减去一个节拍
if (TaskComps[i].Timer == 0) // 时间减完了
{
// 恢复计时器值,从新下一次
TaskComps[i].Timer = TaskComps[i].ItvTime;
TaskComps[i].Run = 1;
// 任务可以运行
}
}
}
}
此函数放入中断服务函数。在中断中逐个判断,如果定时值为 0 了, 表示没有使用此定时器或此定时器已经完成定时,不作处理。否则定时 器减一,直到为零时,相应标志位值 1,表示此任务的定时值到了。
{
{0, 60, 60, TaskDisplayClock},
// 显示时钟
{0, 20, 20, TaskKeySan},
// 按键扫描
{0, 30, 30, TaskDispStatus},
// 显示工作状态
// 这里添加你的任务。。。。
};
2、 任务列表 // 任务清单
typedef enum _TASK_LIST
{
TAST_DISP_CLOCK,
// 显示时钟
TAST_KEY_SAN,
// 按键扫描
TASK_DISP_WS,
// 工作状态显示
// 这里添加你的任务。。。。
TASKS_MAX
// 总的可供分配定时任务数目
} TASK_LIST
此任务清单只是为了很好的展示任务的关系,我们所要的只是总任务数
这一项。与 #define TASK_NUM (3) 语句作用是一致的。
由上文可知,该方法程序结构清晰,程序简单,易于后期维护。
时间片轮询法所需要注意的是: 1、 任务的划分
掌握自己项目所实现的功能,将其划分为多个功能模块,每个 功能模块一个任务处理函数。 2、任务的优先 3、任务的执行 任务一定要时间速度快。任务中不能调用大的延时函数,也不 能因为某个任务需要等待而影响其他任务。 4、时间的划分 保证任务能在此时间内完成。
{ }
// 这里添加其他任务。。。。。。。。。
各任务处理函数根据自己项目需要编写。
5、主函数
int main(void)
{
InitSys();
// 初始化
while (1)
{
TaskProcess();
// 任务处理
}
}
时间片轮询法的架构就写完了,你可以根据自己的任务写任务处 理函数,根据时间性能的要求,确定定时中断函数的时间值。
} /***************************************************************************** ********* * FunctionName : TaskKeySan() * Description : 扫描任务 * EntryParameter : None * ReturnValue : None ****************************************************************************** ********/ void TaskKeySan(void) {
*********
* FunctionName : TaskDisplayClock()
* Description : 显示任务 * EntryParameter : None * ReturnValue : None ****************************************************************************** ********/ void TaskDisplayClock(void) {
// 计时器
uint8 ItvTime;
ቤተ መጻሕፍቲ ባይዱ
// 任务运行间隔时间
void (*TaskHook)(void);
// 要运行的任务函数
} TASK_COMPONENTS;
// 任务定义
在结构体变量定义后,进行初始化(按照三个功能模块设定好初始值):
static TASK_COMPONENTS TaskComps[] =
时间片轮询法
对于一个单片机程序员来说,接受一个项目,在软件设计方面,你首先需要 考虑的是如何安排你的功能函数使之达到你的项目要求。也就是说你得有个自己 的软件架构。
对于像我这种菜鸟级的程序员来说,就是采用简单的顺序执行,需要什么功 能就添加什么功能函数。这样做应付小项目非常快,但一旦项目的功能复杂,随 着函数的不断增加,程序将会变得混乱。面对大的项目,如果一定要使用这种顺 序执行法,则程序员本人应当在接手项目时,保持设计思路的清晰,设计好完整 的流程图。
4、任务处理
void TaskProcess(void)
{
uint8 i; for (i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{ if (TaskComps[i].Run)
// 时间不为 0
{ TaskComps[i].TaskHook(); TaskComps[i].Run = 0;
任务:我们现在有一个任务可以细分为三个功能模块:时钟显示、按键扫描 和工作状态显示。我们的程序应当这么进行:
1、 设计一个结构体并完成初始化 // 任务结构
typedef struct _TASK_COMPONENTS
{
uint8 Run;
// 程序运行标记:0-不运行,1 运行
uint8 Timer;
// 运行任务 // 标志清 0
}
}
}
此函数就是判断什么时候该执行哪一个任务了,实现任务的管理操作,应用者
只需要在 main()函数中调用此函数就可以了,并不需要去分别调用和处理任务函
数。
/*****************************************************************************
操作系统不是一句两句就能说得清楚的。如果你能驾驭那最好不过,如果你 对之不熟悉,就不说操作系统本身的复杂性,其移植这一块就需要花费相当多的 时间和精力。
时间片轮询法,本人也是在电子工程论坛看到 zhaojun_xf 的《浅谈单片机应 用程序架构》一文才知道这种软件架构的。下面就通过一个具体的例子来熟悉下 时间片轮询法的架构和具体应有。
3、中断服务函数
void TaskRemarks(void)
{
uint8 i;
for (i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{
if (TaskComps[i].Timer)
// 时间不为 0
{
TaskComps[i].Timer--;
// 减去一个节拍
if (TaskComps[i].Timer == 0) // 时间减完了
{
// 恢复计时器值,从新下一次
TaskComps[i].Timer = TaskComps[i].ItvTime;
TaskComps[i].Run = 1;
// 任务可以运行
}
}
}
}
此函数放入中断服务函数。在中断中逐个判断,如果定时值为 0 了, 表示没有使用此定时器或此定时器已经完成定时,不作处理。否则定时 器减一,直到为零时,相应标志位值 1,表示此任务的定时值到了。
{
{0, 60, 60, TaskDisplayClock},
// 显示时钟
{0, 20, 20, TaskKeySan},
// 按键扫描
{0, 30, 30, TaskDispStatus},
// 显示工作状态
// 这里添加你的任务。。。。
};
2、 任务列表 // 任务清单
typedef enum _TASK_LIST
{
TAST_DISP_CLOCK,
// 显示时钟
TAST_KEY_SAN,
// 按键扫描
TASK_DISP_WS,
// 工作状态显示
// 这里添加你的任务。。。。
TASKS_MAX
// 总的可供分配定时任务数目
} TASK_LIST
此任务清单只是为了很好的展示任务的关系,我们所要的只是总任务数
这一项。与 #define TASK_NUM (3) 语句作用是一致的。
由上文可知,该方法程序结构清晰,程序简单,易于后期维护。
时间片轮询法所需要注意的是: 1、 任务的划分
掌握自己项目所实现的功能,将其划分为多个功能模块,每个 功能模块一个任务处理函数。 2、任务的优先 3、任务的执行 任务一定要时间速度快。任务中不能调用大的延时函数,也不 能因为某个任务需要等待而影响其他任务。 4、时间的划分 保证任务能在此时间内完成。
{ }
// 这里添加其他任务。。。。。。。。。
各任务处理函数根据自己项目需要编写。
5、主函数
int main(void)
{
InitSys();
// 初始化
while (1)
{
TaskProcess();
// 任务处理
}
}
时间片轮询法的架构就写完了,你可以根据自己的任务写任务处 理函数,根据时间性能的要求,确定定时中断函数的时间值。
} /***************************************************************************** ********* * FunctionName : TaskKeySan() * Description : 扫描任务 * EntryParameter : None * ReturnValue : None ****************************************************************************** ********/ void TaskKeySan(void) {