FREERTOS多任务访问同一个UART的方法

简介

    在RTOS多任务编程的时候,同一个硬件(比如UART、I2C等)被多个任务访问的情况比较多,如果不合理处理,就会导致“混乱”的局面。
    处理“混乱”局面的方法比较多,下面基于FreeRTOS,以UART为例讲讲常见的互斥、队列这两种方法

一、互斥访问方法

互斥量:是一个可以处于两态之一的变量:解锁和加锁。
原理:创建一个互斥量,任务A在需要占用资源(使用UART发送数据),把资源(UART)占用。此时,任务B及其他任务就不能占用该资源。当任务A使用完资源(UART发送完数据),释放资源,其他任务就可以抢占该资源。

创建互斥量

任务A占用资源

使用资源(发送数据)

任务A释放资源

优先级高的任务B占用资源

使用资源

任务B释放资源

依次,优先级任务占用资源

代码:

//创建互斥量资源
SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateMutex();
 
 
void TaskA(void *pvParameters)
{
  for(;;)
  {
    //占用资源
    if(xSemaphoreTake(xSemaphore, 10 ) == pdTRUE)
    {
      //使用资源(发送数据)
      USART_SendNByte();
      //释放资源
      xSemaphoreGive(xSemaphore);
    }
  }
}

信号量与互斥量区别 (划重点):

信号量:多个任务同步使用某个资源;
一个任务完成某个动作后通过信号告诉别的任务,别的任务才可以执行某些动作;

互斥量:多任务互斥使用某个资源;
一个任务占用某个资源,那么别的任务就无法访问,直到该任务离开,其他任务才可以访问该资源;

二、队列操作方法

    队列操作方法就是FIFO,先入先出的原理。比如:任务A要使用UART发送一串数据,将其加入队列; 接着任务B也要使用UART发送一串数据。
    那么,任务A将这串数据加入队列,接着任务B又将要发送的一串数据加入队列。
    在另外一个UART发送的任务中,从队列中按照FIFO方式读取队列里面的数据,依次发送出去即可。

创建一个队列(发送数据队列)

创建一个任务(UART发送数据任务)

任务A加入队列

任务B加入队列

·

·

·

另外一边的任务,依次读取队列数据,使用UART发送出去。

代码:

QueueHandle_t xQueue;
xQueue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE);
 
 
xTaskCreate(UART_Send_Task, "UART_Send", STACK_SIZE, NULL, TASK_PRIORITY, NULL);
 
 
void TaskA(void *pvParameters)
{
  for(;;)
  {
    //任务相关操作
 
 
    //加入队列
    xQueueSend(xQueue, &TaskA_Buf, 10)
  }
}
 
 
void TaskB(void *pvParameters)
{
  for(;;)
  {
    //任务相关操作
 
 
    //加入队列
    xQueueSend(xQueue, &TaskB_Buf, 10)
  }
}
 
 
void UART_Send_Task(void *pvParameters)
{
  for(;;)
  {
    //循环读取队列BUF
    if(xQueueReceive(xQueue, &Buf, 10) == pdTRUE)
    {
      USART_SendNByte(&Buf);
    }
  }
}

总结

以上两种方法比较常用,也比较简单,希望对大家有帮助。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS是一个开源的实时操作系统,在FreeRTOS中使用UART进行串口读写需要使用FreeRTOS提供的API来实现,而不是直接使用UART.h库。 首先需要在FreeRTOS中创建一个任务,并在任务中使用FreeRTOS提供的API进行串口的读写操作。以下是一个使用STM32CubeMX和HAL库来配置串口的示例代码: ```c #include "FreeRTOS.h" #include "task.h" #include "stm32f4xx_hal.h" #include "usart.h" void vUARTTask(void *pvParameters) { uint8_t buffer[64]; // 缓冲区 HAL_StatusTypeDef status; // 状态变量 while (1) { // 读取串口数据 status = HAL_UART_Receive(&huart1, buffer, sizeof(buffer), portMAX_DELAY); if (status != HAL_OK) { // 处理错误 } // 处理数据 // ... // 发送串口数据 status = HAL_UART_Transmit(&huart1, buffer, sizeof(buffer), portMAX_DELAY); if (status != HAL_OK) { // 处理错误 } } } int main(void) { // 初始化FreeRTOS BaseType_t status = xTaskCreate(vUARTTask, "UART Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); if (status != pdPASS) { // 处理错误 } vTaskStartScheduler(); while (1) { // 不会运行到这里 } return 0; } ``` 在以上示例代码中,`vUARTTask()`函数是一个任务,在任务中使用`HAL_UART_Receive()`函数接收串口数据,使用`HAL_UART_Transmit()`函数发送串口数据。`portMAX_DELAY`参数表示在没有数据或空间可用之前,任务将一直阻塞。 需要注意的是,在使用FreeRTOS进行串口读写操作时,由于涉及到多任务并发访问的问题,需要考虑数据同步和互斥。可以使用FreeRTOS提供的互斥锁和信号量等机制来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值