为啥dma只接收最后一个字符

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥dma只接收最后一个字符相关的知识,希望对你有一定的参考价值。

通常采用DMA做USART接收固定长度的数据,或通过DMA完成固定数量的不间断数据流。不固定长度数据接收需要起始符和结尾符,这样就需要在每一次RX的中断后做字符检测(可参考MODBUS-ASCii),或采用接收最后一个字符后停顿超过预定时间来检测数据完结,同样需要RX中断(可参考MODBUS-RTU)。这跟用DMA减少中断开销的原意违背。

如真想用DMA,可以试试这方法,前提是主循环没有太多对实时性影响的工作:
不采用DMA完成中断,在主循环里polling当前DMA的计数器得知最新一个数据在Buffer的位置,然后检测结尾符,if收到结尾符后对buffer所有数据做处理。
细节你可以自行分析一下,看看跟你原程序有没有矛盾。
参考技术A

因为cubeMX/CubeIDE生成的代码顺序导致了bug.

以下是cube自动生成的初始化代码:

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  /* USER CODE BEGIN 2 */

但是这样会导致DMA出问题. 需要将DMA的初始化放到UART初始化的前面:

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();//交换顺序
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

然后就正常了.

并记住,每次重新生成代码后都要手动更改顺序

为啥 UART w/DMA 只接收发送数据的最后一个字节?

【中文标题】为啥 UART w/DMA 只接收发送数据的最后一个字节?【英文标题】:Why is UART w/DMA only receiving last byte of sended data?为什么 UART w/DMA 只接收发送数据的最后一个字节? 【发布时间】:2021-10-24 16:39:36 【问题描述】:

这是应该继续接收字节的UARTEx_RxEventCallback() 函数。在这里您可以在 Hercules 屏幕中看到,我发送了123456789,但它只接收到最后一个字节。为什么会这样。我的 DMA 设置设置为正常(不是循环)、外设到内存、字节。 NVIC 中断复选框已启用。一切都设置好了。

这是我的主要任务。

【问题讨论】:

请将您的代码发布为文本而不是图像。见meta.***.com/a/285557/413337 在第一张图片中,代码无关紧要。您必须查看屏幕截图的右侧。这是我问题的重要部分。这里实际上没有与代码相关的问题! 【参考方案1】:

由于初始化顺序,您的 DMA 无法正常工作,您必须在 UART/USART 之前初始化 DMA,如下所示:

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART3_UART_Init();

【讨论】:

【参考方案2】:

看起来你没有增加内存地址,所以数据总是复制到数组的第一个元素。 hdma_usart3_rx.Init.MemInc 应该是 DMA_MINC_ENABLE

【讨论】:

请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。 我确实增加了内存地址:hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;

以上是关于为啥dma只接收最后一个字符的主要内容,如果未能解决你的问题,请参考以下文章

我在用STM32串口DMA接收数据时,为啥在接收过程中,我的程序停止运行了,接收完成后又开始运行,求解?

STM32HAL库DMA和串口接收不定长字符串

STM32HAL库DMA和串口接收不定长字符串

STM32中串口DMA实验里,为啥选择通道4(选择串口的发送端,而不是接收端)?

STM32F4 HAL SPI_Receive dma 只接收一次

STM32F4 DMA接收串口定长数据,串口每秒来1000个数据,使用DMA-Normal模式