📄 schedule.c
字号:
#define SCHEDULE_GLOBAL
#include "schedule.h"
static void SCH_Updata(void);
// 在任一时刻要求的任务最大数目
#define SCH_MAX_TASKS (3)
// 任务队列
sTask SCH_tasks_G[SCH_MAX_TASKS];
// 错误代码
#define ERROR_SCH_TOO_MANY_TASKS (1)
#define ERROR_SCH_CANNOT_DELETE_TASK (2)
#define RETURN_NORMAL 0
#define RETURN_ERROR 1
/*---------------------------------------------------------*-
* 函数名称: SCH_Dispatch_Tasks()
* 入 口:
* 出 口:
* 函数功能: 调度函数,当一个任务()需要运行时,此函数将运行它,
*
* 说 明: 这个函数必须被主循环(重复)调用
-*---------------------------------------------------------*/
void SCH_Dispatch_Tasks(void)
{
unsigned char Index;
// 调度(运行)下一个任务(如果有任务就绪)
for (Index=0; Index<SCH_MAX_TASKS; Index++)
{
if (SCH_tasks_G[Index].RunMe > 0)
{
// 运行任务
(*SCH_tasks_G[Index].pTask)();
// 复位 / 降低RunMe标志
SCH_tasks_G[Index].RunMe -= 1;
// 如果这个是'单次'任务,将它从队列中删除
if (SCH_tasks_G[Index].Period == 0)
{
SCH_Delete_Task(Index);
}
}
}
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Add_Task()
* 入 口: (*pFunction)任务指针,(DELAY)到第一次运行间隔时标,
* (PERIOD)每次运行的间隔时标
*
* 出 口: 返回SCH_MAX_TASKS表示任务队列已满
* 返回(Index)=任务位置
*
* 函数功能: 用来添加任务到任务队列上,以保证它们在需要的时
* 候被调用
*
* 说 明: 使任务函数每隔一定间隔或在用户的延迟之后执行.
-*---------------------------------------------------------*/
unsigned char SCH_Add_Task(void (*pFunction)(), // 任务指针
const unsigned int DELAY, // 延迟Delay个时标后函数将第一次运行
const unsigned int PERIOD) // 连续的运行之间的间隔(时标)
{
unsigned char Index = 0; // 首先在队列中找到一个空隙
while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
{
Index++;
}
if (Index == SCH_MAX_TASKS)
{
return SCH_MAX_TASKS; // 同时返回错误代码
}
// 如果能运行到这里,则说明任务队列中有空间
SCH_tasks_G[Index].pTask = pFunction;
SCH_tasks_G[Index].Delay = DELAY;
SCH_tasks_G[Index].Period = PERIOD;
SCH_tasks_G[Index].RunMe = 0;
return Index; // 返回任务的位置(以便以后删除)
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Delete_Task()
* 入 口: TASK_INDEX -任务索引.由SCH_Add_task()提供
*
* 出 口: 返回值: RETURN_ERROR(或)RETURN_NORMAL
*
* 函数功能: 从调度器删除任务.
*
* 说 明: 请注意:并不是从存储器中删除相关的函数,仅仅是不再
* 由调度器调用这个任务.
-*---------------------------------------------------------*/
uchar SCH_Delete_Task(const unsigned char TASK_INDEX)
{
uchar Return_code; //返回错误代码
if (SCH_tasks_G[TASK_INDEX].pTask == 0)
{
Return_code = RETURN_ERROR;
}
else
{
Return_code = RETURN_NORMAL;
}
// 删除任务
SCH_tasks_G[TASK_INDEX].pTask = 0x00;
SCH_tasks_G[TASK_INDEX].Delay = 0;
SCH_tasks_G[TASK_INDEX].Period = 0;
SCH_tasks_G[TASK_INDEX].RunMe = 0;
return Return_code;
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Update()
* 入 口:
* 出 口:
* 函数功能: 在调度器的中断服务程序中运行
*
* 说 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
* RunMe标志加1,然后该任务将由调度程序执行.
-*---------------------------------------------------------*/
static void SCH_Updata(void)
{
unsigned char Index;
for (Index=0; Index < SCH_MAX_TASKS; Index++)
{
// 检测这里是否有任务?
if (SCH_tasks_G[Index].pTask != 0)
{
if (SCH_tasks_G[Index].Delay == 0)
{
SCH_tasks_G[Index].RunMe += 1; // RunMer标志加1
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;
}
}
}
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Init_Timer2()
* 入 口:
* 出 口:
* 函数功能: 准备调度器数据结构并且设置定时器以所需的频率中断
*
* 说 明: 调度器初始化化函数,必须在使用调度器之前调用它
-*---------------------------------------------------------*/
void InitTimer1(void) //8MHz,10ms,64分频
{
uchar i;
for (i=0; i<SCH_MAX_TASKS; i++)
{
SCH_Delete_Task(i);
}
TCCR1B = 0x00; //stop
TCNT1H = 0xFB; //setup
TCNT1L = 0x1E;
OCR1AH = 0x04;
OCR1AL = 0xE2;
OCR1BH = 0x04;
OCR1BL = 0xE2;
ICR1H = 0x04;
ICR1L = 0xE2;
TCCR1A = 0x00;
TCCR1B = 0x03; //start Timer
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Update_Server()
* 入 口:
* 出 口:
* 函数功能: 调度器的中断服务程序
*
* 说 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
* RunMe标志加1,然后该任务将由调度程序执行.
-*---------------------------------------------------------*/
#pragma interrupt_handler SCH_Update_Server:9 //定时器溢出中断
void SCH_Update_Server(void)
{
TCNT1H = 0xFB; //reload counter value
TCNT1L = 0x1E;
TimeTick++;
MotorDelayTime++;
if(TimeTick%100 == 0) //1s喂狗
{
if(TimeTick == 200)TimeTick = 0;
OutWdServer();
}
SCH_Updata();
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Start()
* 入 口:
* 出 口:
* 函数功能: 通过允许中断来启动调度器
*
* 说 明: 在添加了所有定期的任务之后调用,从而使任务保持同步.
* 注意:应该只使能调度器中断
-*---------------------------------------------------------*/
void SCH_Start(void)
{
SEI();
}
//**************END OF FILE*********************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -