单片机应用程序的框架大概有三种:

1,简单的前后台顺序执行程序.

2,时间片轮询法.

3,应用操作系统.

下面我们主要来讲解时间片轮询法:

在这里我们先介绍一下定时器的复用功能。就是使用1个定时器,可以是任意的定时器,这里不做特殊说明,下面假设有3个任务,那么我们应该做如下工作:

1. 初始化定时器,这里假设定时器的定时中断为1ms(当然你可以改成10ms,这个和操作系统一样,中断过于频繁效率就低,中断太长,实时性差)。

2. 定义一个数值:
#define TASK_NUM   (3)                       //  这里定义的任务数为3,表示有三个任务会使用此定时器定时
uint16 TaskCount[TASK_NUM] ;           //  这里为三个任务定义三个变量来存放定时值,用于存放每个任务需要的时间
uint8  TaskMark[TASK_NUM];               //  同样对应三个标志位,为0表示时间没到,为1表示定时时间到

3. 在定时器中断服务函数中添加:
/**************************************************************************************
* FunctionName : TimerInterrupt()
* Description : 定时中断服务函数
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void TimerInterrupt(void)                   //定时器溢出之后就会进入到这里,可以是1ms,也可以是10ms
{
    uint8 i;

for (i=0; i<TASKS_NUM; i++)        //分别去查看每个任务,这里TASKS_NUM是表示任务的个数,这里是3个
    {
        if (TaskCount[i])                         //TaskCount[i],这个是代表第i个任务当前延迟的时间,如果没有到延迟时间到0,就继续延迟
        {
              TaskCount[i]--;                     //减少一个刻度
              if (TaskCount[i] == 0)           //如果TaskCount[i]为0,说明我们指定的时间到了
              {
                    TaskMark[i] = 0x01;       //TaskMark[i],表示第i个任务的延迟已经完成,可以执行了
              }
        }
   }
}

4. 在我们的应用程序中,在需要的应用  [延迟]  的地方添加如下代码:

TaskCount[0] = 20;        // 延时20ms,比如按键程序,需要我们每20ms检测一次,并不需要实时查看
TaskMark[0]  = 0x00;     // 启动此任务的定时器

到此我们只需要在任务中判断TaskMark[0] 是否为0x01即可。其他任务添加相同,至此一个定时器的复用问题就实现了。在等待一个定时的到来的同时我们可以循环判断标志位,同时也可以去执行其他函数。  [即:在一个函数运行的间隙中我们可以运行其他的函数]

那么如果我们在一个函数延时的时候去执行其他函数,充分利用CPU时间,是不是和操作系统有些类似了呢?但是操作系统的任务管理和切换是非常复杂的。下面我们就将利用此方法架构一个新的应用程序。

时间片轮询法的架构:

1.设计一个结构体:这个是定义的一个  模子, 用于扣蛋糕用的,  实际上是定义任务包括几个要素,我们把任务的要素都列出来,

这样就可以使每个任务都有规定格式的要素了

typedef struct _TASK_COMPONENTS      //任务结构体,任务的几个要素  [这个是很重要的]
{
    uint8 Run;                                               // 程序运行标记:0-不运行,1-运行  ,这里是程序会不会运行
    uint8 Timer;                                            // 计时器, 这个是用于在定时器中减减的
    uint8 ItvTime;                                          // 任务运行间隔时间, 这个是用于更新参数的
    void (*TaskHook)(void);                          // 要运行的任务函数
} TASK_COMPONENTS;                           // 任务定义

2. 任务运行标志出来,此函数就相当于中断服务函数,需要在定时器的中断服务函数中调用此函数,这里独立出来,便于移植和理解。
/**************************************************************************************
* FunctionName   : TaskRemarks()          //放到定时器中
* Description    : 任务标志处理
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskRemarks(void)                            //要放到  timer中断中
{
    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;            // 任务可以运行, 任务的延迟已经过了, 可以继续运行了
            }
        }
   }
}

3. 任务处理:实现任务管理操作, 用于循环判断哪个任务需要运行了
/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskProcess(void)
{
    uint8 i;
    for (i=0; i<TASKS_MAX; i++)           // 逐个任务时间处理
    {
         if (TaskComps[i].Run)                 // 这个标志不为0, 标志为0, 标志置1是在timer时间中断中, 是在时间查询那里的
        {
             TaskComps[i].TaskHook();      // 运行任务, 这个是一个函数, 在运行完这个函数后, 我们下一步操作就是清除标志位
             TaskComps[i].Run = 0;           // 标志清0
        }
    }   
}

假设我们有三个任务:时钟显示,按键扫描,和工作状态显示

1. 定义一个上面定义的那种结构体变量:
/**************************************************************************************
* Variable definition                           
**************************************************************************************/
static TASK_COMPONENTS TaskComps[] =
{   //0:程序刚开始不运行;  60:用于减减的计数;  60:函数重复周期,用于重装减减;  TaskDisplayClock:是一个函数名,用于重复运行的刷屏;
    {0, 60, 60, TaskDisplayClock},           // 显示时钟         
    {0, 20, 20, TaskKeySan},                   // 按键扫描
    {0, 30, 30, TaskDispStatus},              // 显示工作状态
     // 这里添加你的任务。。。。
};

在定义变量时,我们已经初始化了值,这些值的初始化,非常重要,跟具体的执行时间优先级等都有关系,这个需要自己掌握。

上面的结构体初始化表示,我们有三个任务:

①每1s执行一下时钟显示,因为我们的时钟最小单位是1s,所以在秒变化后才显示一次就够了。
②由于按键在按下时电平会抖动,而我们知道一般按键的抖动大概是20ms,那么我们在顺序执行的函数中一般是延迟20ms等待电平稳定后才开始采集电平,而这里我们每20ms扫描一次,效果是非常不错的,即达到了消抖的目的,也不会漏掉按键输入。
③为了能够显示按键后的其他提示和工作界面,我们这里设计每30ms显示一次,如果你觉得反应慢了,你可以让这些值小一点。

TaskDisplayClock, TaskKeySan,  TaskDispStatus 后面的名称是对应的函数名,你必须在应用程序中编写这函数来分别完成三个任务。

2. 任务列表:(也叫作任务清单)
typedef enum _TASK_LIST
{
    TAST_DISP_CLOCK,               // 显示时钟
    TAST_KEY_SAN,                     // 按键扫描
    TASK_DISP_WS,                     // 工作状态显示
     // 这里添加你的任务。。。。
     TASKS_MAX                                           // 总的可供分配的定时任务数目
} TASK_LIST;
好好看看,我们这里定义这个任务清单的目的其实就是参数TASKS_MAX的值,其他值是没有具体的意义的,只是为了清晰的表面任务的关系而已。

硬件——STM32 , 软件框架的更多相关文章

  1. stm32软件编程的框架及注意事项——rtos篇

    0.通常,嵌入式软件(这里指单片机系统)的框架千变万化,有带rtos的,也有裸机的. 0.1.写过带系统的,也写过裸机的,这里总结一下两个类型的框架,记录下自己的心得,主要是文字描述,框架图可以后期添 ...

  2. linux内核中的GPIO系统之(1):软件框架

    一.前言 作为一个工作多年的系统工程师,免不了做两件事情:培训新员工和给新员工分配任务.对于那些刚刚从学校出来的学生,一般在开始的时候总是分配一些非常简单的任务,例如GPIO driver.LED d ...

  3. 安装 SQL Server 2008 R2 的硬件和软件要求(转)

    以下各部分列出了安装和运行 SQL Server 2008 R2 的最低硬件和软件要求.有关 SharePoint 集成模式下的 Analysis Services 的要求的详细信息,请参阅硬件和软件 ...

  4. DM8168 DVRRDK软件框架研究

    转载注明:http://blog.csdn.net/guo8113/article/details/41120491 Netra(DM8168)处理器是个多核处理器,每一个核之间相互独立却又相互关联, ...

  5. 安装 SQL Server 2012 的硬件和软件要求(官方全面)

    以下各节列出了安装和运行 SQL Server 2012 的最低硬件和软件要求. 有关 SharePoint 集成模式下 Analysis Services 的要求的详细信息,请参阅硬件和软件要求(S ...

  6. 安装 SQL Server 2005 的硬件和软件要求(官方全面)

    SQL Server 2005 安装要求 本主题介绍了安装 SQL Server 205 的硬件和软件要求,以及查看安装文档的说明. 硬件和软件要求(32 位和 64 位) 访问 SQL Server ...

  7. Niagara解决设备连接应用的软件框架平台技术。

    Niagara 是Tridium公司所研发的设计用于解决设备连接应用的软件框架平台技术. Niagara是一种应用框架,或者说是软件框架,特别设计用于应对智能设备所带来的各种挑战,包括设备连接到企业级 ...

  8. WinForm酒店管理软件--框架

    WinForm酒店管理软件--框架 搞软件开发4年多了,现在自认为还是菜鸟,从一开始走上工作岗位各种技术对我都很新奇没解决一个问题都觉得很伟大到后来开始对出路的迷茫,到现在我坚信学什么技术不重要,做什 ...

  9. STM32软件复位(基于库文件V3.5)

    源:STM32软件复位(基于库文件V3.5) void SoftReset(void) { __set_FAULTMASK(); // 关闭所有中端 NVIC_SystemReset();// 复位 ...

随机推荐

  1. WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了

    原文:WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了 版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4 ...

  2. hzwer 模拟题 祖孙询问

    祖孙询问 题目描述 已知一棵n个节点的有根树.有m个询问.每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系. 输入输出格式 输入格式: 输入第一行包括一个整数n表示节点个数. 接下来n行每行一 ...

  3. 洛谷 P1889 士兵站队

    P1889 士兵站队 题目描述 在一个划分成网格的操场上, n个士兵散乱地站在网格点上.由整数 坐标 (x,y) 表示.士兵们可以沿网格边上.下左右移动一步,但在同时刻任一网格点上只能有名士兵.按照军 ...

  4. JNI之——Can&#39;t load IA 32-bit .dll on a AMD 64-bit platform错误的解决

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46605003 在JNI开发中,Java程序须要调用操作系统动态链接库时,报错信息: ...

  5. HDU 5384 Danganronpa (AC自己主动机模板题)

    题意:给出n个文本和m个模板.求每一个文本中全部模板出现的总次数. 思路:Trie树权值记录每一个模板的个数.对于每一个文本跑一边find就可以. #include<cstdio> #in ...

  6. centOS6.3(64bit)Hadoop的Eclipse开发环境搭建

    操作系统centos6.3(64位) 一个namenode 两个datanode Hadoop版本号:hadoop-1.1.2 Eclipse版本号:eclipse-standard-kepler-S ...

  7. vue -- 跨域cookie 丢失的问题

    前端使用了vue-reource的$http进行请求后台接口 登陆完成后,服务端监控发现无法拿到cookie,下面看几张前端控制台监控的图 reqqust Header  没有显示cookie 信息 ...

  8. 2017国家集训队作业[agc016e]Poor Turkey

    2017国家集训队作业[agc016e]Poor Turkey 题意: 一开始有\(N\)只鸡是活着的,有\(M\)个时刻,每个时刻有两个数\(X_i,Y_i\),表示在第\(i\)个时刻在\(X_i ...

  9. ActiveMQ学习总结(3)——spring整合ActiveMQ

    1.参考文献 Spring集成ActiveMQ配置 Spring JMS异步发收消息 ActiveMQ 2.环境 在前面的一篇ActiveMQ入门实例中我们实现了消息的异步传送,这篇博文将如何在spr ...

  10. 平衡数之Treap

    #include <memory>//智能指针头文件 #include <random>//随机数头文件 #include <iostream> #include ...