单片机裸机任务调度详解与实现方法
主APP文件
结构体封装任务组件
typedef struct{
uint8_t run;/* 调度标志,1:调度,0:挂起*/
uint8_t TimCount;/* 时间片周期,用于递减计数*/
uint8_t TimRload;/* 时间片周期,用于重载*/
void (*TaskFuncCb)(void); /* 函数指针,保存任务函数地址*/
}TaskComps_t;
注册任务函数
static TaskComps_t g_TaskComps[] = {
{0,50,50,HmiTask},
{0,200,200,LCDTask},
/* 添加业务功能模块 */
}
计算注册任务个数
#define TASK_NUM_MAX (sizeof(g_TaskComps) / sizeof(g_TaskComps[0]))
编写任务执行函数
//此函数放到main函数while(1)循环中
static void TaskHandlerFunc(void){
for (uint32_t i = 0; i < TASK_NUM_MAX; ++i)
{
if (g_TaskComps[i].run == 1)
{
g_TaskComps[i].pTaskFunc();
g_TaskComps[i].run=0;
}
}
}
例如:
int main(void){
...
while(1){
...
TaskHandlerFunc();
}
}
编写时间片函数
void TaskScheduleCb(void){
for (uint32_t i = 0; i < TASK_NUM_MAX; ++i)
{
if (g_TaskComps[i].timCount)
{
g_TaskComps[i].timCount--;
if (g_TaskComps[i].timCount == 0)
{
g_TaskComps[i].run = 1;
g_TaskComps[i].timCount = g_TaskComps[i].timRload;
}
}
}
}
在mian.c中调用注册
定时器中断文件
STM32
HAL库
stm32f4xx_it.c
时间片函数要在滴答定时器中断中运行,但这个函数是在应用层的,不能直接写在硬件层,所有需要一个回调函数,调用此函数运行。
static void (*pTaskScheduleFunc)(void);
//声明在main.h文件中
void TaskScheduleCbReg(void (*pFunc)(void)){
pTaskScheduleFunc = pFunc;
}
//在 滴答定时器中断中使用
void SysTick_Handler(void)
{
pTaskScheduleFunc();
}
51系列
写一个每次1ms中断一次的定时器中断。在此中断函数里面调用。
static void (*pTaskScheduleFunc)(void);
//声明在main.h文件中
void TaskScheduleCbReg(void (*pFunc)(void)){
pTaskScheduleFunc = pFunc;
}
//在定时器1ms中断中使用
void timer0() interrupt 1
{
pTaskScheduleFunc();
}
在主函数中进行注册调用
int main(void){
...
TaskSheduleCbReg(TaskScheduleCb);
while(1){
TaskHandler();
}
}
作者:June 7