当我在 STM32F407VET 中使用 UART 中断方法时,我丢失了一些字符

I'm missing some characters when I'm using UART interrupt method in STM32F407VET

我在中断模式下使用STM32F407VE的UART1。波特率为 115200。 我正在使用 docklight serial window 来读取 UART 输出。我一次发送 15 到 20 个字符。 当我检查环回代码时,我缺少字符,如下所示。

我尝试更改波特率。但是当我增加字符数时,同样的问题仍然存在。 这是我的中断处理程序:

void USART1_IRQHandler(void) {
  uint8_t data;

  HAL_UART_IRQHandler(&huart1);
  __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);

  data = (uint8_t)(huart1.Instance->DR); //& (uint16_t)0x00FFU);

  HAL_UART_Transmit(&huart1, (uint8_t *)&data, 1, 10);
}

您正在接收一个字节并将该字节放入 UART 的 TDR 寄存器中。它可能是 运行 相同的波特率,因此在传输完成之前收到一个新的接收中断。对 HAL_UART_Transmit 的调用正在阻塞,将检查传输是否为 运行。语句 if(huart->gState == HAL_UART_STATE_READY) 将 return false 因此将采用 else 路径。这将导致 return 值为 HAL_BUSY。这表明没有发生转移,因为转移仍在进行中。

您需要添加一个循环缓冲区来解决这个问题。将接收到的字节存储在中断处理程序中的存储容器中,程序的另一部分需要检查存储容器是否不为空,如果不为空则传输内容。更新存储容器时需要禁用中断,因为可能会出现竞争条件。

您还可以在传输中添加传输结束字符,表明可以安全地将其回显给您,从而避免出现竞争情况。如果您使用 ASCII,0x04 是一个很好的选择,因为它被定义为 EOT(传输结束)。

另一种选择是使用 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) 在中断模式下接收一定数量的字节。

UART 的库代码可以在里面找到:stm32f4xx_hal_uart.c。 STM 的 HAL 具有很好的可读性和信息性,请随意查看。它可以帮助将来找到其他错误。 (ST 并不总是在他们的代码中做出明显或合作的选择)

实际上这里几乎什么都错了。不要以这种方式清除 RXNE 标志。当uC从数据寄存器中读取数据时,由硬件清零。不要在中断处理程序中使用阻塞函数。

如果您使用 HAL,请使用回调函数。

我的建议是先阅读 uC 文档和 HAL 手册,然后再开始编程。

此外,您可能超出了 USART。要确认,请以 9600 波特尝试,如果丢失的字符较少,那就是你的问题。在这种情况下,您需要使用 HW 握手,或者添加缓冲区并且不要在 IRQ 处理程序中进行传输,而是在主循环中进行传输。