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 阅读(519) 评论(0) 编辑 收藏 举报