Darren_pty

导航

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 的运行!\r\n");
112                 break;
113                 case TASK1_RESUME:
114                 vTaskResume(Task1_Handler); //恢复任务 1 
115                 printf("恢复任务 1 的运行!\r\n");
116                 break;
117                 case TASK2_SUSPEND:
118                 vTaskSuspend(Task2_Handler);//挂起任务 2 
119                 printf("挂起任务 2 的运行!\r\n");
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次\n", 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次\n", 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的运行!\r\n");
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 }

 

执行结果:

 

posted on 2020-12-20 18:14  Darren_pty  阅读(498)  评论(0编辑  收藏  举报