单片机程序架构-时间片轮询架构

1定时器复用说明

(1)首先定义任务数、任务定时初值(任务轮询时间=定时初值*定时器中断时间)、任务定时计数器;

(2)在定时器中断服务函数中添加【复用函数】。

#define TASK_NUM 3             //  这里定义的任务数为3,表示有三个任务会使用此定时器定时。

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

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

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

    for (i=0; i

2时间片轮询架构

时间片轮询架构组成:【一个结构体+两个函数】

2.1一个任务结构体

/**************************************************************************************
* FunctionName   : TaskStruct
* Description    : 任务结构体
* EntryParameter : None
* ReturnValue    : None
* attention      : 它包含了一个任务所需要的所有信息;
*               1:运行状态标志位:0-不运行;1-运行。  
*               2:计数器TimerCountdown--												
*               3:计数器数值填充器,预设的初值:TimerInitialValue(任务运行间隔时间)  
*               4:任务对应的函数指针  
**************************************************************************************/
typedef struct TaskComponents
{
    uint8_t Run;               // 程序运行的标记:0-不运行、1-运行
    uint8_t TimerCountdown;    // 计数器
    uint8_t TimerInitialValue; // 任务运行间隔时间
    void (*Task_hand)();       // 要运行的任务函数 
}TaskComponents;               // 任务定义

2.2两个函数

/**************************************************************************************
* FunctionName   : TaskRemarks()
* Description    : 任务标志处理
* EntryParameter : None
* ReturnValue    : None
* attention      : 这个函数是用来更新每个任务的计数器以及它们的运行标志位的,
                   它是写在单片机的定时器中断服务函数中的。
**************************************************************************************/
void TaskRemarks(void)
{
    uint8_t i;

    for (i = 0; i < TaskMax; i++)                    // 逐个任务时间处理
    {
        if(TaskComps[i].TimerCountdown)              // 时间不为0
        {
            TaskComps[i].TimerCountdown--;           // 减去一个节拍
            if (TaskComps[i].TimerCountdown == 0)    // 时间减完了
            {
                // 恢复计时器值,重新下一次
                TaskComps[i].TimerCountdown= TaskComps[i].TimerInitialValue;
                TaskComps[i].Run = 1;       // 任务可以运行
            }
        }
    }
}

/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理--->判断什么时候该执行那一个任务
* EntryParameter : None
* ReturnValue    : None
* * attention    : 放在mian的while(1)即可
**************************************************************************************/
void TaskProcess(void)
{
    uint8_t i;

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

3实现步骤

3.1定义任务结构体

/**************************************************************************************
* FunctionName   : TaskStruct
* Description    : 任务结构体
* EntryParameter : None
* ReturnValue    : None
* attention      : 它包含了一个任务所需要的所有信息;
*               1:运行状态标志位:0-不运行;1-运行。  
*               2:计数器TimerCountdown--												
*               3:计数器数值填充器,预设的初值:TimerInitialValue(任务运行间隔时间)  
*               4:任务对应的函数指针  
**************************************************************************************/
typedef struct TaskComponents
{
    uint8_t Run;               // 程序运行的标记:0-不运行、1-运行
    uint8_t TimerCountdown;    // 计数器
    uint8_t TimerInitialValue; // 任务运行间隔时间
    void (*Task_hand)();       // 要运行的任务函数 
}TaskComponents;               // 任务定义

3.2初始化任务结构体

初始化:{程序运行标记,计数器,任务运行间隔,任务函数}

#define InitStatus 0

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

3.3定义任务清单&任务数目--->枚举类型

// 任务清单
typedef enum TaskList
{
    TaskDisplayClock,    // 显示时钟
    TaskKeySan,          // 按键扫描
    TaskDispStatus,      // 显示工作状态
    // 这里继续添加任务。。。。
    TaskMax              // 总的可供分配的定时任务数目
}TaskList;

3.4编写定时器中断函数&任务处理函数

/**************************************************************************************
* FunctionName   : TaskRemarks()
* Description    : 任务标志处理
* EntryParameter : None
* ReturnValue    : None
* attention      : 这个函数是用来更新每个任务的计数器以及它们的运行标志位的,
                   它是写在单片机的定时器中断服务函数中的。
**************************************************************************************/
void TaskRemarks(void)
{
    uint8_t i;

    for (i = 0; i < TaskMax; i++)                    // 逐个任务时间处理
    {
        if(TaskComps[i].TimerCountdown)              // 时间不为0
        {
            TaskComps[i].TimerCountdown--;           // 减去一个节拍
            if (TaskComps[i].TimerCountdown == 0)    // 时间减完了
            {
                // 恢复计时器值,重新下一次
                TaskComps[i].TimerCountdown= TaskComps[i].TimerInitialValue;
                TaskComps[i].Run = 1;       // 任务可以运行
            }
        }
    }
}

/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理--->判断什么时候该执行那一个任务
* EntryParameter : None
* ReturnValue    : None
* * attention    : 放在mian的while(1)即可
**************************************************************************************/
void TaskProcess(void)
{
    uint8_t i;

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

/**************************************************************************************
* FunctionName   : Timer1Callback()
* Description    : 定时中断服务函数,回调函数
* ReturnValue    : None
**************************************************************************************/
static void Timer1Callback(void)
{
	TaskRemarks();
}

3.5编写main函数

(1)初始化函数在While(1)外;

(2)任务处理函数在While(1)里。

 timer_1_enable(32768/10,Timer1Callback);

参数32768表示1S,这里32768/10表示100ms。在实际操作中,中断的时间可以缩短一些,但是不能太短,频繁的中断效率也会低的。

/**************************************************************************************
* FunctionName   : main()
* Description    : 主函数
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
int main___(void)
{
    InitSys();                  // 初始化-打开定时器

    //这里用的是100ms中断一次来做实验
    timer_1_enable(32768/10,Timer1Callback);

    while (1)
    {
        TaskProcess();          // 任务处理
    }
}

3.6编写任务函数

/**************************************************************************************
* FunctionName   : TaskDisplayClock()
* Description    : 显示任务
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskDisplayClock(void)
{
    printf("完成任务:TaskDisplayClock()");
}

/**************************************************************************************
* FunctionName   : TaskKeySan()
* Description    : 扫描任务
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskKeySan(void)
{
    printf("完成任务:TaskKeySan()");
}

/**************************************************************************************
* FunctionName   : TaskDispStatus()
* Description    : 工作状态显示
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskDispStatus(void)
{
    printf("完成任务:TaskDispStatus()");
}

// 这里添加其他任务。。。。。。。。。

参考文献

单片机程序架构(一)时间片轮询架构_单片机时间触发器程序架构-CSDN博客

单片机的程序架构——时间片轮询【学习笔记】_单片机 时间片轮询架构-CSDN博客

你可能感兴趣的:(嵌入式,单片机)