⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sch51.c

📁 时间触发式单片机最小系统
💻 C
字号:
/*------------------------------------------------------
 SCHd51.c
 simple embedded operation system(s_EOS)
 Based on the sheduler
------------------------------------------------------*/
#include"SCH51.h"
#include"main.h"
#include"mytask.h"

bit Error_code_G=0;

/* Store in DATA area, if possible, for rapid access
Total memory per task is 7 bytes */
typedef data struct
{
    /* Pointer to the task (must be a 'void (void)' function) */
    void (code * pTask)(void);
    /* Delay (ticks) until the function will (next) be run
    - see SCH_Add_Task() for further details */
    uint Delay;
    /* Interval (ticks) between subsequent runs.
    - see SCH_Add_Task() for further details */
    uint Period;

    /* Incremented (by scheduler) when task is due to execute */
    uchar RunMe;
} sTask;
  /* The array of tasks */
  sTask SCH_tasks_G[SCH_MAX_TASKS];
////////////////////////////////////////////////////////////

void SCH_Init_T0(void)
{
   uchar i;
   for (i = 0; i < SCH_MAX_TASKS;i++)
      {
         SCH_Delete_Task(i);
      }
/* SCH_Delete_Task() will generate an error code,
because the task array is empty.
-> reset the global error variable. */

/* Now set up Timer 0
16-bit timer function with automatic reload
Crystal is assumed to be 12 MHz
The Timer 2 resolution is 0.000001 seconds (1 μs)
The required Timer 0 overflow is 0.001 seconds (1 ms)
- this takes 1000 timer ticks
Reload value is 65536 - 1000 = 64536 (dec) = 0xFC18 */
      TCON = 0x04; /* Load Timer 0 control register */
      TMOD = 0x01; /* Load Timer 0 mode register */
      TH0 = 0xd8; /* Load Timer 0 high byte */
      //RCAP2H = 0xFC; /* Load Timer 0 reload capture reg, high byte */
      TL0 = 0xf0; /* Load Timer 0 low byte */
      //RCAP2L = 0x18; /* Load Timer 0 reload capture reg, low byte */
      ET0 = 1; /* Timer 0 interrupt is enabled */
      TR0 = 1; /* Start Timer 0 */
}
//////////////////////////////////////////////////////////////
/*--------------------------------------------------------*/
void SCH_Update(void) interrupt INT_T0_Overflow
{
      uchar Index;
      TF0 = 0; /* Have to manually clear this. */
      /* NOTE: calculations are in *TICKS* (not milliseconds) */
      for (Index = 0; Index < SCH_MAX_TASKS; Index++)
         {
            /* Check if there is a task at this location */
            if (SCH_tasks_G[Index].pTask)
               {
                 if (--SCH_tasks_G[Index].Delay == 0)
                   {
                     /* The task is due to run */
                     SCH_tasks_G[Index].RunMe += 1; /* Inc. 'RunMe' flag */
                     if (SCH_tasks_G[Index].Period)
                      {
                       /* Schedule regular tasks to run again */
                       SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
                      }
                   }
                }
         }
}
//////////////////////////////////////////////////////////////
uchar SCH_Add_Task(void (code * pFunction)(),
                         const uint DELAY,
                         const uint PERIOD)
    {
      uchar Index = 0;
      /* First find a gap in the array (if there is one) */
      while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
        {
         Index++;
        }
       /* Have we reached the end of the list? */
       if (Index == SCH_MAX_TASKS)
        {
          /* Task list is full
          -> set the global error variable */
          Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
          /* Also return an error code */
          return SCH_MAX_TASKS;
        }
        /* If we're here, there is a space in the task array */
        SCH_tasks_G[Index].pTask = pFunction;
        SCH_tasks_G[Index].Delay = DELAY + 1;
        SCH_tasks_G[Index].Period = PERIOD;
        SCH_tasks_G[Index].RunMe = 0;
        return Index; /* return pos. of task (to allow deletion) */
    }
///////////////////////////////////////////////////////////////
/*--------------------------------------------------------*-
SCH_Dispatch_Tasks()
This is the 'dispatcher' function. When a task (function)
is due to run, SCH_Dispatch_Tasks() will run it.
This function must be called (repeatedly) from the main loop.
-*--------------------------------------------------------*/
void SCH_Dispatch_Tasks(void)
{
    uchar Index;
    /* Dispatches (runs) the next task (if one is ready) */
    for (Index = 0; Index < SCH_MAX_TASKS; Index++)
     {
      if (SCH_tasks_G[Index].RunMe > 0)
        {
        (*SCH_tasks_G[Index].pTask)(); /* Run the task */
         SCH_tasks_G[Index].RunMe -= 1; /* Reduce RunMe count */
         /* Periodic tasks will automatically run again
         - if this is a 'one shot' task, delete it */
         if (SCH_tasks_G[Index].Period == 0)
           {
              SCH_Delete_Task(Index);
           }
        }
      }
    /* Report system status */
    //SCH_Report_Status();
    /* The scheduler enters idle mode at this point */
    SCH_Go_To_Sleep();
}
//////////////////////////////////////////////////////////////
/*--------------------------------------------------------*/
void SCH_Go_To_Sleep(void)
{
   PCON |= 0x01; /* Enter idle mode (generic 8051 version) */
    /* Entering idle mode requires TWO consecutive instructions
     on 80c515 / 80c505 - to avoid accidental triggering.
     E.g:
    PCON |= 0x01;
    PCON |= 0x20; */
}
//////////////////////////////////////////////////////////////
/*--------------------------------------------------------*/
void SCH_Start(void)
{
  EA = 1;
}
/////////////////////////////////////////////////////////////
bit SCH_Delete_Task(const uchar TASK_INDEX)
{
  bit Return_code;
  if (SCH_tasks_G[TASK_INDEX].pTask == 0)
    { 
     /* No task at this location...
     -> set the global error variable */
      Error_code_G = ERROR_SCH_CANNOT_DELETE_TASK;
     /* ...also return an error code */
     Return_code = RETURN_ERROR;
    }
  else
    {
     Return_code = RETURN_NORMAL;
    }
    SCH_tasks_G[TASK_INDEX].pTask = 0x0000;
    SCH_tasks_G[TASK_INDEX].Delay = 0;
    SCH_tasks_G[TASK_INDEX].Period = 0;
    SCH_tasks_G[TASK_INDEX].RunMe = 0;
    return Return_code; /* return status */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -