main入口
int main(void)
{
// 硬件初始化 。。。
user_main();
while (1)
{
}
下面这段代码是一个使用FreeRTOS实现的简单示例,目的是演示多个任务如何使用队列进行UART(通用异步接收/发送器)发送
通信机制
这个示例的核心是通过队列在不同任务之间安全地传递数据。在该示例中,队列充当了生产者(vTask1和vTask2)和消费者(vTaskUartSend)之间的缓冲区。
#include "user_main.h"
#include <stdbool.h>
#include <string.h>
#include "arm_math.h"
#include "main.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
// UART发送缓冲队列
QueueHandle_t xUARTSendQueue;
void vTask1(void *argument);
void vTask2(void *argument);
void vTaskUartSend(void *argument);
void user_main(void)
{
// 创建队列
xUARTSendQueue = xQueueCreate(50, sizeof(char));
// 创建任务
xTaskCreate(vTask1, "vTask1", 128, NULL, 1, NULL);
xTaskCreate(vTask2, "vTask2", 128, NULL, 1, NULL);
// 创建UART发送任务
xTaskCreate(vTaskUartSend, "vTaskUartSend", 128, NULL, 2, NULL);
// 启动调度
vTaskStartScheduler();
Error_Handler();
}
任务vTask1
和vTask2
这两个任务作用相同,它们每500毫秒发送一个字符串到UART发送队列。在发送字符串之前,它们通过调用taskENTER_CRITICAL
和taskEXIT_CRITICAL
进入和退出临界区,字符串的每个字符都逐个加入到xUARTSendQueue队列中,以保证字符串作为一个整体被放入队列,避免被另一个任务打断。
void vTask1(void *argument)
{
(void)argument;
const char *txt = "vTask1\n";
while (1)
{
// 进入临界区
taskENTER_CRITICAL();
//将字符串每个字符一次传入到队列中
for(int i = 0; i < strlen(txt); i++) {
xQueueSend(xUARTSendQueue, &txt[i], NULL);
}
// 退出临界
taskEXIT_CRITICAL();
vTaskDelay(500);
}
}
void vTask2(void *argument)
{
(void)argument;
const char *txt = "vTask2\n";
while (1)
{
taskENTER_CRITICAL();
for(int i = 0; i < strlen(txt); i++) {
xQueueSend(xUARTSendQueue, &txt[i], NULL);
}
taskEXIT_CRITICAL();
vTaskDelay(500);
}
}
UART发送任务vTaskUartSend
这个任务的作用是从xUARTSendQueue队列中持续读取字符,并通过HAL_UART_Transmit函数将它们发送出去。任务使用xQueueReceive从队列中接收字符,如果队列为空,该任务会阻塞直到队列中有数据可读。portMAX_DELAY参数确保了在队列为空时,任务会无限期等待直到有数据可用。
void vTaskUartSend(void *argument)
{
(void)argument;
char c;
while (1)
{
// 从队列中依次读取字符,并打印。
xQueueReceive(xUARTSendQueue, &c, portMAX_DELAY);
HAL_UART_Transmit(&huart1, (uint8_t *)&c, 1, 10);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。