STM32 DMA第一次接收UART数据顺序错误

问题描述 投票:0回答:1

我有一个使用 STM32L010F4 的项目,它通过 UART 接收六个字节的数据。收到后,它应该将 ACK 发送到不同的设备。 RX 数据有一个已知的 SOF 和 EOF 字节。我正在使用 DMA 接收数据。重新启动项目后,我第一次获取数据的顺序是正确的:第一个字节是 SOF,然后是四个字节的数据,然后是 EOF 字节。然而,随后的接收首先是 EOF 字节,然后是 SOF 字节,然后是四个数据字节。我正在清除读取之间的 RX 缓冲区,所以我不认为这可能是剩余数据的情况。

/* Private user code -------------------------------------------*/
uint8_t RX_Data[6] = {0};
uint8_t ACK_Data[3] = {0x01, 0x30, 0x0D};
uint8_t RX_Data_Rdy = 0;
uint8_t TX_Data_Pending = 0;

/**
   * @brief  The application entry point.
   * @retval int
*/
int main(void)
{
   /* MCU Configuration-----------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_LPUART1_UART_Init();

  /* Infinite loop */
  while (1)
  {
      if(RX_Data_Rdy != 1)
      {
          uint8_t Result = HAL_UART_Receive_DMA (&huart2, RX_Data, 6);
      }

      if(TX_Data_Pending)
      {
          HAL_UART_Transmit_DMA(&hlpuart1, ACK_Data, 3);
      }
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
     RX_Data_Rdy = 1;
    TX_Data_Pending = 1;
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    TX_Data_Pending = 0;
    RX_Data_Rdy = 0;
    memset(RX_Data, 0, 6);
}
stm32 uart dma
1个回答
0
投票

您的代码已损坏,因为它实际上只有两种状态:接收,在这种情况下,您在循环中重复调用

HAL_UART_Receive_DMA()
,以及传输,在这种情况下,您在循环中重复调用
HAL_UART_Transmit_DMA()

到目前为止,最简单的解决方案是忘记 DMA 和中断,只使用常规轮询例程,例如:

while (1)
{
    HAL_StatusTypeDef result;

    result = HAL_UART_Receive(&huart2, RX_Data, 6, 1000); // 1000ms timeout
    if (result != HAL_OK)
    {
        // Handle error or timeout
    }

    result = HAL_UART_Transmit(&hlpuart1, ACK_Data, 3, 1000);
    if (result != HAL_OK)
    {
        // Handle error or timeout
    }
}

如果你绝对确定你必须使用DMA和中断,你真的需要两个以上的状态来告诉你你当前在做什么。它可能是这样的:

enum state_e {
    STATE_READY_TO_RECEIVE,
    STATE_RECEIVING,
    STATE_READY_TO_SEND,
    STATE_SENDING
};

volatile enum state_e state = STATE_READY_TO_RECEIVE;

int main(void)
{
    // Other initialisation stuff here

    while (1)
    {
        HAL_StatusTypedef result;

        switch(state)
        {
        case STATE_READY_TO_RECEIVE:
            result = HAL_UART_Receive_DMA (&huart2, RX_Data, 6);
            // check result for errors
            state = STATE_RECEIVING;
            break;

        case STATE_READY_TO_SEND:
            result = HAL_UART_Transmit_DMA(&hlpuart1, ACK_Data, 3);
            // check result for errors
            state = STATE_SENDING;
            break;

        case STATE_RECEIVING:
        case STATE_SENDING:
            // Nothing to do, waiting for the hardware
            break;

        default:
            // handle bad state error
            break;
        }
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (state == STATE_RECEIVING)
    {
        state = STATE_READY_TO_SEND;
    }
    else
    {
        // error - state machine broken
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if (state == STATE_SENDING)
    {
        state = STATE_READY_TO_RECEIVE;
    }
    else
    {
        // error - state machine broken
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.