// flush the UART, otherwise the DMA won't start with data coming in
RMA_USART->CR1 &= ~USART_CR1_RE; // disable UART rx
while (USART1->ISR & USART_ISR_RXNE_RXFNE) {
u8 h = USART1->RDR; // flush the FIFO
UNUSED(h);
}
USART1->CR1 |= USART_CR1_RE; // reenable UART rx
// now race to setup the UART with DMA (as usual)
UART_Start_Receive_DMA(&huart1, (u8 *)my_rx.buf, sizeof(my_rx.buf));
// stop errors from aborting the DMA (can't do this in Cube)
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_TC);
3条答案
按热度按时间bogh5gae1#
经过长时间的调试,我终于找到了原因和解决方案。当第一个字节到达UART外设时,由于时钟不匹配,它触发帧错误,然后停止DMA。当UART数据速率非常高时,这种情况会发生得更频繁。但是我添加了ErrorCallback函数来处理中断。不幸的是,我误用了这个功能。
我的用途:
HAL_UART_MspDeInit未清除结构和初始化,因此Receive_DMA函数无法再次启动。我的沟通停止了。
正确用途:
由于我的代码中的三个错别字,它给我带来了很多时间。但最后,它解决了。
cu6pst1q2#
UART和DMA外设通常有一个错误检测器,因此将其标志写入状态寄存器。当发生错误时,STM32 HAL将停止任何正在进行的传输,并等待您处理此故障。您可以使用调试模块检查HAL状态寄存器以解决问题,并在代码中添加处理方法。首先,您可以通过运行DeInit()来重置外围设备,并在运行外围设备的Init()例程错误后立即重置任何其他代码e。例如,状态机和使用来自该外围设备的数据的东西。
tjrkku2a3#
根据我的经验,问题的根源是HAL,它通过禁用DMA来对任何错误做出React。由于我使用循环DMA,这不是处理错误的可行方法。正如您所发现的,在初始化时,数据流(以速度)也肯定会发生错误。以下是我的解决方案,增加了通常的
UART_Start_Receive_DMA()
init代码:运行此代码时请禁用中断。
一个更好的解决方案是用更接近金属的东西代替HAL代码。我没有尝试过这个,但libopencm3似乎是值得的。
还要注意,DMA通道3不能用于至少某些STM32上的UART RX。