对于FreeRTOS中的操作,最常用的就是创建、删除、暂停和恢复任务。
此次实验目标:
1.创建任务一:LED1每间隔1秒闪烁一次,并通过串口打印
2.创建任务二:LED2每间隔0.5秒闪烁一次,并通过串口打印
3.创建任务三:通过KEY1实现对任务一的创建和删除。
按键按下以后如果有任务一就删除任务一,没有任务一就创建任务一。
4. 创建任务四:通过KEY2实现对任务二的暂停和恢复。
按键按下以后如果任务二在执行就暂停任务二,任务二在暂停就恢复任务二。
实现方式:
使用正点原子探索者,主控芯片为STM32F407ZGT6。
一、主要的电气原理图如下:
二、CubeMX配置
1.设置FreeRTOS
2.设置usart1
波特率115200
3.设置时钟,选择外部高速时钟
配置时钟树如下
4.注意一定要修改时基
5.生成代码
三、编写代码(都在freertos.c中写)
1.串口重定向
#include <stdio.h>// 包含标准输入输出头文件
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
return ch;
}
2.实现任务的代码
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of LED1 */
osThreadDef(LED1, led1, osPriorityNormal, 0, 128);
LED1Handle = osThreadCreate(osThread(LED1), NULL);
/* definition and creation of LED2 */
osThreadDef(LED2, led2, osPriorityIdle, 0, 128);
LED2Handle = osThreadCreate(osThread(LED2), NULL);
/* definition and creation of KEY1 */
osThreadDef(KEY1, key1, osPriorityIdle, 0, 128);
KEY1Handle = osThreadCreate(osThread(KEY1), NULL);
/* definition and creation of KEY2 */
osThreadDef(KEY2, key2, osPriorityIdle, 0, 128);
KEY2Handle = osThreadCreate(osThread(KEY2), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
}
/* USER CODE BEGIN Header_led1 */
/**
* @brief Function implementing the LED1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_led1 */
void led1(void const * argument)
{
/* USER CODE BEGIN led1 */
/* Infinite loop */
for(;;)
{
printf("led1\n\r");
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);
osDelay(1000);
}
/* USER CODE END led1 */
}
/* USER CODE BEGIN Header_led2 */
/**
* @brief Function implementing the LED2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_led2 */
void led2(void const * argument)
{
/* USER CODE BEGIN led2 */
/* Infinite loop */
for(;;)
{
printf("led2\n\r");
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
osDelay(500);
}
/* USER CODE END led2 */
}
/* USER CODE BEGIN Header_key1 */
/**
* @brief Function implementing the KEY1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_key1 */
void key1(void const * argument)
{
/* USER CODE BEGIN key1 */
/* Infinite loop */
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
{
osDelay(20);//防误触
if(LED1Handle==NULL)
{
printf("key1==creat\n\r");
osThreadDef(LED1, led1, osPriorityNormal, 0, 128);
LED1Handle = osThreadCreate(osThread(LED1), (void*)"new task1");
}
else
{
vTaskDelete(LED1Handle);
LED1Handle=NULL;
printf("key1==delete\n\r");
}
}
}
/* USER CODE END key1 */
}
/* USER CODE BEGIN Header_key2 */
/**
* @brief Function implementing the KEY2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_key2 */
void key2(void const * argument)
{
/* USER CODE BEGIN key2 */
char Flag=0;
/* Infinite loop */
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
{
osDelay(20);//防误触
if(Flag==0)
{
printf("key2 suspend\n\r");
vTaskSuspend(LED2Handle);
Flag=1;
}
else
{
vTaskResume(LED2Handle);
printf("key2 resume \n\r");
Flag=0;
}
}
}
/* USER CODE END key2 */
}
/* Private application code --------------------------------------------------*/
注意:任务被删除时,句柄不会删除,需要手动清空。