typedef unsigned char uint8;
typedef unsigned int uint16;
#include <reg52.h>
sbit led0 = P0^0;
sbit led1 = P0^1;
sbit led2 = P0^2;
uint8 Cur_TaskID; //当前运行的任务号
uint8 Task_Stack0[10]; //0号任务的堆栈,10个字节
uint8 Task_Stack1[10]; //1号任务的堆栈,10个字节
uint8 Task_Stack2[10]; //2号任务的堆栈,10个字节
uint8 Task_StackSP[3]; //3个堆栈的栈顶指针
//Task_StackSP[0] -> Task_Stack0
//Task_StackSP[1] -> Task_Stack1
//Task_StackSP[2] -> Task_Stack2
void Task_0(); //任务0
void Task_1(); //任务1
void Task_2(); //任务2
void Task_Scheduling(uint8 Task_ID); //任务调度
void main (void)
{
//堆栈内容
Task_Stack0[1] = (uint16) Task_0; //按照小端模式,任务函数入口地址装入任务堆栈
Task_Stack0[2] = (uint16) Task_0 >> 8;
Task_Stack1[1] = (uint16) Task_1;
Task_Stack1[2] = (uint16) Task_1 >> 8;
Task_Stack2[1] = (uint16) Task_2;
Task_Stack2[2] = (uint16) Task_2 >> 8;
//堆栈指针
Task_StackSP[0] = Task_Stack0;
Task_StackSP[0] += 2; //刚入栈两个元素。这里取得栈顶地址,即Task_Stack0[2]
Task_StackSP[1] = Task_Stack1;
Task_StackSP[1] += 2;
Task_StackSP[2] = Task_Stack2;
Task_StackSP[2] += 2;
Cur_TaskID = 0;
SP = Task_StackSP[0]; //SP取得0号任务的栈顶地址
}//利用main的返回指令RET,使PC取得0号任务入口地址
//任务调度函数,当前任务号是Cur_TaskID,将要执行的任务号是Nex_TaskID
void Task_Scheduling(uint8 Nex_TaskID)
{
Task_StackSP[Cur_TaskID] = SP;//保存当前堆栈指针到当前任务堆栈中
Cur_TaskID = Nex_TaskID;//将要执行的任务号
SP = Task_StackSP[Cur_TaskID];//将要执行的任务堆栈指针
}
//0号任务函数
void Task_0()
{
while(1)
{
led0 = 0;
Task_Scheduling(1);//当前任务号Cur_TaskID=0,将要执行的任务号Nex_TaskID=1
}
}
//1号任务函数
void Task_1()
{
while(1)
{
led1 = 0;
Task_Scheduling(2);//当前任务号Cur_TaskID=1,将要执行的任务号Nex_TaskID=2
}
}
//2号任务函数
void Task_2()
{
while(1)
{
led2 = 0;
Task_Scheduling(0);//当前任务号Cur_TaskID=2,将要执行的任务号Nex_TaskID=0
}
}
代码要做的,就是3个任务的顺序执行。任务调度函数Task_Scheduling的思想也即如前面所述。在Keil中可以运行代码,可以看到,程序在3个任务中顺序执行了。