单片机的程序架构——时间片轮询【学习笔记】

在这里插入图片描述

1.顺序执行

/**************************************************************************************
* FunctionName   : main()
* Description    : 主函数
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
int main(void) 
{ 
    uint8 keyValue;

 

    InitSys();                  // 初始化

 

    while (1)
    {
        TaskDisplayClock();
        keyValue = TaskKeySan();
        switch (keyValue)
       {
            case x: TaskDispStatus(); break;
            ...
            default: break;
        }
    }
}

2.时间片轮寻:

2.0 一个定时器的复用:
      【中断过于频繁效率就低,中断太长,实时性差】——设置合适的定时器中断时间
  • ①首先定义任务数、任务定时初值(任务轮询时间=定时初值*定时器中断时间)、任务定时计数器。
  • ②在定时器中断服务函数中添加【复用函数】
#define TASK_NUM   (3) //  这里定义的任务数为3,表示有三个任务会使用此定时器定时。

uint16 TaskCount[TASK_NUM] ; //  这里为三个任务定义三个变量来存放定时值

uint8  TaskMark[TASK_NUM];//  同样对应三个标志位,为0表示时间没到,为1表示定时时间到。

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

    for (i=0; i<TASKS_NUM; i++) 
    {
        if (TaskCount[i]) 
        {
              TaskCount[i]--; 
              if (TaskCount[i] == 0) 
              {
                    TaskMark[i] = 0x01; 
              }
        }
   }
}

定时中断服务函数中:对任务逐个判断 定时计数到了没有 & 置标志为1 & 定时计数初值重置

如果定时值为0了,表示没有使用此定时器或此定时器已经完成定时,已经处理。

如果定时值不为0,定时器减一,
这时为零时,相应标志位值1,表示此任务的定时值到了

2.1 时间片轮询架构:
                两个函数+一个结构体======》时间片轮询架构
// 任务结构
typedef struct _TASK_COMPONENTS
{
    uint8 Run;                 // 程序运行标记:0-不运行,1运行
    uint8 Timer;              // 计时器
    uint8 ItvTime;              // 任务运行间隔时间【AKA计时器初始值值】
    void (*TaskHook)(void);    // 要运行的任务函数
} TASK_COMPONENTS;       // 任务定义

/**************************************************************************************
* FunctionName   : TaskRemarks()
* Description    : 任务标志处理
* EntryParameter : None
* ReturnValue    : None
* attention      : ***在定时器中断中调用此函数即可***
**************************************************************************************/
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;           // 任务可以运行
           }
        }
   }
}

/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理|判断什么时候该执行那一个任务
* EntryParameter : None
* ReturnValue    : None
* * attention      : ***放在mian的while(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
        }
    }   
}
2.2 具体实现:
2.2.1定义 任务结构体
// 任务结构
typedef struct _TASK_COMPONENTS
{
    uint8 Run;                 // 程序运行标记:0-不运行,1运行
    uint8 Timer;              // 计时器
    uint8 ItvTime;              // 任务运行间隔时间【AKA计时器初始值值】
    void (*TaskHook)(void);    // 要运行的任务函数
} TASK_COMPONENTS;       // 别名
2.2.2初始化 任务结构体
static TASK_COMPONENTS TaskComps[] = 
{
    {0, 60, 60, TaskDisplayClock},            // 显示时钟
    {0, 20, 20, TaskKeySan},               // 按键扫描
    {0, 30, 30, TaskDispStatus},            // 显示工作状态

     // 这里添加你的任务。。。。

};
2.2.3定义 任务清单&任务数目 枚举类型
// 任务清单
typedef enum _TASK_LIST
{
    TAST_DISP_CLOCK,            // 显示时钟
    TAST_KEY_SAN,             // 按键扫描
    TASK_DISP_WS,             // 工作状态显示
     // 这里添加你的任务。。。。
     TASKS_MAX         // 总的可供分配的定时任务数目
} TASK_LIST;
2.2.4编写 定时器中断函数&任务处理函数
/**************************************************************************************
* FunctionName   : TaskRemarks()
* Description    : 任务标志处理
* EntryParameter : None
* ReturnValue    : None
* attention      : ***在定时器中断中调用此函数即可***
**************************************************************************************/
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;           // 任务可以运行
           }
        }
   }
}

/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理|判断什么时候该执行那一个任务
* EntryParameter : None
* ReturnValue    : None
* * attention      : ***放在mian的while(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
        }
    }   
}
2.2.5编写main函数
  • 初始化函数在while(1)外
  • 任务处理函数在while(1)里
/**************************************************************************************
* FunctionName   : main()
* Description    : 主函数
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
int main(void) 
{ 
    InitSys();                  // 初始化-打开定时器

    while (1)
    {
        TaskProcess();             // 任务处理
    }
}
2.2.6编写你的任务函数
/**************************************************************************************
* 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)
{

}

// 这里添加其他任务。。。。。。。。。
2.3 注意点

任务与任务间数据传递时,数据传递要采用全局变量

3.操作系统:

FreeRTOS、鸿蒙os~~~【略】

>>>这是一篇学习笔记,感谢博主:@Good__life
  • 38
    点赞
  • 220
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值