基于时间片简单实现任务调用器
基于时间片的调度(或称为定时调度)是一种在嵌入式系统中常见的任务调度方式,它通过使用计时器中断(例如SysTick)来触发周期性事件。以下是这种调度方式的关键组成部分及其作用:
任务周期(Task Period):
- 任务周期定义了任务执行的时间间隔,即任务多久执行一次。
- 例如,如果任务周期设置为100ms,那么该任务每100毫秒执行一次。
- 任务周期是调度器决定何时触发任务执行的关键参数。
任务标志位(Task Flag):
- 任务标志位是一个布尔变量,用于指示特定任务是否到了执行的时间。
- 当计时器达到任务周期时,相应的任务标志位会被设置,以通知调度器该任务需要被执行。
- 在主循环中,调度器会检查这些标志位,如果某个任务的标志位被设置,则执行相应的任务,并在执行后清除该标志位。
计时器(Timer):
- 计时器是一个计数变量,用于跟踪自上次任务执行以来经过的时间。
- 计时器在每个SysTick中断中递增,当其值达到任务周期时,相应的任务标志位被设置。
- 计时器通常从0开始计数,达到任务周期后重置为0,以便开始新一轮的计数。
在STM32F103C6这类微控制器中,SysTick定时器通常被配置为每1ms产生一次中断。在SysTick中断服务程序(SysTick_Handler)中,每个任务的计时器会递增,一旦达到任务的周期,就会设置相应的任务标志位。
以下是一个简化的代码示例,展示了如何实现基于时间片的调度:
#include "stm32f10x.h"
#define TASK1_PERIOD 100 // 任务1周期100ms
#define TASK2_PERIOD 200 // 任务2周期200ms
volatile uint8_t Flag_Task1 = 0; // 任务1标志位
volatile uint8_t Flag_Task2 = 0; // 任务2标志位
static uint16_t Task1_Timer = 0; // 任务1计时器
static uint16_t Task2_Timer = 0; // 任务2计时器
void SysTick_Handler(void) {
Task1_Timer++;
Task2_Timer++;
if (Task1_Timer >= TASK1_PERIOD) {
Task1_Timer = 0;
Flag_Task1 = 1;
}
if (Task2_Timer >= TASK2_PERIOD) {
Task2_Timer = 0;
Flag_Task2 = 1;
}
}
void SysTick_Init(void) {
SysTick_Config(SystemCoreClock / 1000); // 1ms中断一次
}
void Task1(void) {
// 任务1的代码
}
void Task2(void) {
// 任务2的代码
}
int main(void) {
SysTick_Init();
while (1) {
if (Flag_Task1) {
Flag_Task1 = 0;
Task1();
}
if (Flag_Task2) {
Flag_Task2 = 0;
Task2();
}
}
}
在这个例子中,任务1每100ms执行一次,任务2每200ms执行一次。SysTick中断服务程序会递增每个任务的计时器,并在达到周期时设置相应的标志位。主循环检查这些标志位,并执行相应的任务。