您当前的位置:五五电子网电子知识单片机-工控设备源码-程序混合式调度器C51源代码和相关注释 正文
混合式调度器C51源代码和相关注释

混合式调度器C51源代码和相关注释

点击数:7482 次   录入时间:03-04 11:47:46   整理:http://www.55dianzi.com   源码-程序

    /*==============================================================
1ms时标 混合式调度器(一个抢占式任务,多个合作式任务)
作者:shadow.hu
===============================================================*/
#include<reg52.h>
#define uchar  unsigned char
#define ushort unsigned short
#define SCH_MAX_TASKS 9
#define ERROR_SCH_TOO_MANY_TASKS  9
#define ERROR_SCH_CANOT_DELETE_TASK 0
#define RETURN_ERROR 0
#define RETURN_NORMAL 1

#define INTERRPT_Timer_2_Overflow 5

#define SCH_REPORT_ERRORS
#ifdef  SCH_REPORT_ERRORS
#define Error_Port P1
#endif

typedef data struct
{
    void (code *pTask)(void);
 ushort Delay;
 ushort Period;
 ushort RunMe;
 uchar  Co_op;//如果任务是合作式的,设置为1,如果任务是抢占式的,设置为0
}sTask;
sTask SCH_tasks_G[SCH_MAX_TASKS];

void SCH_Init_T2(void);
uchar SCH_Add_Task(void (code * pFunction)(),const ushort Delay,  ushort PERIOD);
//                      函数名指针                延时的时标数    执行任务的时间间隔
//                                                为0则立即执行  如果为0,表示单次任务 
void SCH_Dispatch_Tasks(void);
void SCH_Start(void);
bit SCH_Delete_Task(const ushort TASK_INDEX);
void SCH_Go_To_Sleep(void);
void SCH_Report_Status(void);//报告系统状况
void LED_Flash_Init(void);
void LED_Flash_Update_A(void);
void LED_Flash_Update_B(void);
void LED_Flash_Update_C(void);
void LED_Flash_Update_D(void);
void LED_Flash_Update_E(void);
void LED_Flash_Update_F(void);
void LED_Flash_Update_G(void);
void LED_Flash_Update_H(void);

uchar Error_code_G = 0;//
statIC ushort Error_tick_count_G;//记住自从上一次纪录错误以来的时间
static uchar Last_error_code_G;//上次的错误代码(在1分钟之后复位)

uchar  LED_State_G_A = 0;
uchar  LED_State_G_B = 0;
uchar  LED_State_G_C = 0;
uchar  LED_State_G_D = 0;
uchar  LED_State_G_E = 0;
uchar  LED_State_G_F = 0;
uchar  LED_State_G_G = 0;
uchar  LED_State_G_H = 0;

sbit LED_PIN_A = P1^0;
sbit LED_pin_B = P1^1;
sbit LED_pin_C = P1^2;
sbit LED_pin_D = P1^3;
sbit LED_pin_E = P1^4;
sbit LED_pin_F = P1^5;
sbit LED_pin_G = P1^6;
sbit LED_pin_H = P1^7;

//Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
//Error_code_G = ERROR_SCH_WAITING_FOR_SLAVE_TO_ACK;
//Error_code_G = ERROR_SCH_WAITING_FOR_START_COMAND_FROM_MASTER;
//Error_code_G = ERROR_SCH_ONE_OR_MORE_SLAVES_DID_NOT_START;
//Error_code_G = ERROR_SCH_LOST_SLAVE;
//Error_code_G = ERROR_SCH_CAN_BUS_ERROR;
//Error_code_G = ERROR_I2C_WRITE_BYTE_AT24C64;

void main(void)
{
 SCH_Init_T2();
 LED_Flash_Init();
 SCH_Add_Task(LED_Flash_Update_A,0,1000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_B,0,2000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_C,0,3000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_D,0,4000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_E,0,5000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_F,0,6000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_G,0,7000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_H,0,8000);//添加一个任务

     SCH_Start();//开全局中断
 while(1)
 {
  SCH_Dispatch_Tasks();
 }
}
/*------------------------------------------------------------
 这是调度器的中断服务程序,初始化函数中的定时器设置决定了它
的调度频率,这个版本的调度器由定时器2触发中断,定时器自动重装。
-------------------------------------------------------------*/
void SCH_Update(void) interrupt INTERRPT_Timer_2_Overflow
{
 //刷新任务队列
 uchar Index;
 TF2 = 0;//必须手工清除
 //注意:计算单位为时标(不是毫秒)
 for(Index = 0;Index < SCH_MAX_TASKS;Index++)
 {  //检测这里是否有任务
  if(SCH_tasks_G[Index].pTask)
  { 
  if(SCH_tasks_G[Index].Delay == 0)
  {
    //任务需要运行,间隔的时间已经到了
    if(SCH_tasks_G[Index].Co_op)
    {
    //如果是合作式任务,RunMe标志加1
    SCH_tasks_G[Index].RunMe += 1;//要执行任务的标志加1
    }
    else//如果它是抢占式任务,立即运行它
    {
    (*SCH_tasks_G[Index].pTask)();//运行任务
    SCH_tasks_G[Index].RunMe -= 1;
    //周期性的任务将自动再次运行,单次任务就删除
    if(SCH_tasks_G[Index].Period == 0)
    {
      SCH_tasks_G[Index].pTask = 0;
    }
    }   
    if(SCH_tasks_G[Index].Period)//时标间隔不等于0
    {
    //调度周期性的任务再次运行,每隔这个固定的时标长度执行一次任务
    SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
    }
  }
  else //任务有延迟执行要求,还没到达延迟的时间
  {
    //还没有准备好运行,延迟减1
    SCH_tasks_G[Index].Delay -= 1;
  }
  }
 }
}

    void SCH_Init_T2(void)
{
    uchar i;
 for(i=0;i<SCH_MAX_TASKS;i++)
 {
  SCH_Delete_Task(i);
 }
 Error_code_G = 0;
 T2CON = 0x04;
 TMOD = 0x00;
 TH2  = 0xfc;
 RCAP2H = 0xfc;
 TL2  = 0x18;
 RCAP2L = 0x18;
 ET2  = 1;
 TR2  = 1;
}
/*----------------------------------------------------------------------------
任务函数每隔一定时间间隔或在用户定义的延迟之后运行
pFunction -- 将被调用的函数名称。注意:被调函数必须是“void void”型
DELAY    -- 在任务第一次被执行之前的间隔
PERIOD    -- 如果它为0,则只调用该函数一次,由DELAY确定其调用的时间
            如果非0,那么它就是被重复调用的时间间隔
Co_op    -- 如果是合作式任务则设置为1,如果是抢占式任务则设置为0.

    注意:如果以后要删除任务,将需要返回值
例子:
Task_ID = SCH_Add_Task(Do_X,1000,0,0);
使函数Do_X()在1000个调度器时标之后运行一次(抢占式任务)
Task_ID = SCH_Add_Task(Do_X,0,1000,1);
使函数Do_X()每隔1000个调度器时标运行一次(合作式任务)
Task_ID = SCH_Add_Task(Do_X,300,1000,0);
使函数Do_X()每隔1000个调度器时标运行一次,任务首先在T=300个时标时被执行
  然后是1300个时标.........(抢占式任务)

    -----------------------------------------------------------------------------*/



www.55dianzi.com
uchar SCH_Add_Task(void (code * pFunction)(),const ushort DELAY, ushort PERIOD,bit Co_op)
{
 uchar Index = 0;
 //首先在队列中找到一个空隙(如果有的话,否则就不添加新任务)
 while((SCH_tasks_G[Index].pTask != 0)&&(Index < SCH_MAX_TASKS))
 {
  Index++;//当一个新任务被添加,且没有超过任务上限
 }
 //是否达到任务队列的结尾?
 if(Index == SCH_MAX_TASKS)//任务数量达到上限
 {
  Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
  return SCH_MAX_TASKS;//直接返回,不添加这个新任务
 }
 //如果能运行到这里,说明任务队列中有空隙,添加任务。

[1] [2]  下一页


本文关键字:源代码  源码-程序单片机-工控设备 - 源码-程序

《混合式调度器C51源代码和相关注释》相关文章>>>