首页 文章

STM32F0 DMA“输入溢出”

提问于
浏览
0

我有一个问题,STM32F0 DMA从UART接收数据 . 我在非循环模式下使用2个DMA通道(对于rx和tx),rx通道的优先级较低 . 来自UART的数据处理空闲线路中断,其中我读取DMA接收字节的数量并处理它们 . 一切正常,直到包中的字节数小于或等于DMA缓冲区大小 . 否则DMA奇怪地关闭,并且在空闲线路中断后给出1,0,0,......数量的DMA接收字节 . 这是代码的一部分,我检查DMA缓冲区是否填充并尝试将DMA计数器重置为缓冲区大小:

#define S_M_INPUT_CMD_SIZE 20
static char s_m_uart_dma_in_buff[S_M_INPUT_CMD_SIZE + 1]; 

void USART1_IRQHandler(void)
{
   ITStatus reception_status = USART_GetITStatus(USART1, USART_IT_IDLE);
   if(reception_status != RESET)
   {
      int32_t bytes_number = S_M_INPUT_CMD_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);            
      if (DMA_GetFlagStatus(DMA1_FLAG_TC3) != RESET)
      {
         USART_ITConfig(UART_, USART_IT_IDLE, DISABLE);
         DMA_Cmd(DMA1_Channel3, DISABLE);
         while (DMA1_Channel3->CCR & DMA_CCR_EN);
         for (int i = 0; i < S_M_INPUT_CMD_SIZE; i++)
            s_m_uart_dma_in_buff[i] = '\0'; 
         DMA_SetCurrDataCounter(DMA1_Channel3, S_M_INPUT_CMD_SIZE); 
         DMA_Cmd(DMA1_Channel3, ENABLE); 
         DMA_ClearFlag(DMA1_FLAG_GL3);
      }
      USART_ClearITPendingBit(UART_, USART_IT_IDLE);
   } 
}

在第一次“溢出”和DMA使能之后出现在rx寄存器中的“缓冲区大小1”字节,之后接收的字节数稳定为零 . 我做错了什么?

1 回答

  • 1

    如果您尝试使用您的代码接收大小超过S_M_INPUT_CMD_SIZE的数据包,会发生什么情况:

    • DMA完成接收块S_M_INPUT_CMD_SIZE并禁用(非循环模式)

    • USART1接收一个字节

    • USART1从数据包接收另外一个字节并丢弃它们,因为没有人处理UART

    • 包完成后,你得到IDLE中断并重新启动DMA

    • DMA读取先前收到的字节

    • 没有更多的数据包 - 你得到0,0,......收到的DMA字节数

    我不得不说,这是处理DMA传输的奇怪方法 . DMA传输通常必须在DMA中断处理程序中处理,而不是外设 .

    为了处理长数据包,你必须实现DMA中断处理程序 . 因此可以比IDLE中断更早地重新启动DMA接收 . 因此DMA将准备好从UART接收更多数据 .

    还有一件事 . 在你的代码中有一场比赛 . 在您读取 bytes_number 并禁用DMA之间,可以通过DMA传输一个或多个字节 .

    但更正确的处理UART的方法是在循环模式下运行DMA并且不要重新初始化它 . 因为每次禁用DMA都会丢失一些UART输入 .

相关问题