IoT 产品一般硬件相对简单,但有时也需要做任务管理,希望这篇文章可以为你解惑。
1、任务管理
1.1、添加任务
INT8U SCH_Add_Task(void (code * pFunction)(void), const INT32U DELAY, const INT16U PERIOD, const INT8U PREEMPTIVE_EN)
{
INT8U Index = 0; // Index×î´óΪ255£¬ËùÒÔSCH_MAX_TASKS×î´óΪ256
// Ê×ÏÈÔÚ¶ÓÁÐÖÐÕÒµ½Ò»¸ö¿Õ¿é(Èç¹ûÓеĻ°)
while((SCH_tasks[Index].pTask != NULL) && (Index < SCH_MAX_TASKS))
{
Index++;
}
if(Index == SCH_MAX_TASKS) //µ½´ï¶Óβ
{
Error_code = ERROR_SCH_TOO_MANY_TASKS;
return SCH_MAX_TASKS;
}
// ÈÎÎñ¶ÓÁÐÖÐÓпռä
SCH_Clear_Task(Index); //ÏÈÇå¿Õ£¬ÔÙ¸³Öµ
SCH_tasks[Index].pTask = pFunction;
SCH_tasks[Index].Delay_MS = DELAY;
SCH_tasks[Index].Period_TICKS = PERIOD;
SCH_tasks[Index].Preemptive_En = PREEMPTIVE_EN;
SCH_tasks[Index].RunMe = 0;
return Index;
}
1.2、删除任务
INT8U SCH_Delete_Task(const INT8U TASK_ID)
{
INT8U Return_code;
if(SCH_tasks[TASK_ID].pTask == NULL)
{
Error_code = ERROR_SCH_CANNOT_DELETE_TASK; //ÉèÖÃÈ«¾Ö´íÎó±äÁ¿
Return_code = RETURN_ERROR;
}
else
{
Return_code = RETURN_NORMAL;
SCH_tasks[TASK_ID].pTask = NULL;
}
return Return_code;
}
1.3、启动任务
static void SCH_Go_To_Sleep() // ÔÚSCH_Start_Tasks()ĩβ´¦½øÈë¿ÕÏÐģʽ£¬µ±CPUÊÕµ½ÈκÎÖжÏʱ·µ»ØÕý³£Ä£Ê½
{
PCON |= 0x01;
}
void SCH_Start_Tasks(void) // ´Ëº¯ÊýÖ»µ÷¶ÈºÏ×÷ʽÈÎÎñ£¬ÇÀռʽÈÎÎñÔÚT0µÄISRÖе÷¶È
{
INT8U Index;
SCH_Start_Ticks();
while(1)
{
for(Index = 0; Index < SCH_MAX_TASKS; Index++)
{
if((SCH_tasks[Index].Preemptive_En == 0) && (SCH_tasks[Index].RunMe > 0)) // Èç¹ûµ±Ç°ÈÎÎñÊǺÏ×÷ʽÈÎÎñÇÒÒѾÍÐ÷
{
(*SCH_tasks[Index].pTask)(); // ÔËÐиÃÈÎÎñ
SCH_tasks[Index].RunMe -= 1;
if(SCH_tasks[Index].Period_TICKS == 0) // Èç¹ûÕâÊǸö¡°µ¥´Î¡±ÈÎÎñ£¬½«Ëü´Ó¶ÓÁÐÖÐɾ³ý
{
SCH_Delete_Task(Index);
}
}
}
SCH_Go_To_Sleep(); //µ÷¶ÈÆ÷½øÈë¿ÕÏÐģʽ
}
}
1.4、清理任务资源
void SCH_Clear_Task(const INT8U Index) // Çå¿ÕµÚIndex¸öÈÎÎñ¿é
{
SCH_tasks[Index].pTask = NULL;
SCH_tasks[Index].Delay_MS = 0;
SCH_tasks[Index].Period_TICKS = 0;
SCH_tasks[Index].Preemptive_En = 0;
SCH_tasks[Index].RunMe = 0;
}
2、抢占式任务调度
void SCH_Update(void) interrupt INTERRUPT_TIM_0_OF // T0_TICK_TIME_MS(ms) ¶¨Ê±µ½
{
INT8U Index;
SCH_Timer0_Reload();
MS_Counter += T0_TICK_TIME_MS ; // ÿT0_TICK_TIME_MSms×ÔÔöT0_TICK_TIME_MSms
for(Index = 0; Index < SCH_MAX_TASKS; Index++)
{
if(SCH_tasks[Index].pTask) // ×¢Ò⣬pTaskÓпÉÄÜΪ¿Õ£¬ÒòΪSCH_MAX_TASKS¿ÉÒÔ´óÓÚʵ¼ÊÌí¼ÓµÄÈÎÎñÊý
{
if(SCH_tasks[Index].Delay_MS <= 0)
{
if(SCH_tasks[Index].Preemptive_En == 1) // ΪÇÀռʽÈÎÎñ£¬ÔòÁ¢¼´ÔËÐÐ
{
(*SCH_tasks[Index].pTask)();
SCH_tasks[Index].RunMe -= 1; // RunMe±êÖ¾¸´Î»/¼õ1
if(SCH_tasks[Index].Period_TICKS == 0) // Èç¹ûÕâ¸öÇÀռʽÈÎÎñÊǸö¡°µ¥´Î¡±ÈÎÎñ£¬½«Ëü´Ó¶ÓÁÐÖÐɾ³ý£¬·ñÔò¼ÌÐøÔËÐÐ
{
SCH_tasks[Index].pTask = NULL; // SCH_Delete_Task(Index);
}
}
else //ΪºÏ×÷ʽÈÎÎñ
{
SCH_tasks[Index].RunMe += 1;
}
if(SCH_tasks[Index].Period_TICKS) // Period != 0±íʾ¸ÃÈÎÎñÖÜÆÚÐÔÖ´ÐУ¬·ñÔò£¬Ö»Ö´ÐÐÒ»´Î
{
SCH_tasks[Index].Delay_MS = SCH_tasks[Index].Period_TICKS * TICKS_TIME_MS;
}
}
else
{
SCH_tasks[Index].Delay_MS -= T0_TICK_TIME_MS; // ¼õÈ¥¶¨Ê±²½³¤
}
}
}
}
3、示例
void main(void)
{
SCH_Init_T0_UART(); //ͬʱ³õʼ»¯¶¨Ê±Æ÷ºÍUART
SCH_Add_Task (Task_Pulse_50ms, 0, 1, 0); // cooperative
SCH_Add_Task (Task_Pulse_100ms, 0, 2, 0); // cooperative
SCH_Add_Task (Task_Pulse_200ms, 0, 4, 0); // cooperative
SCH_Add_Task (Task_Pulse_400ms, 0, 8, 0); // cooperative
SCH_Add_Task (Task_Pulse_800ms, 0, 16, 0); // cooperative
SCH_Start_Tasks();
}
void SCH_Init_T0_UART(void)
{
INT8U Index;
for(Index = 0; Index < SCH_MAX_TASKS; Index++)
{
SCH_Clear_Task(Index);
}
Error_code = 0;
TMOD = 0x21; // T1:Gate C/T M1 M0 T0:Gate C/T M1 M0
// 0010 0001£ºT1 ·½Ê½2¶¨Ê±£¬8λ³õÖµÖØ×°£¬T0:¶¨Ê±Æ÷,·½Ê½1(16λ)
SCH_Timer0_Reload();
SCON = 0x40; // SCON=0100 0000£¬´®¿ÚÒÔ·½Ê½1¹¤×÷, 8벨ÌØÂʿɱä, 1Æðʼλ8Êý¾Ýλ1ֹͣλ
#if USE_UART ==1 //ʹÓô®¿Ú
#if BAUDRATE == 9600UL
PCON = 0x00; //PCON=0000 0000B£¬²¨ÌØÂʲ»±¶Ôö, ²¨ÌØÂÊ9600, ¾§Õñ11.0592
TH1 = 0xFd; //²¨ÌØÂÊ£º9600 bps
TL1 = 0xFd;
#endif
#if BAUDRATE == 57600UL
PCON = 0x80;
TH1 = 0xFF;
TL1 = 0xFF;
#endif //ÀàËƵĿÉÒÔ×Ô¶¨ÒåÉèÖó£Óò¨ÌØÂÊ£¬ÆäÖУ¬UL²»ÄÜÊ¡ÂÔ,´ú±í³¤ÕûÐÍ
#endif
EA = 1; //¿ª×ÜÖжÏ(±ØÐ뿪Æô)
ET0 = 1; //¿ªÆôT0¶¨Ê±ÖжÏ(±ØÐ뿪Æô)
ET1 = 0; //½ûÖ¹T1¶¨Ê±ÖжÏ(±ØÐë½ûÖ¹£¬ÒòΪT1ÒÔÓÃÓÚ²úÉú²¨ÌØÂÊ)
#if (USE_UART_RI==1 || USE_UART_TI==1)
ES = 1; //¿ªÆô´®¿ÚÖжÏ
#else
ES = 0; //½ûÖ¹´®¿ÚÖжÏ
#endif
#if USE_UART ==1 //ʹÓô®¿Ú
TR1 = 1; //T1¿ªÊ¼´®¿Ú¶¨Ê±²úÉú²¨ÌØÂÊ
#else
TR1 = 0; //½ûÖ¹T1´®¿Ú¶¨Ê±²úÉú²¨ÌØÂÊ
#endif
TR0 = 0; //µ±Ç°½ûÖ¹T0¶¨Ê±(ϵͳÆô¶¯¶àÈÎÎñʱÔÙ¿ªÆô)
}