📄 sch.c
字号:
/*------------------------------------------------------------------*-
版权说明:
1、此程序应称作“时间触发多任务调度器”。
2、程序摘自《时间触发嵌入式系统设计模式
使用8051系统微控制器开发可靠应用》。
在本站好书推荐中有对此书的说明。
3、原作者在书中对版权进行了说明:
只要购买了本书就可以使用书中源程序。
4、在项目中多次用到此程序,感觉很不错。
此处提供的调度器程序是我简化过的。
移植说明:
1、代码全部用标准C语言编写,可以方便的插
入到项目中。
2、内核唯一需要硬件支持的是定时器,需要开
一个定时器,为内核提供调度周期信号。
-*------------------------------------------------------------------*/
#include "AFA.h"
s_task SCH_task_array[SCH_MAX_TASKS]; /*定义任务队列 */
/*------------------------------------------------------------------*-
SCH_Init_Time()
调度器初始化
1、准备调度器数据结构并且设置定时器以所需的
频率中断。
2、必须在使用调度器之前调用这个函数。
-*------------------------------------------------------------------*/
void SCH_Init_Time(void) {
uint8 i;
for (i = 0; i < SCH_MAX_TASKS; i++) { /*清空任务队列 */
SCH_Delete_Task(i);
}
OCR1A = 1250; /*计数周期为10mS,F=1M*/
TIMSK1 = 0x02; /*比较中断A允许 */
SREG = 0x80;
TCCR1A = 0x00;
TCCR1B = 0x08; /*运行于CTC模式 */
TCCR1B |= 0x02; /*设置8分频 */
}
/*------------------------------------------------------------------*-
SCH_Start()
启动调度器
1、启动调度器,也就允许调度器运行。
2、主要是允许中,因为任务状态是在中断中
刷新的。
-*------------------------------------------------------------------*/
void SCH_Start(void) {
SEI(); /*开全局中断 */
}
/*------------------------------------------------------------------*-
SCH_Add_Task()
任务添加
1、将任务添加到任务队列中,并设置执行条件。
2、任务添加成功将返回,任务被添加的位置。
3、任务添加失败将返回0。
4、变量说明:
pFunction 函数指针,指向要添加的函数。
delay 任务运行等待时间。
period 任务运行周期时间,此处用于需要
周期性运行的任务。
如只要运行一次,则此值应为0
-*------------------------------------------------------------------*/
uint8 SCH_Add_Task(void (* pFunction)(), uint16 delay, uint16 period) {
static uint8 i = 0;
while ((SCH_task_array[i].task != 0) && (i < SCH_MAX_TASKS)) {
i++;
}
if (i == SCH_MAX_TASKS) { /*检查任务队列溢出 */
return 0; /*溢出处理 */
}
SCH_task_array[i].task = pFunction; /*加载任务 */
SCH_task_array[i].delay = delay;
SCH_task_array[i].period = period;
SCH_task_array[i].run = 0x00;
return i; /*返回任务ID号 */
}
/*------------------------------------------------------------------*-
SCH_Update()
任务刷新
1、定时器T1,A组比较中断。
2、对任务定时时间进行刷新。
3、任务定时时间到,设置任务运行标志。
-*------------------------------------------------------------------*/
#pragma interrupt_handler SCH_Update: 12
void SCH_Update(void) {
static uint8 i;
for (i = 0; i < SCH_MAX_TASKS; i ++) {
if (SCH_task_array[i].task) { /*检测任务是否存在 */
if (SCH_task_array[i].delay != 0) { /*刷新任务等待时间 */
SCH_task_array[i].delay --;
}
if (SCH_task_array[i].delay == 0) { /*任务时间是否到 */
SCH_task_array[i].run += 1; /*设置运行标志 */
if (SCH_task_array[i].period) { /*是否为循环任务 */
SCH_task_array[i].delay = SCH_task_array[i].period;
} /*重载任务定时器 */
}
}
}
}
/*------------------------------------------------------------------*-
SCH_Dispatch_Tasks()
任务调度
1、调度程序,当任务需要运行时,由本程序调用。
2、这个函数必须重复运行。
-*------------------------------------------------------------------*/
void SCH_Dispatch_Tasks(void) {
static uint8 i;
for (i = 0; i < SCH_MAX_TASKS; i++) { /*查询任务队列 */
if (SCH_task_array[i].run > 0) {
(*SCH_task_array[i].task)(); /*运行任务 */
SCH_task_array[i].run --; /*运行标志自减 */
if (SCH_task_array[i].period == 0) { /*删除单周期任务 */
SCH_Delete_Task(i);
}
}
}
}
/*------------------------------------------------------------------*-
SCH_Delete_Task()
任务删除
1、删除指定任务。
2、要删除任务的ID,此ID在任务添加时给出。
-*------------------------------------------------------------------*/
void SCH_Delete_Task(uint8 task_id) {
SCH_task_array[task_id].task = 0x00; /*清除任务 */
SCH_task_array[task_id].delay = 0x00;
SCH_task_array[task_id].period = 0x00;
SCH_task_array[task_id].run = 0x00;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -