UCOSIII(三)如何用挂起任务和恢复任务实现自己想要它实现的任务

基本流程:

共5个自己的任务(不计入系统任务)

1. start_task:用来创建其他任务,创建完其他任务就把自己挂起,并且把其他功能任务也挂起,仅执行一次,且他的优先级在个人任务中是最高的

2. task:用来串口接收数据,并且判断来的数据,该执行什么任务,因为在start任务中已经把功能任务挂起了,这里只要通过比对来的数据来恢复对应任务就可以了

3.led0_task,led1_task,led2_task: 三个功能任务,在task任务把自己恢复以后,执行完一次就立即把自己挂起,等待task的下一次恢复任务。

做了一个流程图,应该比较清楚,

 

 

 代码:

五个任务的定义:

#define START_TASK_PRIO 3 //define priority
#define START_TASK_STK_SIZE 128 //define the task stack size
OS_TCB START_TASK_TCB; //define task control block
CPU_STK START_TASK_STK[START_TASK_STK_SIZE];//define task stack
void start_task(void *p_arg);//(void *p_arg ) is necessary

#define TASK_PRIO 4 //define priority
#define TASK_STK_SIZE 128 //define the task stack size
OS_TCB TASK_TCB; //define task control block
CPU_STK TASK_STK[TASK_STK_SIZE];//define task stack
void task(void *p_arg);//(void *p_arg ) is necessary

#define LED0_TASK_PRIO 5 //define priority
#define LED0_TASK_STK_SIZE 128 //define the task stack size
OS_TCB LED0_TASK_TCB; //define task control block
CPU_STK LED0_TASK_STK[LED0_TASK_STK_SIZE];//define task stack
void led0_task(void *p_arg);//(void *p_arg ) is necessary

#define LED1_TASK_PRIO 6 //define priority
#define LED1_TASK_STK_SIZE 128 //define the task stack size
OS_TCB LED1_TASK_TCB; //define task control block
CPU_STK LED1_TASK_STK[LED0_TASK_STK_SIZE];//define task stack
void led1_task(void *p_arg);//(void *p_arg ) is necessary

#define LED2_TASK_PRIO 7 //define priority
#define LED2_TASK_STK_SIZE 128 //define the task stack size
OS_TCB LED2_TASK_TCB; //define task control block
CPU_STK LED2_TASK_STK[LED2_TASK_STK_SIZE];//define task stack
void led2_task(void *p_arg);//(void *p_arg ) is necessary

 

主函数:

int main(void)
{
    OS_ERR  err;
    CPU_SR_ALLOC();
    
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz   
  HAL_Init();                     //初始化HAL库
  delay_init(180);                //初始化延时函数
  uart_init(115200);              //初始化USART
  LED_Init();                     //初始化LED 
  OSInit(&err);
    
    OS_CRITICAL_ENTER();//进入代码临界保护区
    
    OSTaskCreate (&START_TASK_TCB, (CPU_CHAR *)"start_task",start_task,0,START_TASK_PRIO,START_TASK_STK,START_TASK_STK_SIZE/10,START_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err);
    
    OS_CRITICAL_EXIT();//退出代码临界保护区
    OSStart(&err);      //开启UCOSIII
    while(1);
}

 

开始任务函数(start_task):

void start_task(void *p_arg)
{
    
    OS_ERR  err;
    CPU_SR_ALLOC();
    CPU_Init();
    OS_CRITICAL_ENTER();//进入代码临界保护区
    //创建其余四个任务
    OSTaskCreate (&TASK_TCB, (CPU_CHAR *)"task",task,0,TASK_PRIO,TASK_STK,TASK_STK_SIZE/10,TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err);
    OSTaskCreate (&LED0_TASK_TCB, (CPU_CHAR *)"led0_task",led0_task,0,LED0_TASK_PRIO,LED0_TASK_STK,LED0_TASK_STK_SIZE/10,LED0_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err);
    OSTaskCreate (&LED1_TASK_TCB, (CPU_CHAR *)"led1_task",led1_task,0,LED1_TASK_PRIO,LED1_TASK_STK,LED1_TASK_STK_SIZE/10,LED1_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err);
    OSTaskCreate (&LED2_TASK_TCB, (CPU_CHAR *)"led2_task",led2_task,0,LED2_TASK_PRIO,LED2_TASK_STK,LED2_TASK_STK_SIZE/10,LED2_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err);
    
    OS_CRITICAL_EXIT();//退出代码临界保护区
  //挂起三个功能任务和自身
    OS_TaskSuspend((OS_TCB*)&LED0_TASK_TCB,&err);
    OS_TaskSuspend((OS_TCB*)&LED1_TASK_TCB,&err);
    OS_TaskSuspend((OS_TCB*)&LED2_TASK_TCB,&err);
    OS_TaskSuspend((OS_TCB*)&START_TASK_TCB,&err);        //挂起自身开始任务    
}

 

选择功能函数(task):

void task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    while(1)
    {
        if(USART_RX_STA&0x8000)//用串口来接收数据,来执行相应任务
    {                       
            len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
            left((char *)temp,(char *)USART_RX_BUF, len);
            if(strcmp((const char *)temp,"任务1")==0)
            {
                OSTaskResume((OS_TCB*)&LED0_TASK_TCB,&err);        
            }
            else if(strcmp((const char *)temp,"任务2")==0)
            {
                OSTaskResume((OS_TCB*)&LED1_TASK_TCB,&err);
            }
            else if(strcmp((const char *)temp,"任务3")==0)
            {
                OSTaskResume((OS_TCB*)&LED2_TASK_TCB,&err);
            } 
            USART_RX_STA=0;
            OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err);
    }
    }
}

 

功能任务1(led0_task):

void led0_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    while(1)
    {
      printf("\r\n 0 \r\n");    
      OS_TaskSuspend((OS_TCB*)&LED0_TASK_TCB,&err);
    }
}

功能任务2(led1_task):

void led1_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
        while(1)
    {
      printf("\r\n 1 \r\n");    
      OS_TaskSuspend((OS_TCB*)&LED1_TASK_TCB,&err);
    }
}

功能任务3(led2_task):

void led2_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
      while(1)
    {
      printf("\r\n 2 \r\n");    
      OS_TaskSuspend((OS_TCB*)&LED2_TASK_TCB,&err);
    }    
}

 

注意事项:

1. 在task任务中,最后一定加函数   OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err);   这是个延时函数,但是它还有跳出这个任务执行下一个任务的功能,如果不加这个函数,mcu将一直执行task这个任务,跳不出来。

2. 在功能任务中一定要加 while(1) 循环,否则这个任务执行一次就不再执行了,就算task中恢复任务,他也不执行,因为函数已经执行完了,没什么可以执行的了,所以想要连续的执行这个任务,就得加循环

3. 任务挂起有一个不好的地方,就是等待,在正点原子的书中写到   “ OSTaskResume()函数用来恢复被OSTaskSuspend()函数挂起的任务, OSTaskResume()函数是唯一能恢复被挂起任务的函数。如果被挂起的任务还在等待别的内核对象,比如事件标志组、信号量、互斥信号量、消息队列等,即使使用OSTaskResume()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行 “.所以他不能很快的做出响应,这一点一定要注意,快相应的场合这个不适用。(谨慎使用)

 

posted @ 2020-10-02 11:02  采风远行  阅读(797)  评论(0编辑  收藏  举报