目录
FreeRTOS学习第2篇–创建任务(动态方法和静态方法)
一、示例功能
基于我现有的硬件,完成一个多任务的编程。在本次示例中,创建了4个任务。4个任务分别是:StartDefaultTask、ColorLED_Test、PlayMusic、IRReceiver_Test。其中StartDefaultTask是翻转LED的值、ColorLED_Test是一个全彩的灯、PlayMusic是一个无源蜂鸣器播放孤勇者的任务、IRReceiver_Test是一个接收红外码值的任务。
二、StartDefaultTask任务源码
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
mdelay(100);
}
/* USER CODE END StartDefaultTask */
}
三、ColorLED_Test任务源码
void ColorLED_Test(void * pvParameters)
{
uint32_t color = 0;
ColorLED_Init();
while (1)
{
//LCD_PrintString(0, 0, "Show Color: ");
//LCD_PrintHex(0, 2, color, 1);
ColorLED_Set(color);
color += 200000;
color &= 0x00ffffff;
mdelay(1000);
}
}
四、PlayMusic任务源码
void MUSIC_Analysis(void){
uint16_t MusicBeatNum = ((((sizeof(Music_Lone_Brave))/2)/3)-1);
uint16_t MusicSpeed = Music_Lone_Brave[0][2];
for(uint16_t i = 1;i<=MusicBeatNum;i++){
//BSP_Buzzer_SetFrequency(Tone_Index[Music_Lone_Brave[i][0]][Music_Lone_Brave[i][1]]);
PassiveBuzzer_Set_Freq_Duty(Tone_Index[Music_Lone_Brave[i][0]][Music_Lone_Brave[i][1]], 50);
//HAL_Delay(MusicSpeed/Music_Lone_Brave[i][2]);
mdelay(MusicSpeed/Music_Lone_Brave[i][2]);
}
}
void PlayMusic(void *params)
{
PassiveBuzzer_Init();
while (1)
{
MUSIC_Analysis();
}
}
五、IRReceiver_Test任务源码
void IRReceiver_Test(void * pvParameters)
{
uint8_t dev, data;
OLED_Init();
IRReceiver_Init();
while(1)
{
OLED_ShowString(0,0,"IR Receiver: ",16);
OLED_ShowString(0,16,"Device Data",16);
if (!IRReceiver_Read(&dev, &data))
{
OLED_ShowString(0, 32, " ",16);
OLED_ShowNum(0,32,dev,4,16);
OLED_ShowNum(64,32,data,4,16);
OLED_ShowString(0, 48, " ",16);
OLED_ShowString(0,48,"Key name: ",16);
OLED_ShowString(80,48,(u8 *)IRReceiver_CodeToString(data),16);
}
OLED_Refresh(); // 刷新屏幕
}
}
六、创建任务
相关功能的代码片段
/* USER CODE BEGIN Header */
#include "driver_timer.h"
#include "driver_color_led.h"
#include "driver_passive_buzzer.h"
#include "driver_ir_receiver.h"
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2023 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
static StackType_t g_pucStackOfColorTask[128];
static StaticTask_t g_TCBofColorTask;
static TaskHandle_t xColorTaskHandle;
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
TaskHandle_t xSoundTaskHandle;
BaseType_t ret;
/* 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) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* 创建任务: 色 */
xColorTaskHandle = xTaskCreateStatic(ColorLED_Test, "ColorTask", 128, NULL, osPriorityNormal, g_pucStackOfColorTask, &g_TCBofColorTask);
/* 创建任务: 声 */
extern void PlayMusic(void *params);
ret = xTaskCreate(PlayMusic, "SoundTask", 128, NULL, osPriorityNormal, &xSoundTaskHandle);
xTaskCreate( IRReceiver_Test, "IRReceiver_Test", configMINIMAL_STACK_SIZE, NULL, osPriorityNormal, NULL );
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
mdelay(100);
}
/* USER CODE END StartDefaultTask */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
xTaskCreate 创建
使用 xTaskCreate 函数是在 FreeRTOS 中创建任务的一种方法,函数原型如下:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
1.TaskFunction_t pvTaskCode:任务函数的指针。这个参数是一个函数指针,指向一个任务的实际执行代码。任务函数的原型必须符合 TaskFunction_t 类型,即 void func(void *pvParameters),其中 pvParameters 是一个指向和任务相关的参数的指针。
2.const char * const pcName:任务的名称。这个参数是一个字符串常量,用于标识任务。
3.const configSTACK_DEPTH_TYPE usStackDepth:任务栈的大小。这个参数表示任务栈的深度、空间或者大小,单位是world,也就是按4 字节来算。在创建任务时需要提供一个足够大的堆栈以确保任务可以运行。
4.void * const pvParameters:任务参数的指针。这个参数是任务的实际参数,它的类型可以是 void 指针或者其他任意类型的指针。在任务执行时,可以通过此参数来传递任务需要的参数。
5.UBaseType_t uxPriority:任务的优先级。这个参数用于指定任务的优先级,数值越大表示优先级越高。优先级的取值范围根据量化数值的位数而定,可以在cmsis_os2.h的文件中看到关于优先级的枚举
/// Priority values.
typedef enum {
osPriorityNone = 0, ///< No priority (not initialized).
osPriorityIdle = 1, ///< Reserved for Idle thread.
osPriorityLow = 8, ///< Priority: low
osPriorityLow1 = 8+1, ///< Priority: low + 1
osPriorityLow2 = 8+2, ///< Priority: low + 2
osPriorityLow3 = 8+3, ///< Priority: low + 3
osPriorityLow4 = 8+4, ///< Priority: low + 4
osPriorityLow5 = 8+5, ///< Priority: low + 5
osPriorityLow6 = 8+6, ///< Priority: low + 6
osPriorityLow7 = 8+7, ///< Priority: low + 7
osPriorityBelowNormal = 16, ///< Priority: below normal
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
osPriorityNormal = 24, ///< Priority: normal
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
osPriorityAboveNormal = 32, ///< Priority: above normal
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
osPriorityHigh = 40, ///< Priority: high
osPriorityHigh1 = 40+1, ///< Priority: high + 1
osPriorityHigh2 = 40+2, ///< Priority: high + 2
osPriorityHigh3 = 40+3, ///< Priority: high + 3
osPriorityHigh4 = 40+4, ///< Priority: high + 4
osPriorityHigh5 = 40+5, ///< Priority: high + 5
osPriorityHigh6 = 40+6, ///< Priority: high + 6
osPriorityHigh7 = 40+7, ///< Priority: high + 7
osPriorityRealtime = 48, ///< Priority: realtime
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osPriority_t;
6.TaskHandle_t * const pxCreatedTask:用于返回创建的任务的句柄。创建任务成功后,系统将返回一个指向该任务的任务句柄。
xTaskCreateStatic创建
使用 xTaskCreateStatic() 函数静态创建任务。该函数与 xTaskCreate() 类似,但它使用静态分配的任务控制块和堆栈空间,而不是在运行时动态分配。函数原型如下:
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer )
通过静态创建方式,可以使用编译器的内存分配器来分配任务所需的内存空间,从而避免了动态分配内存的开销和潜在的内存泄漏问题。静态创建方式还可以在一些对内存使用有限制的场合下有效地管理系统资源,提高系统的稳定性和性能。
实验现象:
在我的硬件上LED灯正常翻转,全彩灯正常闪刷,无源蜂鸣器正常的播放声音,红外接收任务能正常接收红外值。
实验代码:
https://download.csdn.net/download/weixin_44317448/88548602
参考资源:
https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter9.html
https://www.bilibili.com/video/BV1Jw411i7Fz?p=16&vd_source=cc94aa2e05dfbf63745cf6a66a174b2f