1. 程式人生 > 實用技巧 >5-FreeRTOS任務掛起和恢復

5-FreeRTOS任務掛起和恢復

需求:

①按鍵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 }

執行結果: