zoukankan      html  css  js  c++  java
  • 5-FreeRTOS任务挂起和恢复

    注意事项:

     ① 中断服务函数中不能使用任务延时函数vTaskDelay,使用任务API也要带有ISR

    xTaskResumeFromISR(任务句柄)   //在中断中恢复任务;

    portYIELD_FROM_ISR()  //上下文切换,当恢复任务优先级等于或高于正在运行任务时,退出中断的时候一定要进行上下文切换;

    需求:

    ①按键KEY_UP控制TASK1任务的挂起和恢复

    ②按键KEY1控制TASK2任务的挂起

    ③按键KEY0控制着TASK2任务的恢复(KEY0属于中断事件控制)

    代码:

    ①任务code

      1 #define TASK1_SUSPEND    1        //WK_UP  
      2 #define TASK1_RESUME    2         
      3 #define TASK2_SUSPEND    3        // KEY1
      4 
      5  //----------------------------------------任务优先级
      6  #define START_TASK_PRIO     1 
      7  #define KEY_TASK_PRIO       2
      8  #define TASK1_PRIO          3 
      9  #define TASK2_PRIO          4 //优先级高
     10  
     11  
     12  //----------------------------------------任务堆栈大小
     13  #define START_STK_SIZE 128 
     14  #define TASK1_STK_SIZE 128 
     15  #define TASK2_STK_SIZE 128 
     16  #define KEY_STK_SIZE   128 
     17  
     18  //----------------------------------------任务句柄
     19  TaskHandle_t Task1_Handler; 
     20  TaskHandle_t Task2_Handler; 
     21  TaskHandle_t StartTask_Handler; 
     22  TaskHandle_t KeyTask_Handler; //任务句柄
     23  
     24  
     25  //----------------------------------------任务函数
     26  void start_task(void *pvParameters); 
     27  void task1_task(void *pvParameters); 
     28  void task2_task(void *pvParameters); 
     29  void key_task(void *pvParameters); //任务函数
     30 
     31  
     32  int main(void)
     33  {
     34    BaseType_t OS;
     35    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  
     36    User_GPIO_Init();
     37      Exit_Init();
     38      Delay_init();
     39      USART_Config();
     40      
     41  //  TIM6_Time_Init(9999,7199);//定时1s
     42  //  TIM7_Time_Init(9999,7199);//定时1s
     43  
     44      
     45      OS= xTaskCreate(
     46                                             (TaskFunction_t        ) start_task,       //任务函数
     47                                             (const char *          )  "start_task",    //任务名
     48                                             (configSTACK_DEPTH_TYPE) START_STK_SIZE,   //堆栈大小
     49                                             (void *                )NULL,              //传递给任务函数的参数
     50                                             (UBaseType_t           ) START_TASK_PRIO,  //任务优先级
     51                                             (TaskHandle_t *        ) &StartTask_Handler  //任务句柄
     52                     );
     53                                   
     54      if(OS==pdPASS) 
     55          GPIO_SetBits(GPIOA, GPIO_Pin_8);
     56          
     57      vTaskStartScheduler(); //开启任务调度
     58      
     59  }
     60  
     61  
     62  void start_task(void *pvParameters)
     63  {
     64   
     65          taskENTER_CRITICAL(); //进入临界区
     66          
     67        //创建任务Task1
     68 xTaskCreate((TaskFunction_t )task1_task, //任务函数
     69          (const char* )"task1_task", //任务名称
     70          (uint16_t )TASK1_STK_SIZE, //任务堆栈大小
     71          (void* )NULL,
     72          (UBaseType_t )TASK1_PRIO, //任务优先级
     73          (TaskHandle_t* )&Task1_Handler); //任务句柄
     74  
     75          
     76          
     77          //创建任务Task2
     78 xTaskCreate((TaskFunction_t )task2_task, //任务函数
     79          (const char* )"task2_task", //任务名称
     80          (uint16_t )TASK2_STK_SIZE, //任务堆栈大小
     81          (void* )NULL,
     82          (UBaseType_t )TASK2_PRIO, //任务优先级
     83          (TaskHandle_t* )&Task2_Handler); //任务句柄
     84                  
     85                  
     86                  //创建Task3
     87 xTaskCreate((TaskFunction_t )key_task, //任务函数
     88          (const char* )"key_task", //任务名称
     89          (uint16_t )KEY_STK_SIZE, //任务堆栈大小
     90          (void* )NULL,
     91          (UBaseType_t )KEY_TASK_PRIO, //任务优先级
     92          (TaskHandle_t* )&KeyTask_Handler); //任务句柄
     93                  
     94          
     95          vTaskDelete(StartTask_Handler); //vTaskDelete(NULL)也可以   删除开始任务
     96          taskEXIT_CRITICAL();            //退出临界区
     97  }
     98  
     99  
    100 
    101 void key_task(void *pvParameters)
    102 {
    103     u8 key;
    104     while(1)
    105     {
    106             key=KEY_Scan();
    107             switch(key)
    108             {
    109                 case TASK1_SUSPEND:
    110                 vTaskSuspend(Task1_Handler); //挂起任务 1 
    111                 printf("挂起任务 1 的运行!
    ");
    112                 break;
    113                 case TASK1_RESUME:
    114                 vTaskResume(Task1_Handler); //恢复任务 1 
    115                 printf("恢复任务 1 的运行!
    ");
    116                 break;
    117                 case TASK2_SUSPEND:
    118                 vTaskSuspend(Task2_Handler);//挂起任务 2 
    119                 printf("挂起任务 2 的运行!
    ");
    120                 break;
    121             }
    122             vTaskDelay(10); //延时 10ms
    123     }
    124 }
    125  
    126  
    127  //任务1
    128  void task1_task(void *pvParameters)
    129  {  
    130      uint8_t count_num=0; 
    131      while(1)
    132      {
    133        count_num++;
    134        printf("任务1执行:%d次
    ", count_num);
    135 
    136        vTaskDelay(1000);  //延时1000个时钟节拍,就是1s   configTICK_RATE_HZ
    137      }
    138          
    139  }
    140   
    141   //任务2
    142  void task2_task(void *pvParameters)
    143  {  
    144     uint8_t count_num1=0;
    145     while(1)
    146     {
    147       count_num1++;
    148       printf("任务2执行:%d次
    ", count_num1);
    149       
    150             vTaskDelay(1000);
    151    }
    152  }

    ②KEY0外部中断函数

     1 #define KEY0    GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)//读取按键0
     2 
     3 
     4 extern TaskHandle_t Task2_Handler;
     5 
     6 //外部中断初始化函数
     7 void Exit_Init(void)
     8 {
     9  
    10     EXTI_InitTypeDef EXTI_InitStructure;    
    11     NVIC_InitTypeDef NVIC_InitStructure;
    12 
    13   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
    14 
    15 
    16    //GPIOC5 中断线以及中断初始化配置
    17   GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
    18 
    19     EXTI_InitStructure.EXTI_Line=EXTI_Line5;
    20     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    
    21     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    22     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    23     EXTI_Init(&EXTI_InitStructure);         //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
    24 
    25     
    26     NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;            //使能按键所在的外部中断通道
    27     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;//抢占优先级6 
    28     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //子优先级0
    29     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能外部中断通道
    30     NVIC_Init(&NVIC_InitStructure); 
    31 }
    32 
    33 
    34 
    35 
    36 void EXTI9_5_IRQHandler(void)
    37 {    
    38     BaseType_t YieldRequired;    
    39     delay_xms(20);  //消抖        
    40     if(KEY0==0)    
    41     {
    42         delay_xms(20);  //消抖
    43         YieldRequired=xTaskResumeFromISR(Task2_Handler);//恢复任务2
    44         printf("恢复任务2的运行!
    ");
    45         if(YieldRequired==pdTRUE)
    46         {
    47 /*如果函数xTaskResumeFromISR()返回值为pdTRUE,那么说明要恢复的这个任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),所以在
    48 退出中断的时候一定要进行上下文切换!*/
    49             portYIELD_FROM_ISR(YieldRequired); 
    50         }
    51     }
    52       EXTI_ClearITPendingBit(EXTI_Line5);    //清除LINE5上的中断标志位  
    53 }

    ③GPIO初始化及按键检测

     1 #define KEY0    GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)//读取按键0
     2 #define KEY1    GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)//读取按键1
     3 #define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键2 
     4 
     5 #define TASK1_SUSPEND    1        //WK_UP  
     6 #define TASK1_RESUME    2      //WK_UP 
     7 #define TASK2_SUSPEND    3        // KEY1
     8 
     9 uint8_t Task1_flag=2;//挂起和恢复Task1
    10 
    11 
    12 
    13 void User_GPIO_Init(void)
    14 {
    15   //LED  PA8 PD2
    16   GPIO_InitTypeDef GPIO_InitStructure;
    17   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
    18     GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试
    19 
    20   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    21   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    22   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    23   GPIO_Init(GPIOD, &GPIO_InitStructure);
    24 
    25   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    26   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    27   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    28   GPIO_Init(GPIOA, &GPIO_InitStructure);
    29     
    30     
    31     //KEY PA0(上拉)    PC5      PA15
    32   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    33   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    34   GPIO_Init(GPIOC, &GPIO_InitStructure);
    35     
    36     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
    37   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    38   GPIO_Init(GPIOA, &GPIO_InitStructure);
    39     
    40   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    41   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    42   GPIO_Init(GPIOA, &GPIO_InitStructure);
    43 }
    44 
    45 
    46 
    47 u8 KEY_Scan(void)
    48 {     
    49       
    50     if((KEY1==0||WK_UP==1))
    51     {
    52         delay_xms(20);  //消抖
    53 
    54             
    55         if(KEY1==0)
    56         {
    57           while(! KEY1);
    58             return TASK2_SUSPEND;
    59         }
    60             
    61         else if(WK_UP==1)
    62         {
    63           while(WK_UP);
    64             Task1_flag = !Task1_flag;//第一次是0
    65             if(!Task1_flag)//0
    66               return TASK1_SUSPEND; 
    67             if(Task1_flag)
    68               return TASK1_RESUME; 
    69         }            
    70 
    71     }     
    72     return 0;// 无按键按下
    73 }

    执行结果:

  • 相关阅读:
    Controlling behavior of existing services in system
    获取站点路径方法
    如何处理DataTable.Select();执行后重新排序的问题!
    ASP.NET 2.0 编程珠玑之五调试已创建好的代码
    Meal Scheduler in C#
    DHTML+Ajax? MXML+ActionScript? XAML+C#? 是巧合,还是必然?
    C#验证输入的是否数字
    Monitoring System Usage using Windows Service
    ADO.NET 2.0中的DataSet和DataTable
    使用asp.net 2.0和SQL SERVER 2005构建多层应用
  • 原文地址:https://www.cnblogs.com/darren-pty/p/14164391.html
Copyright © 2011-2022 走看看