You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32中FreeRTOS同优先级三任务共用UART的问题解决

问题分析与解决方案

问题根源

同优先级任务采用时间片轮转调度,当第一个任务调用HAL_UART_Transmit(阻塞式,带100ms超时)时,UART进入忙状态;后续任务切换过来后,同样调用该函数时,UART未就绪,函数会在超时后返回错误(你未检查返回值,因此未察觉),导致发送失败。而不同优先级时,高优先级任务会完成整个发送流程后才让出CPU,因此所有任务都能成功发送。

以下是符合你要求的解决方案(不修改优先级、不用信号量/互斥锁、无循环等待就绪):


方案1:使用UART中断模式发送(HAL_UART_Transmit_IT)

将阻塞式发送替换为非阻塞的中断模式,任务发起发送请求后立即返回,UART通过中断完成传输,同优先级任务轮转时每个任务都能成功发起发送。

修改后的任务代码示例:

// 每个任务使用独立缓冲区,避免数据覆盖
static uint8_t t1_buf[] = "T1\r\n";
static uint8_t t2_buf[] = "T2\r\n";
static uint8_t t3_buf[] = "T3\r\n";

void StartDefaultTask(void const * argument)
{
  for(;;)
  {
    // 单次检查UART状态,仅在就绪时发起发送
    if(HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY)
    {
      HAL_UART_Transmit_IT(&huart2, t1_buf, sizeof(t1_buf)-1);
    }
    osDelay(1000);
  }
}

void StartTask02(void const * argument)
{
  for(;;)
  {
    if(HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY)
    {
      HAL_UART_Transmit_IT(&huart2, t2_buf, sizeof(t2_buf)-1);
    }
    osDelay(1000);
  }
}

void StartTask03(void const * argument)
{
  for(;;)
  {
    if(HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY)
    {
      HAL_UART_Transmit_IT(&huart2, t3_buf, sizeof(t3_buf)-1);
    }
    osDelay(1000);
  }
}

// 必须实现UART发送完成回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART2)
  {
    // 可选:发送完成后的后续处理
  }
}

注意:需确保已开启UART的TX中断(CubeMX配置时勾选或代码中手动开启)。


方案2:使用DMA模式发送(HAL_UART_Transmit_DMA)

利用DMA硬件完成UART发送,完全不占用CPU资源,任务发起发送后立即返回,效率更高。

修改示例:

static uint8_t t1_buf[] = "T1\r\n";
static uint8_t t2_buf[] = "T2\r\n";
static uint8_t t3_buf[] = "T3\r\n";

void StartDefaultTask(void const * argument)
{
  for(;;)
  {
    if(HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY)
    {
      HAL_UART_Transmit_DMA(&huart2, t1_buf, sizeof(t1_buf)-1);
    }
    osDelay(1000);
  }
}

// 另外两个任务替换对应缓冲区即可

// 可选实现DMA发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART2)
  {
    // 可选:清理或标记操作
  }
}

注意:需确保CubeMX配置了UART的DMA发送通道,或代码中手动完成DMA初始化。


方案合规性说明

  • 未修改任务优先级,保持osPriorityNormal;
  • 未使用信号量、互斥锁,仅利用HAL库的非阻塞发送机制;
  • 仅单次检查UART状态,无循环等待,符合通用单片机编程思路。

内容的提问来源于stack exchange,提问作者Nima Azad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:06:05