STM32f103C8T6 FreeRTOS - 按键实现任务挂起和恢复,按键按下时,LED任务执行,led闪烁,当led任务挂起,Led停止闪烁。

1.STM32CubeMX 创建任务

1.1配置GPIO
按键配置外部中断触发
GPIO绿灯,红灯配置输出模式

1.2配置FreeRTOS
创建按键与LED任务,按键优先级正常,LED优先级稍微低。

2.Keil编写
2.1 外部中断回调
在配置文件中stm32f1xx_hal_gpio.c 中,调用HAL_GPIO_EXTI_Callback
/**
* @brief EXTI line detection callbacks.
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
2.2 gpio.c按键实现Led颜色切换
//按键检测回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(Key1_Pin == GPIO_Pin) //判断按下的GPIO
{
if ( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET) //按下按键,导通
{
HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_SET);
}
}
else
{
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET) // 高电平,未准备好
{
HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET)
{
HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_SET); //关闭红灯
HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_RESET); //开启绿灯
}
}
}
}
}
3.实现任务挂起与恢复
3.1任务挂起和恢复函数

3.1.1 函数vTaskSuspend()
此函数用于将某个任务设置为挂起状态,进入挂起态的任务永远不会进入运行态。退出挂起态的唯一方法就是调用任务恢复函数vTaskResume()或xTaskResumeFromISR(),函数申明如下:
void vTaskSuspend( TaskHandle_t xTaskToSuspend)
入口参数:
xTaskToSuspend: 要挂起的任务的任务句柄。可通过函数xTaskGetHandle()来根据任务名字获取某个任务的任务句柄。如果参数为NULL表示挂起任务自己。
返回值:无

3.1.2 函数vTaskResume()
将一个任务从挂起态恢复到就绪态,只有通过函数vTaskSuspend()设置为挂起态的任务才可以用vTaskResume()恢复,函数申明如下:
void vTaskResume(TaskHandle_t xTaskToResume)
入口参数:
xTaskToResume: 要恢复的任务的任务句柄
返回值:无

3.2实现函数
gpio.h中建立标志位
/*定义一个枚举,建立三个状态*/
typedef enum{
Key_up,
Key_down,
Key_reset,
}teKeyStatus;
gpio.c
//按键检测回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(Key1_Pin == GPIO_Pin) //判断按下的GPIO
{
if ( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET) //按下按键,导通
{
HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET)
{
/*建立标志位*/
keyStatus = Key_down;
}
}
else
{
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET) // 高电平,未准备好
{
HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET)
{
/*建立标志位*/
keyStatus = Key_up;
}
}
}
}
}
freertos.c外部声明
extern teKeyStatus keyStatus; //外部申明
编写Task
/* USER CODE BEGIN Header_Key_Task */
/**
* @brief Function implementing the KeyTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Key_Task */
void Key_Task(void const * argument)
{
/* USER CODE BEGIN Key_Task */
keyStatus = Key_reset;
/* Infinite loop */
for(;;)
{
if(keyStatus == Key_up)
{
/*挂起LED任务*/
vTaskSuspend(LedTaskHandle);
keyStatus = Key_reset;
}
if(keyStatus == Key_down)
{
/*恢复LED任务*/
vTaskResume(LedTaskHandle);
keyStatus = Key_reset;
}
/* 扫描周期10ms */
osDelay(10);
}
/* USER CODE END Key_Task */
}
/* USER CODE BEGIN Header_Led_Task */
/**
* @brief Function implementing the LedTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Led_Task */
void Led_Task(void const * argument)
{
/* USER CODE BEGIN Led_Task */
/* Infinite loop */
for(;;)
{
HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_SET);
osDelay(500);
HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_RESET);
osDelay(500);
}
/* USER CODE END Led_Task */
}