zoukankan      html  css  js  c++  java
  • 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("
     0 
    ");    
          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("
     1 
    ");    
          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("
     2 
    ");    
          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()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行 “.所以他不能很快的做出响应,这一点一定要注意,快相应的场合这个不适用。(谨慎使用)

  • 相关阅读:
    python学习之计算机基础详解
    python学习笔记-day03
    名称空间与作用域
    函数参数的应用
    day14
    day13
    函数的基本使用
    day12
    day 09
    文件操作
  • 原文地址:https://www.cnblogs.com/CaiFengYuanXing/p/13760605.html
Copyright © 2011-2022 走看看