上一期配置完FreeRTOS的环境后,这一期记录自己关于任务创建的学习过程。
官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。
xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄
vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。
因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。
任务函数编写
/*
LED1翻转
*/
void LED_TOG(void * pvParameters)//参数为 void * pvParameters
{
while(1)
{
printf('LED_TOG runningrn');//串口打印运行信息
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转
vTaskDelay(500);//延迟500ms
}
}
要注意的是vTaskDelay是FreeRTOS用来延时的函数。
之后我们要创建任务函数的启动函数
TaskHandle_t Start_LED_Handler;
void Start_LED(void * pvParameters)
{
xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
(char * )'LED_TOG',//任务名称
(configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
(void* ) NULL,//无返回
(UBaseType_t ) 1,//优先级1
(TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
vTaskDelete(NULL);
}
我们创建启动任务的函数,将 任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄 ,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。
同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务)
void FreeRTOS_Init()
{
xTaskCreate((TaskFunction_t )Start_LED,
(char * )'Start_LED',
(configSTACK_DEPTH_TYPE) 128,
(void* ) NULL,
(UBaseType_t ) 0,
(TaskHandle_t * )Start_LED_Handler);
vTaskStartScheduler();//启动运行函数
}
这样子我们在主函数中添加刚刚定义的启动启动函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
KEY_Init();
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
FreeRTOS_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
我们的代码就可以正常运行啦!
我们在用上述的方法实现两个灯一起翻转
还是先编辑任务函数如下,并且定义其相关句柄
TaskHandle_t LED_TOG2_Handler;
void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
{
while(1)
{
printf('LED_TOG runningrn');//串口打印运行信息
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转
vTaskDelay(500);//延迟500ms
}
}
在任务启动函数中加入我们新建的任务。
void Start_LED(void * pvParameters)
{
xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
(char * )'LED_TOG',//任务名称
(configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
(void* ) NULL,//无返回
(UBaseType_t ) 1,//优先级1
(TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数
(char * )'LED_TOG2',//任务名称
(configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
(void* ) NULL,//无返回
(UBaseType_t ) 2,//优先级2
(TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄
vTaskDelete(NULL);
}
再次运行我们的代码。
麦克阿瑟将军曾说过:点灯对于嵌入式来说,就像Hello World对于程序员一样重要。我们不能不去点灯,就像西方不能失去耶路撒冷。
上一篇:基于STM32F407的FreeRTOS学习笔记(4)
下一篇:学习STM32单片机,要理解它的堆栈
推荐阅读最新更新时间:2024-11-13 16:45
设计资源 培训 开发板 精华推荐
- LTC3838EUHF-1 6.5V 至 34V 输入、5V/12A 和 3.3V/12A 双路输出、300kHz、RSENSE、5V 输出连接至 EXTVCC、降压转换器的典型应用电路
- 回流焊温控器
- LT3091IDE 并联线性稳压器的典型应用
- EVAL-RHF1401V2,基于 RHF1201 14 位、30 MSPS ADC 的评估板
- SOP-8封装差分运放 单端转差分Demo
- LT1086CT-3.3 低压差负电源的典型应用
- REP010: 工作在183MHz IF的双频IS-136前端IC
- AM2G-0507DH30Z ±7.2V 2 瓦 DC-DC 转换器的典型应用
- 基于HVLED815的评估板:具有初级侧电流调节的10 W宽范围高功率因数隔离LED驱动器
- AM2G-0509SZ 9V 2 瓦 DC-DC 转换器的典型应用,用于开/关控制应用