📄 sch51.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 + -