时间片轮询法

注: 我看了,网上大多数博客都是用这份代码做讲解,所以我也是用它来说明自己的理解,我是在微信上看到的这篇文章,等我找到原作者,我再附上转载链接

时间片轮询法_第1张图片

文章目录

  • 序言
  • 基本思想
  • 代码实现
    • 任务结构体
    • 任务数组
    • 任务列表
    • 标志位处理函数
    • 任务处理函数
    • 任务函数
    • 中断服务函数
    • 主函数
  • 架构图解
  • 总结

序言

程序开发分为几种模式:裸机开发,时间片轮询,系统级开发。裸机开发,有过单片机开发经验的朋友应该都很熟悉了,这是一种没有任何架构设计的开发,一套程序从头到尾。时间片轮询,这是我们今天要介绍的对象,也是我最近新get到的技能,我们待会儿详说。系统级开发,这是我将来打算发展的方向,但是由于目前还在理论储备阶段,所以没有任何开发经验。等过几年再说。所以我们今天的主角是:时间片轮询法

基本思想

举个例子,有一个函数A,我们给它设置一个计数器B(程序多久执行一次)和一个状态标志位C(用来判断这个程序是否需要执行)还有一个计数填充值D,其中的B会被单片机自带的定时器中断服务函数不断地刷新(递减刷新),当B到0的时候C会被置位,同时B会被重新填满D值,当主程序运行到A的时候不会直接去运行它,而是先检查C,如果C没有被置位,说明还没有到A的执行时间,不执行A,如果C被置位了,就执行A,执行完后将C复位,让C再等上一段时间才再次被执行。

代码实现

任务结构体

下面是任务结构体,它包含了一个任务所需要的所有信息,包括运行状态标志位,计数器,计数器数值填充器(任务运行间隔时间)以及这个任务对应的函数指针

// 任务结构
typedef struct _TASK_COMPONENTS
{
    uint8 Run;                  // 程序运行标记:0-不运行,1运行
    uint8 Timer;                // 计时器
    uint8 ItvTime;              // 任务运行间隔时间
    void (*TaskHook)(void);    // 要运行的任务函数
} TASK_COMPONENTS;       // 任务定义

任务数组

下面是任务数组,当我们需要添加一个任务到时间片轮询队列中的时候,我只需要再这里添加函数指针,设置好相关参数就可以了

static TASK_COMPONENTS TaskComps[] = 
{
    {0, 60, 60, TaskDisplayClock},     // 显示时钟
    {0, 20, 20, TaskKeySan},           // 按键扫描
    {0, 30, 30, TaskDispStatus},       // 显示工作状态
 
     // 这里添加你的任务。。。。
};

任务列表

typedef enum _TASK_LIST
{
    TAST_DISP_CLOCK,            // 显示时钟
    TAST_KEY_SAN,             // 按键扫描
    TASK_DISP_WS,             // 工作状态显示
     // 这里添加你的任务。。。。
     TASKS_MAX                                           // 总的可供分配的定时任务数目
} TASK_LIST;

标志位处理函数

这个函数是用来更新每个任务的计数器以及它们的运行标志位的,它是写在单片机的定时器中断服务函数中的

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;           // 任务可以运行
            }
        }
   }
}

任务处理函数

这个函数用来判断任务是否到了执行时间,它会逐个检查任务列表中的任务,如果到了就执行,同时清空执行标志位,没到就不执行

void TaskProcess(void)
{
    uint8 i;
 
    for (i=0; i<TASKS_MAX; i++)           // 逐个任务时间处理
    {
         if (TaskComps[i].Run)           // 时间不为0
        {
             TaskComps[i].TaskHook();         // 运行任务
             TaskComps[i].Run = 0;          // 标志清0
        }
    }   
}

任务函数

/**************************************************************************************
* FunctionName   : TaskDisplayClock()
* Description    : 显示任务
 
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskDisplayClock(void)
{
 
 
 
}
 
/**************************************************************************************
* FunctionName   : TaskKeySan()
* Description    : 扫描任务
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskKeySan(void)
{
 
 
}
 
/**************************************************************************************
* FunctionName   : TaskDispStatus()
* Description    : 工作状态显示
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskDispStatus(void)
{
 
 
}

中断服务函数

/**************************************************************************************
* FunctionName : TimerInterrupt()
* Description : 定时中断服务函数
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void TimerInterrupt(void)
{
    TaskRemarks( );
}

主函数

/**************************************************************************************
* FunctionName   : main()
* Description    : 主函数
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
int main(void) 
{ 
    InitSys();                  // 初始化
 
    while (1)
    {
        TaskProcess();             // 任务处理
    }
}

架构图解

下面这个图片可以帮助理解上面的代码的整体架构
时间片轮询法_第2张图片


总结

整个程序的执行流程就是:中断函数不断刷新着每一个任务的状态,任务处理函数根据这些状态来判断哪些函数要被执行,如果要执行,就立马执行。添加任务就是在任务数组中添加一个结构体信息,编写一个任务函数,在任务列表中添加一个函数。

你可能感兴趣的:(C)