当前位置:首页 > 单片机 > 单片机
[导读] /*==============================================================1ms时标 混合式调度器(一个抢占式任务,多个合作式任务)作者:shadow.hu======================================================

/*==============================================================
1ms时标 混合式调度器(一个抢占式任务,多个合作式任务)
作者:shadow.hu
===============================================================*/
#include
#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);//报告系统状况
voidLED_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;//
statICushort 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_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个时标.........(抢占式任务)

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

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;//直接返回,不添加这个新任务
}
//如果能运行到这里,说明任务队列中有空隙,添加任务。
SCH_tasks_G[Index].pTask = pFunction;
SCH_tasks_G[Index].Delay = DELAY;
SCH_tasks_G[Index].Period = PERIOD;
SCH_tasks_G[Index].Co_op = Co_op;
SCH_tasks_G[Index].RunMe = 0;
return Index;//返回任务的位置(以便以后删除)
}


void SCH_Dispatch_Tasks(void)
{
uchar Index;
//调度(运行)下一个任务(如果有任务就绪)
for(Index = 0;Index < SCH_MAX_TASKS;Index++)
{
//只调度合作式任务
if((SCH_tasks_G[Index].RunMe > 0)&&(SCH_tasks_G[Index].Co_op))
{
(*SCH_tasks_G[Index].pTask)();//执行任务
SCH_tasks_G[Index].RunMe -= 1;//清除任务需要执行的标志
}
//如果这是个“单次”任务,将它从队列中删除
if(SCH_tasks_G[Index].Period == 0)
{
SCH_tasks_G[Index].pTask = 0;// 比通过调用来删除任务更快SCH_Delete_Task(Index);
}
}
SCH_Report_Status();//报告系统状况
SCH_Go_To_Sleep();
}

void SCH_Start(void)
{
EA = 1;
}

bit SCH_Delete_Task(const ushort TASK_INDEX)
{
bit Return_code;
if(SCH_tasks_G[TASK_INDEX].pTask == 0)
{
//这里没有任务。。。设置全局错误变量
Error_code_G = ERROR_SCH_CANOT_DELETE_TASK;
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;
}

void SCH_Go_To_Sleep()
{
PCON |= 0x01;//进入休眠模式
}

void SCH_Report_Status(void)
{
/* #ifdef SCH_REPORT_ERRORS
if(Error_code_G != Last_error_code_G)
{
Error_Port = 255 - Error_code_G;
Last_error_code_G = Error_code_G;
if(Error_code_G != 0)
{
Error_tICk_count_G = 60000;
}
else
{
Error_tick_count_G = 0;
}
}
else
{
if(Error_tick_count_G != 0)
{
if(--Error_count_G == 0)
{
Error_code_G = 0;
}
}
}
#endif */
}

void

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭