【IoT】如何写一个可以简单处理多任务的小系统(51单片机为例)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liwei16611/article/details/82350891

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¶¨Ê±(ϵͳÆô¶¯¶àÈÎÎñʱÔÙ¿ªÆô)  	
}

猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/82350891