本篇讲述串口接收数据,通过消息队列发送和任务接收消息队列。
一.代码准备
1.串口初始化,主要用来打印串口日志和接收串口数据
// Initialize serial communication at 115200 bits per second:
Serial.begin(115200);
while (!Serial) {
delay(10);
}
Serial.println("Uart Init");
Serial.println();
2.创建消息队列
// Create the queue which will have <QueueElementSize> number of elements, each of size `message_t` and pass the address to <QueueHandle>.
QueueHandle = xQueueCreate(QueueElementSize, sizeof(message_t));
// Check if the queue was successfully created
if (QueueHandle == NULL) {
Serial.println("Queue could not be created. Halt.");
while (1) {
delay(1000); // Halt at this point as is not possible to continue
}
}
Serial.println("Create Queue OK");
Serial.println();
3.创建串口接收及发送消息队列任务
//任务检查串口接收,有数据就消息队列发送出去
void TaskReadFromSerial(void *pvParameters) { // This is a task.
message_t message;
for (;;) {
// Check if any data are waiting in the Serial buffer
message.line_length = Serial.available();
if (message.line_length > 0) {
// Check if the queue exists AND if there is any free space in the queue
if (QueueHandle != NULL && uxQueueSpacesAvailable(QueueHandle) > 0) {
int max_length = message.line_length < MAX_LINE_LENGTH ? message.line_length : MAX_LINE_LENGTH - 1;
for (int i = 0; i < max_length; ++i) {
message.line[i] = Serial.read();
}
message.line_length = max_length;
message.line[message.line_length] = 0; // Add the terminating nul char
Serial.println("Receive UART data,and go to send message queue");
Serial.println();
// The line needs to be passed as pointer to void.
// The last parameter states how many milliseconds should wait (keep trying to send) if is not possible to send right away.
// When the wait parameter is 0 it will not wait and if the send is not possible the function will return errQUEUE_FULL
int ret = xQueueSend(QueueHandle, (void *)&message, 0);
if (ret == pdTRUE) {
// The message was successfully sent.
Serial.println("The message was successfully sent");
} else if (ret == errQUEUE_FULL) {
// Since we are checking uxQueueSpacesAvailable this should not occur, however if more than one task should
// write into the same queue it can fill-up between the test and actual send attempt
Serial.println("The `TaskReadFromSerial` was unable to send data into the Queue");
} // Queue send check
} // Queue sanity check
} else {
delay(100); // Allow other tasks to run when there is nothing to read
} // Serial buffer check
} // Infinite loop
}
{
xTaskCreate(
TaskReadFromSerial, "Task Read From Serial", 2048 // Stack size
,
NULL // No parameter is used
,
1 // Priority
,
NULL // Task handle is not used here
);
Serial.println("Create TaskReadFromSerial Task");
Serial.println();
}
4.创建消息队列接收任务
//消息队接收任务
void TaskWriteToSerial(void *pvParameters) { // This is a task.
message_t message;
for (;;) { // A Task shall never return or exit.
// One approach would be to poll the function (uxQueueMessagesWaiting(QueueHandle) and call delay if nothing is waiting.
// The other approach is to use infinite time to wait defined by constant `portMAX_DELAY`:
if (QueueHandle != NULL) { // Sanity check just to make sure the queue actually exists
int ret = xQueueReceive(QueueHandle, &message, portMAX_DELAY);
if (ret == pdPASS) {
// The message was successfully received - send it back to Serial port and "Echo: "
Serial.printf("The message was successfully received\"\n");
Serial.printf("Echo line of size %d: \"%s\"\n", message.line_length, message.line);
// The item is queued by copy, not by reference, so lets free the buffer after use.
} else if (ret == pdFALSE) {
Serial.println("The `TaskWriteToSerial` was unable to receive data from the Queue");
}
} // Sanity check
} // Infinite loop
}
{
// Set up two tasks to run independently.
xTaskCreate(
TaskWriteToSerial, "Task Write To Serial" // A name just for humans
,
2048 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);`
,
NULL // No parameter is used
,
2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
,
NULL // Task handle is not used here
);
Serial.println("Create TaskWriteToSerial Task");
Serial.println();}
二.编译烧录测验
编译烧录后可看到初始化情况,在串口发送数据,可看到串口接收并将数据消息队列发送出去,任务接收到消息队列并打印出来,实现了消息队列的成功收发。
图1:任务与消息队列发送与接收
由此,Beetle ESP32 C6可用FreeRTOS实现系统功能。