#include <reg51.h> //51 单片机头文件
#define GPIO0_CONCTRON P0 // 定义 IO
#define GPIO1_CONCTRON P1
#define GPIO2_CONCTRON P2
#define GPIO3_CONCTRON P3
#define true 1
#define flase 0
#define MaxTask 3 // 总任务数
#define Task_one 0 // 任务 0
#define Task_two 1 // 任务 1
#define Task_three 2 // 任务 2
#define Task_one_Period 100 // 任务 0 的挂起周期 // 也就是说 它过了这个时间再运行
#define Task_two_Period 4000 // 任务 0 的挂起周期
#define Task_three_Period 70 // 任务 0 的挂起周期
int count = 0;
typedef struct // 结构体
{
unsigned int wTaskPeriod; // 运行周期
unsigned int wTaskCount; // 运行周期计数器
unsigned int wEvent; // 任务信号
}OSTCB;
OSTCB OS_TCB[MaxTask];
void OS_Create_Task(unsigned int mTaskPro,unsigned int mTaskPreiod) // 创建任务第一个参数 任务 ID 号 第二个参数 任务运行周期
{
OS_TCB[mTaskPro].wTaskPeriod= mTaskPreiod; // 把任务运行周期加载到 TCB 结构体
}
void OS_Event_Post(unsigned char mTask,unsigned int mEvent) // 任务信号邮箱
{
OS_TCB[mTask].wEvent =( 1<<mEvent);
}
void OS_Updata_Task(void) // 任务加载
{
int mTemp;
for(mTemp = 0;mTemp < MaxTask;mTemp ++) // 查询三个任务,
{
OS_TCB[mTemp].wTaskCount ++;
if(OS_TCB[mTemp].wTaskCount == OS_TCB[mTemp].wTaskPeriod) // 如果运行周期计数器 = 运行周期 则任务发送信号量 说明改任务要运行了
{
OS_TCB[mTemp].wTaskCount = 0;
OS_Event_Post(mTemp,mTemp); // 第一个参数任务 ID 号 第二个参数 任务信号量
}
}
}
void OS_Task_Int(void) // 任务初始化
{
unsigned char mTemp;
for(mTemp = 0;mTemp < MaxTask;mTemp ++)
{
OS_TCB[mTemp].wTaskPeriod = 0;
OS_TCB[mTemp].wTaskCount = 0;
OS_TCB[mTemp].wEvent = 0;
}
}
unsigned int OS_Event_Pend(unsigned char mTask) // 发送任务邮箱
{
unsigned int mTaskEvent; // 发送这个任务的信号量
mTaskEvent = OS_TCB[mTask].wEvent;
OS_TCB[mTask].wEvent &=~mTaskEvent; // 运行完后就清这个任务的信号量
return mTaskEvent;
}
void Int_Hardware(void) //51 单片机复位
{
GPIO0_CONCTRON = 0xff;
GPIO1_CONCTRON = 0x01;
GPIO2_CONCTRON = 0xff;
GPIO3_CONCTRON = 0xff;
}
void Task1(void) // 任务 1 运行函数
{
unsigned int GetEvent;
while(1)
{
GetEvent = OS_Event_Pend(Task_one);
if(GetEvent == 0)
{
return;
}
if(GetEvent &(1<<Task_one))
{
GPIO0_CONCTRON = ~GPIO0_CONCTRON;
}
}
}
void Task2(void) // 任务 2 行函数
{
unsigned int GetEvent;
while(1)
{
GetEvent = OS_Event_Pend(Task_two);
if(GetEvent == 0)
{
return;
}
if(GetEvent & (1<<Task_two))
{
GPIO1_CONCTRON = ~GPIO1_CONCTRON;
}
}
}
void Task3(void) // 任务 3 行函数
{
unsigned int GetEvent; // 获取信号量
while(1)
{
GetEvent = OS_Event_Pend(Task_three); // 查任务是否运行完 返回信号量
if(GetEvent == 0) // 如任务运行完成任务挂起,等待下次运行
{
return;
}
if(GetEvent & (1<<Task_three)) // 有任务在运行,就运行这个任务
{
GPIO2_CONCTRON = ~GPIO2_CONCTRON; // 单片机 IO 取反
}
}
}
void OS_start(void) // 任务开始
{
while(1)
{
Task1();
Task2();
Task3();
}
}
void main(void)
{
IE = 0x82; // 开中断
TMOD = 0x01;
TH0 = (65536-1)/256;
TL0 = (65536-1)%256;
TR0 = 1; // 开定时器
Int_Hardware(); // 硬件复位
OS_Task_Int(); // 任务初始化
while(1)
{
OS_Create_Task(Task_one,Task_one_Period); // 在 TCB 结构体里任务加载下面 3 个任务
OS_Create_Task(Task_two,Task_two_Period);
OS_Create_Task(Task_three,Task_three_Period);
OS_start();
}
}
void inter(void) interrupt 1 // 任务毫秒 查循一次进行任务调度
{
TH0 = (65536-1)/256;
TL0 = (65536-1)%256;
OS_Updata_Task(); // 任务查询,更新 和 发送
}
51单片机任务调度与中断处理

本文介绍了一种51单片机的任务调度系统,通过定义任务结构体和周期,实现了任务的创建、事件发布和更新。在中断处理函数中,实现了任务的查询和调度,确保各个任务按周期运行。同时,提供了硬件复位和IO控制的示例代码。
1万+

被折叠的 条评论
为什么被折叠?



