FreeRTOS(3):任务挂起与恢复

📅 2026/7/29 5:27:18
FreeRTOS(3):任务挂起与恢复
任务简介任务大体上与上一篇文章的任务差不多但是将PB1连接的按键用来挂起任务PB11的按键用来恢复任务PB4的按键用中断恢复任务使用xTaskResumeFromISR函数。任务创建复制上一篇文章的FreeRTOS_任务创建与删除动态文件夹粘贴后改名为FreeRTOS_任务创建与恢复进入keil。代码编写由于PB4引脚是JTAG引脚所以在使用PB4引脚前要先释放该引脚然后配置中断具体函数如下笔者是直接将它加在了Key.c这个文件里的void PB4_EXTI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 1. 使能GPIOB、AFIO复用时钟EXTI必须AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // 2. 关闭JTAG释放PB3/PB4引脚F1必须加否则PB4无法做普通IO GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 3. 配置PB4 GPIO模式上拉输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; // 内部上拉输入 GPIO_Init(GPIOB, GPIO_InitStructure); // 4. 配置EXTI中断线PB4映射到EXTI4 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource4); EXTI_InitStructure.EXTI_Line EXTI_Line4; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; // 下降沿触发 EXTI_InitStructure.EXTI_LineCmd ENABLE; EXTI_Init(EXTI_InitStructure); // 5. NVIC中断优先级配置 NVIC_InitStructure.NVIC_IRQChannel EXTI4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0x06; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0x00; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); }随后在key.h这个函数里声明PB4_EXTI_Init函数使得外部能够调用该函数。随后打开FreeRTOS_Task.c文件由于我们定义了PB4_EXTI_Init函数所以我们要引用该函数笔者是直接将他加在别的初始化函数下方如下方代码所示void FreeRTOS_Task(void) { Key_Init(); LED_Init(); PB4_EXTI_Init(); xTaskCreate( (TaskFunction_t ) Start_task, (char * ) Start_task, (configSTACK_DEPTH_TYPE) START_TASK_SIZE, (void * ) NULL, (UBaseType_t ) START_TASK_PRIO, (TaskHandle_t * ) start_task_handle ); vTaskStartScheduler(); }随后更改一下task_3函数中的部分语句即可即将PA1所接按键的事件改为触发vTaskSuspend函数既将task_1任务挂起将PA1所接按键的事件改为触发vTaskResume函数既将task_1任务恢复参考代码如下void task_3( void * pvParameters ) { uint8_t KeyVal 0; while(1) { KeyVal Key_GetNum(); if(KeyVal ! 0) { vTaskDelay(pdMS_TO_TICKS(20)); // RTOS延时让出CPULED正常闪烁 if(Key_GetNum() KeyVal) // 二次确认消抖 { // 等待按键松开 while(Key_GetNum() ! 0) { vTaskDelay(pdMS_TO_TICKS(10)); } vTaskDelay(pdMS_TO_TICKS(20)); // 按键触发逻辑 if(KeyVal 1) { vTaskSuspend(task1_handle); } else if(KeyVal 2) { vTaskResume(task1_handle); } } } vTaskDelay(pdMS_TO_TICKS(10)); } }随后我们就可以写中断函数了在FreeRTOS_Task.c 文件最后添加EXTI4_IRQHandler中断函数用来使得PB4触发xTaskResumeFromISR函数具体代码如下void EXTI4_IRQHandler(void) { BaseType_t xNeedSwitch pdFALSE; if(EXTI_GetITStatus(EXTI_Line4) ! RESET) { // 硬件消抖确认PB4低电平按键按下 if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) 0) { // 中断专用恢复任务API xNeedSwitch xTaskResumeFromISR(task1_handle); } EXTI_ClearITPendingBit(EXTI_Line4); //清除中断标志位 } // 若唤醒更高优先级任务立即切换上下文 portYIELD_FROM_ISR(xNeedSwitch); }最后编译后下载即可实现现象。若有错误还望海涵。