简介
队列是一种数据结构,可以包含一组固定大小的数据。在创建队列的同时,队列的长度和所包含数据类型的大小就确认下来了。一个队列可以有多个写入数据的任务和多个读取数据的任务。当一个任务试图从队列读取数据的时候,它可以设置一个阻塞时间(block time)。这是当队列数据为空时,任务会进入阻塞状态的时间。当有数据在队列或者到达阻塞时间的时候,任务都会进入就绪状态。如果有多个任务同时在阻塞状态等待队列数据,优先级高的任务会在数据到达时进入就绪状态;在优先级相同的时候,等待时间长的任务会进入就绪状态。同理可以推及多个任务写入数据时候的运行状态。
API:
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,UBaseType_t uxItemSize );
BaseType_t xQueueSend(
QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait );
BaseType_t xQueueReceive(
QueueHandle_t xQueue,
void *pvBuffer,
TickType_t xTicksToWait
);
程序实现
首先,在setup()函数内,创建三个向队列传输数据的任务,创建一个从队列读取数据的任务。
void setup()
{
Serial.begin(115200);
xTaskCreate(userA, "User A", 1024 * 8, NULL, 1, NULL);
xTaskCreate(userB, "User B", 1024 * 8, NULL, 1, NULL);
xTaskCreate(userC, "User C", 1024 * 8, NULL, 1, NULL);
xTaskCreate(lcdTask, "lcd", 1024 * 8, NULL, 1, NULL);
}
void loop() {}
将LCD初始化,创建消息队列
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(char[20]));
创建随机显示字母的函数
String randomMsg() {
String myStrings[] = {
"Nice to meet you",
"Where are U from?",
"What do you do?",
"What do U like?",
"What is UR num?",
"Do U have FB?",
"Thanks so much.",
"I am Chinese.",
"I do not KNOW.",
"Thank you.",
"That helps.",
"I Love U",
"Do U miss me?",
"Be careful.",
"Don't worry.",
"Good idea.",
"He's right.",
"I ate already.",
"More than that.",
"Nothing else.",
"See you later.",
"Take it outside.",
};
return myStrings[random(0, 22)];
}
定义三个向队列传送消息的函数
void userA(void *ptParam) {
char msg[20];
String userID = "A: ";
while (1) {
(userID + randomMsg()).toCharArray(msg, 20);
TickType_t timeOut = portMAX_DELAY;
//TickType_t timeOut = 10;
if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {
Serial.print(userID);
Serial.println("Queue is full.");
};
vTaskDelay(2000);
}
}
void userB(void *ptParam) {
char msg[20];
String userID = "B: ";
while (1) {
(userID + randomMsg()).toCharArray(msg, 20);
//portMAX_DELAY - 无限Block
TickType_t timeOut = portMAX_DELAY;
//TickType_t timeOut = 10;
if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {
Serial.print(userID);
Serial.println("Queue is full.");
};
vTaskDelay(2000);
}
}
void userC(void *ptParam) {
char msg[20];
String userID = "C: ";
while (1) {
(userID + randomMsg()).toCharArray(msg, 20);
//portMAX_DELAY - 无限Block
TickType_t timeOut = portMAX_DELAY;
//TickType_t timeOut = 10;
if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {
Serial.print(userID);
Serial.println("Queue is full.");
};
vTaskDelay(2000);
}
}
定义LCD显示函数
void lcdTask(void *ptParam) { //LCD任务主体
lcd.init();
lcd.backlight();
char line0[20] = {' '};
char line1[20] = {' '};
char line2[20] = {' '};
char line3[20] = {' '};
char * lines[] = { line0, line1, line2, line3 };
while (1) {
//文字向上滚动
strcpy(line0, line1);
strcpy(line1, line2);
strcpy(line2, line3);
//TickType_t timeOut = portMAX_DELAY;
TickType_t timeOut = 10;
if (xQueueReceive(queueMsg, lines[3], timeOut) == pdPASS) {
//显示所有的4行文字
for (int i = 3; i >= 0; i--) {
lcd.setCursor(0, i);
lcd.print(" "); //clear this line
lcd.setCursor(0, i);
lcd.print(lines[i]);
}
} else {
Serial.println("Message Queue is Empty");
};
vTaskDelay(10);
}
}