FreeRTOS(9):队列的入队与出队

📅 2026/8/2 8:53:46 👁️ 阅读次数 📝 编程学习
FreeRTOS(9):队列的入队与出队

实验现象

实验步骤:

实验现象,在串口助手上观察现象:

项目创建

复制Freertos_列表项的插入与删除文件,粘贴并且重命名为Freertos_队列的入队与出队,进入keil,删除Timer.c 中的中断函数中的内容和函数头上队列句柄删除,如不删除,会发生报错,删除内容如下图所示:

进入FreeRTOS_Task.c文件,首先删除task1与task2中的代码,然后因为此次实验需要三个任务,创建task3,笔者就不多赘述了,随后定义需要的队列头,大数据队列等,如下图所示:

定义好这些后就可以去到FreeRTOS_Task任务中初始化队列了,初始化的同时将队列的创建结果使用串口打印出来,下方是FreeRTOS_Task的代码:

void FreeRTOS_Task(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); Key_Init(); LED_Init(); Serial_Init(); key_queue = xQueueCreate(2, sizeof(uint8_t)); Serial_Sendstring(key_queue ? "key_queue create successful\r\n" : "key_queue create failed\r\n"); big_data_queue = xQueueCreate(1, sizeof(char *)); Serial_Sendstring(big_data_queue ? "big_data_queue create successful\r\n" : "big_data_queue create failed\r\n"); xTaskCreate((TaskFunction_t)Start_task, "Start_task", START_TASK_SIZE, NULL, START_TASK_PRIO, &start_task_handle); vTaskStartScheduler(); }

注意,start_task中要有三个任务的创建函数,分别是task1,2,3,start_task任务的完整函数如下方所示:

void Start_task(void *pvParameters) { taskENTER_CRITICAL(); xTaskCreate((TaskFunction_t)task_1, "task_1", TASK1_SIZE, NULL, TASK1_PRIO, &task1_handle); xTaskCreate((TaskFunction_t)task_2, "task_2", TASK2_SIZE, NULL, TASK2_PRIO, &task2_handle); xTaskCreate((TaskFunction_t)task_3, "task_3", TASK3_SIZE, NULL, TASK3_PRIO, &task3_handle); taskEXIT_CRITICAL(); vTaskDelete(NULL); }

然后进入task1任务,识别键值,并且根据键值进行不同的操作,并别进行按键消抖和队列入队失败的打印,下方是task1的完整代码:

void task_1(void *pvParameters) { uint8_t keynum, last_key = 0; BaseType_t err; char *buf = buff; while(1) { keynum = Key_GetNum(); if (keynum != 0 && last_key == 0) { vTaskDelay(30); if (Key_GetNum() == keynum) { if (keynum == 1 || keynum == 2) { err = xQueueSend(key_queue, &keynum, 0); if (err != pdTRUE) Serial_Sendstring("queue send failed\r\n"); } else if (keynum == 3) { err = xQueueSend(big_data_queue, &buf, 0); if (err != pdTRUE) Serial_Sendstring("big_queue send failed\r\n"); } } } last_key = keynum; vTaskDelay(10); } }

task2就是将存储在key_queue的值读出来既出队,并通过串口打印出来,下方是task2的完整代码:

void task_2(void *pvParameters) { uint8_t keynum; while(1) { if (xQueueReceive(key_queue, &keynum, portMAX_DELAY) == pdTRUE) { Serial_Sendstring("Key received: "); Serial_SendNum(keynum, 1); Serial_Sendstring("\r\n"); } } }

接下来的task3就是将buff数组里的值读取出来,并通过串口打印出来,(注:这里的读取和上方的读取方式不一样,建议先去了解后再看代码比较容易理解)下方是task3的完整代码:

void task_3(void *pvParameters) { char *buf; while(1) { if (xQueueReceive(big_data_queue, &buf, portMAX_DELAY) == pdTRUE) { Serial_Sendstring("Big data: "); Serial_Sendstring(buf); Serial_Sendstring("\r\n"); } } }

之后编译运行后按按键就能实现在串口助手上显示了。

下方是FreeRTOS_Task的完整代码:

#include "stm32f10x.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "led.h" #include "key.h" #include "serial.h" /* 任务参数 */ #define START_TASK_SIZE 128 #define START_TASK_PRIO 1 #define TASK1_SIZE 256 #define TASK1_PRIO 2 #define TASK2_SIZE 256 #define TASK2_PRIO 3 #define TASK3_SIZE 256 #define TASK3_PRIO 4 TaskHandle_t start_task_handle; TaskHandle_t task1_handle; TaskHandle_t task2_handle; TaskHandle_t task3_handle; void Start_task(void *pvParameters); void task_1(void *pvParameters); void task_2(void *pvParameters); void task_3(void *pvParameters); QueueHandle_t key_queue; QueueHandle_t big_data_queue; char buff[100] = {"12354651165461032216120301654603"}; //大数据的具体内容,可随意更改,注意别超过规定的长度 void FreeRTOS_Task(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); Key_Init(); LED_Init(); Serial_Init(); key_queue = xQueueCreate(2, sizeof(uint8_t)); Serial_Sendstring(key_queue ? "key_queue create successful\r\n" : "key_queue create failed\r\n"); big_data_queue = xQueueCreate(1, sizeof(char *)); Serial_Sendstring(big_data_queue ? "big_data_queue create successful\r\n" : "big_data_queue create failed\r\n"); xTaskCreate((TaskFunction_t)Start_task, "Start_task", START_TASK_SIZE, NULL, START_TASK_PRIO, &start_task_handle); vTaskStartScheduler(); } void Start_task(void *pvParameters) { taskENTER_CRITICAL(); xTaskCreate((TaskFunction_t)task_1, "task_1", TASK1_SIZE, NULL, TASK1_PRIO, &task1_handle); xTaskCreate((TaskFunction_t)task_2, "task_2", TASK2_SIZE, NULL, TASK2_PRIO, &task2_handle); xTaskCreate((TaskFunction_t)task_3, "task_3", TASK3_SIZE, NULL, TASK3_PRIO, &task3_handle); taskEXIT_CRITICAL(); vTaskDelete(NULL); } void task_1(void *pvParameters) { uint8_t keynum, last_key = 0; BaseType_t err; char *buf = buff; while(1) { keynum = Key_GetNum(); if (keynum != 0 && last_key == 0) { vTaskDelay(30); if (Key_GetNum() == keynum) { if (keynum == 1 || keynum == 2) { err = xQueueSend(key_queue, &keynum, 0); if (err != pdTRUE) Serial_Sendstring("queue send failed\r\n"); } else if (keynum == 3) { err = xQueueSend(big_data_queue, &buf, 0); if (err != pdTRUE) Serial_Sendstring("big_queue send failed\r\n"); } } } last_key = keynum; vTaskDelay(10); } } void task_2(void *pvParameters) { uint8_t keynum; while(1) { if (xQueueReceive(key_queue, &keynum, portMAX_DELAY) == pdTRUE) { Serial_Sendstring("Key received: "); Serial_SendNum(keynum, 1); Serial_Sendstring("\r\n"); } } } void task_3(void *pvParameters) { char *buf; while(1) { if (xQueueReceive(big_data_queue, &buf, portMAX_DELAY) == pdTRUE) { Serial_Sendstring("Big data: "); Serial_Sendstring(buf); Serial_Sendstring("\r\n"); } } }

若有错误,还望海涵。