单片机程序编写常使用的程序架构

您所在的位置:网站首页 c语言基本框架包括 单片机程序编写常使用的程序架构

单片机程序编写常使用的程序架构

2024-06-22 17:30| 来源: 网络整理| 查看: 265

单片机程序编写常使用的程序架构 0、前言1、顺序执行法2、时间片轮询法3、操作系统

0、前言

  对于做嵌入式开发,或者单片机开发的工程师来说,编写程序肯定是家常便饭,对于程序,大家肯定都不陌生。但是无论你是刚毕业的应届生,还是久经职场的工程师,在编写程序时,考虑程序架构是非常有必要的事情。但是往往实际开发中,真正考虑好的程序架构的恐怕并不多。随着程序开发的难度以及复杂度的增加,没有一个好的程序架构,往往会使开发者在编写程序的过程中产生逻辑混乱。   当然,我也是一个普通的软件工程师,前人已经给我们总结出了优秀的程序架构,我们只要理解它们,并运用到自己的开发项目中,用着用着你就知道程序架构带来的好处了。目前,单片机程序的架构大致分为三种:

1、顺序执行法:这类写法是大多数人使用的方法,根据产品的工作逻辑,从上往下的执行顺序来编写应用程序即可,不需要考虑程序的具体架构。

2、时间片轮询法:这种方法是介于顺序执行法和操作系统之间的一种方法。本文也是主要对该方法的总结与讨论。

3、操作系统:这种方法是程序编写的最高境界,即单片机中嵌入实时操作系统,然后再操作系统的基础上进行编程。但是,上操作系统的话对单片机的硬件要求比较高,一般普通的或者8位的单片机还是不足以上操作系统的。

1、顺序执行法

  在应用程序比较简单,实时性,并行性要求不太高的情况下,使用顺序执行法进行编程是不错的方法,程序设计简单,思路也比较清晰。但是,当应用程序比较复杂的时候,如果没有一个完整的流程图,编写应用程序的工程师在写逻辑的时候会混乱。不利于在程序功能增加是进行代码维护和优化。特别是当多个任务需要用到定时器且定时时间不一样是,就需要增加标记变量和定时变量来加以区分,最终虽然能够实现功能,但是可能逻辑思维并不是很清晰,一直处于混乱状态。   大多数人采用这种方法的原因是,一开始接触学习单片机的时候就一直以这种方式在写程序。而且在开发项目的过程中,从来没有去考虑过程序结构的问题,对于我们这边没有学过数据结构,程序架构的人单片机工程师来说,在程序设计上基本为零。

顺序结构如下面的程序模型:

/************************************************ *函数名称:main *函数功能:主函数 *输入参数:void *输出返回:void *************************************************/ void main(void) { uint8 keyValue; InitSys(); // 初始化 while (1) { TaskDisplayClock(); keyValue = TaskKeySan(); switch (keyValue) { case x: TaskDispStatus(); break; ... default: break; } } } 2、时间片轮询法

  时间片轮询法,很多时候都是与操作系统一起出现的,因为很多操作系统中就使用了这种方法。许多刚入门的工程师当然还没有机会学习和掌握多任务处理的操作系统开发模式。但是,在使用和学习多任务操作系统开发之前,我们依然需要一种开发模式,它能够在某种程度上和多任务与的操作系统类型,能够实现某种意义上的时间片轮询执行的模式。   当然,这种程序设计模式很多工程师也许都已经在使用了,使用起来比我还要好,还要高明。但是,很多搞那个出来的学生或者还没有出来的学习就没有这个机会看到这种处理模式了。其实,时间片轮询法,就是对定时器的应用,一个定时器多出复用,定时器产生一个1ms,或者10ms,或者100ms的定时周期,给每个需要执行的任务设置好执行任务的周期,直白点就是多久执行一次任务1,多久执行一次任务2,然后以定时器的周期进行计时,一旦时间到了就执行相应的任务。 **注意:**定时器初始化时的定时中断时间不可以过短也不可以过长,时间太短,中断过于频繁效率低,中断太长,实时性就差。

/** ****************************************************************************** * @文件名 : Task.h * @作 者 : JayYang * @版 本 : V1.0.0 * @日 期 : 2021年04月22日 * @摘 要 : 任务执行头文件 ******************************************************************************/ #ifndef __TASK_H__ #define __TASK_H__ /*------------------------------- 包含的头文件 -------------------------------*/ /*---------------------------------- 宏定义 ----------------------------------*/ #define TASK_MAX 3 //定义会使用定时器定时的任务数方式一 #define NotRunning 0 //初始运行状态标志为未运行 //每个任务运行的间隔时间,目前定时器是10ms中断一次 #define TaskTimer1 10 #define TaskTimer2 20 #define TaskTimer3 30 /*--------------------------------- 类型定义 ---------------------------------*/ /* typedef enum{ TASK_1, TASK_2, TASK_3, // 这里添加你的任务..... TASK_MAX // 总的可供分配的定时任务数目,定义会使用定时器定时的任务数方式二 }Task_List_e; //这里定义这个任务列表的目的其实就是参数TASK_MAX的值,其他值是没有具体的意义的,只是为了清晰的表面任务的关系而已 */ typedef struct{ unsigned char RunningStatus; //运行状态标志位:0-不运行;1-运行 unsigned char TimerCountDown; //定时器计数变量,进行--计数 unsigned char TimerInitialVal; //定时器定时初值,也就是每个任务运行的间隔时间 void (*TaskHandler)(void); //任务处理程序函数指针 }TaskManage_t; //定义任务管理结构体,它包含了一个任务所需要的所有信息 typedef struct{ void (*TaskMarks)(void); //任务定时标志位处理函数,[定时器中断函数中调用] void (*TaskProcess)(void); //任务处理函数,[主循环中调用] }Task_t; //定义任务结构体 /*--------------------------------- 变量定义 ---------------------------------*/ extern Task_t Task; /*--------------------------------- 函数声明 ---------------------------------*/ #endif /** ****************************************************************************** * @文件名 : Task.c * @作 者 : JayYang * @版 本 : V1.0.0 * @日 期 : 2021年04月22日 * @摘 要 : 任务执行源文件 ******************************************************************************/ /*------------------------------- 包含的头文件 -------------------------------*/ #include "bsp.h" /*---------------------------------- 宏定义 ----------------------------------*/ /*--------------------------------- 变量定义 ---------------------------------*/ /*--------------------------------- 函数声明 ---------------------------------*/ static void TaskMarks(void); //任务定时标志位处理函数 static void TaskProcess(void); //任务处理函数 static void Task1(void); //任务1 static void Task2(void); //任务2 static void Task3(void); //任务3 TaskManage_t TaskManage[] = { {NotRunning,TaskTimer1,TaskTimer1,Task1}, {NotRunning,TaskTimer2,TaskTimer2,Task2}, {NotRunning,TaskTimer3,TaskTimer3,Task3} }; Task_t Task = {TaskMarks,TaskProcess}; /*--------------------------------- 函数定义 ---------------------------------*/ /************************************************ *函数名称:TaskMarks *函数功能:任务定时标志位处理函数 * 这个函数是用来更新每个任务的计数器以及它们的运行标志位的, * 它是写在单片机的定时器中断服务函数中的 *输入参数:void *输出返回:void *************************************************/ static void TaskMarks(void) { unsigned char i; //逐个任务进行时间计算 for (i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3