硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1076|回复: 3
收起左侧

[技术讨论] DMA发送函数只能被调用一次

[复制链接]

23

主题

49

回帖

118

积分

初级会员

积分
118
发表于 2024-11-15 15:16:56 | 显示全部楼层 |阅读模式

逐步debug DMA发送函数,HAL_UART Transmit DMA,发现函数会对串口句柄的一个状态位,gState 进行判断,只有在 huart->gState==HAL UART STATE READY 的时候才会正常进行发送,
1.png

而第一次发送可以成功,便是因为一开始,gState为HAL_UART_STATE_READY,因此,可以成功发送,而在第一次发送时,HAL_UART_Transmit_DMA 函数会将gState 更改为HAL_UART_STATE_BUSY_TX 状态,gState 位随后一直保持为HAL_UART_STATE_BUSY_TX状态,导致后面的发送无法执行,而gState 状态想要被清除必须要进入串口中断HAL_UART_IRQHandler中的UART_EndTransmit_IT里面,在UART_EndTransmit_IT函数中清除了gState标志位。
我的问题就是串口中断只能第一次进入,后面就不进入了,所以发送失败。在调试的时候偶尔能发送和接收都正常,各位能帮忙给点建议吗?下面是我的代码:
[C] 纯文本查看 复制代码
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART3)
  {
    if (HAL_UARTEx_ReceiveToIdle_DMA(&huart3, usart3RxBuff, MAX_COM3_RXSIZES) == HAL_BUSY) // 接收发生错误后重启
    {
      __HAL_UART_CLEAR_OREFLAG(&huart3);
      huart3.RxState = HAL_UART_STATE_READY;
      huart3.Lock = HAL_UNLOCKED;
      HAL_UARTEx_ReceiveToIdle_DMA(&huart3, usart3RxBuff, MAX_COM3_RXSIZES);
    }
    initSqQueue(&uart[_COM3].Rx, usart3RxBuff, sizeof(usart3RxBuff));
    memset(usart3RxBuff, 0, MAX_COM3_RXSIZES);
    return;
  }
}

[C] 纯文本查看 复制代码
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  if (huart->Instance == USART3)
  {
    uart[_COM3].Rx.rear = Size; // 写入rear
                                // bleAppConfig.rxAct = 1;
#ifdef _UART3_DEBUG
    uartxEcho(&huart3, &uart3);
#endif
    if (uart[_COM3].rxEnd == true)
    {
      uart[_COM3].rxIdle = false;
      initUartTick(&uart[_COM3], CONST_UART_DLY_TIM);
    }
    else
    {
      uart[_COM3].rxIdle = true;
      initUartTick(&uart[_COM3], CONST_UART_DLY_TIM);
      // MAP_Interrupt_disableSleepOnIsrExit();
    }
    return;
  }
  UNUSED(huart);
}

[C] 纯文本查看 复制代码
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART3)
  {
    uart[_COM3].sBusy = false;
#ifdef MAX_COM3_TXSIZES
    memset(usart3TxBuff, 0, MAX_COM3_TXSIZES);
#endif
    return;
  }
  UNUSED(huart);
}

主程序开始调用函数HAL_UARTEx_ReceiveToIdle_DMA(&huart3, usart3RxBuff, MAX_COM3_RXSIZES); 发送调用的函数为HAL_UART_Transmit_DMA(huart, (const uint8_t *)buf, num);调试时buf和num都是正确的,发出去就没有数据。如果不使用DMA发送的话,那么接收的时候就会进入HAL_UART_ErrorCallback错误回调。

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116223
QQ
发表于 2024-11-16 10:53:32 | 显示全部楼层
有个关键的地方,楼主的描述里面没看到,调用完毕HAL_UART_Transmit_DMA(huart, (const uint8_t *)buf, num);后,有等待HAL_UART_TxCpltCallback里面的执行完毕标志后,再次调用HAL_UART_Transmit_DMA没
回复

使用道具 举报

23

主题

49

回帖

118

积分

初级会员

积分
118
 楼主| 发表于 2024-11-18 08:34:27 | 显示全部楼层
eric2013 发表于 2024-11-16 10:53
有个关键的地方,楼主的描述里面没看到,调用完毕HAL_UART_Transmit_DMA(huart, (const uint8_t *)buf, num ...

它如果能进HAL_UART_TxCpltCallback不是说明就已经发送完成了吗?如果不是的话,那应该在哪里判断呢?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116223
QQ
发表于 2024-11-19 09:50:53 | 显示全部楼层
zhouyalong 发表于 2024-11-18 08:34
它如果能进HAL_UART_TxCpltCallback不是说明就已经发送完成了吗?如果不是的话,那应该在哪里判断呢?

还可以看DMA的NDTR计数器,看看变化没,没有变化说明DMA没有执行。也就是程序配置有问题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-6-10 13:34 , Processed in 0.284093 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表