ST意法半导体
直播中

王伟

7年用户 1480经验值
私信 关注
[问答]

DMA循环缓冲区如何重置起点?

我正在尝试使用 DMA 来处理传入的 Rx 数据,理想情况下,我只想增加索引以跟踪传入的数据,基本上是这样的:
  • #define uartsize        2000
  • #define dma_buffer_interrupt_size        1
  • uint8_t                UART_in_Buffer[uartsize];
  • HAL_UART_Receive_DMA(&huart3, &UART_in_Buffer[head_index], dma_buffer_interrupt_size);
  • void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  • {
  •         head_index = (head_index + dma_buffer_interrupt_size) % uartsize;
  • }
我遇到的问题是,当我设置一个循环缓冲区时,一旦它进入 HAL_UART_RxCpltCallback(),它会将索引重置为 0。因此,如果我将 dma_buffer_interrupt_size 设置为 3,例如,它将每 3 次进入该中断例程字节,增加计数,然后如果我再发送 3 个字节,它将覆盖数组的前 3 个字节。  
我可以通过执行以下操作来解决这个问题:
  • void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  • {
  •         head_index = (head_index + dma_buffer_interrupt_size) % uartsize;
  •         HAL_UART_DMAStop(&huart3);
  •         HAL_UART_Receive_DMA(&huart3, &UART_in_Buffer[head_index], dma_buffer_interrupt_size);
  • }
这会将起点更改为头部位置,但它使用大量代码来执行此操作并排除了在普通缓冲区上执行此操作的任何优势(事实上,它可能基本上只是重新创建了普通缓冲区的功能)循环缓冲区)。
有没有办法设置一个循环缓冲区,以便它在每个字节后递增“head_index”,但不会在每次进入中断时将索引重置回 0?否则此时没有真正的方法来管理缓冲区。  
目前,我可以计算收到的字节数(但会覆盖之前的字节数),或者我可以将数据写入 DMA 缓冲区但无法跟踪传入的字节数。  







回帖(1)

曹珉

2022-12-13 11:09:37
这实际上非常完美,而且似乎大大简化了代码。我最终转向了这个:


  • #define uartsize        2000
  • uint8_t UART_in_Buffer[uartsize];

  • HAL_UART_Receive_DMA(&pc_uart, UART_in_Buffer, uartsize);

  • while (1)
  •   {
  •           head_index = (uartsize - DMA1_Stream0->NDTR) % uartsize;
  •   }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分