stm32f743VIT6 + DMA空闲方式接收不定长度的字节

2019-07-20 01:46发布

最近使用stm32f743VIT6 DMA通过空闲中断接收不定长度的字节。有个现象很奇怪,我接收GPS下发的数据的时候,使用的串口2的DMA的空闲中断来接收,(一般情况下GPS发出来的数据都是每秒钟一帧,美帧数据大约几百个字节),要么接收到1个字节就空闲中断了,要么就根本接收不到。
然后我换成用PC机模拟GPS通过USB转TTL 的线下发数据到串口2,这个时候能完整无误的接收到数据,无论下发的数据字节有多少都能 完整无误的接收到。  我把我的串口的配置和中断处理贴出来,希望有知道原因的大牛指点指点。谢谢

       说明一下, 以上我做实验都是通过串口2接收的数据,然后用串口3转发接收的数据到PC机上来观察的。

  以下是   串口1 和串口2和串口3 的初始化配置:


   void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
  static DMA_HandleTypeDef U1hdma_tx;
  static DMA_HandleTypeDef U1hdma_rx;
   
    static DMA_HandleTypeDef U2hdma_tx;
  static DMA_HandleTypeDef U2hdma_rx;
   
   
    static DMA_HandleTypeDef U3hdma_tx;
  static DMA_HandleTypeDef U3hdma_rx;

  GPIO_InitTypeDef  GPIO_InitStruct;

  RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;

       if(huart->Instance==USART1)
                {        
                USARTx_TX_GPIO_CLK_ENABLE();
            
                RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART16;
                RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
                HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

                USARTx_CLK_ENABLE();

                DMAx_CLK_ENABLE();

                GPIO_InitStruct.Pin       = USARTx_TX_PIN;
                GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Pull      = GPIO_PULLUP;
                GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
                GPIO_InitStruct.Alternate = USARTx_TX_AF;

                HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

                GPIO_InitStruct.Pin = USARTx_RX_PIN;
                GPIO_InitStruct.Alternate = USARTx_RX_AF;

                HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
            
                U1hdma_tx.Instance                 = USARTx_TX_DMA_STREAM;
                U1hdma_tx.Init.Request             = USARTx_TX_DMA_CHANNEL;
                U1hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
                U1hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
                U1hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
                U1hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
                U1hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
                U1hdma_tx.Init.Mode                = DMA_NORMAL;
                U1hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
                U1hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
                U1hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
                U1hdma_tx.Init.MemBurst            = DMA_MBURST_INC4;
                U1hdma_tx.Init.PeriphBurst         = DMA_PBURST_INC4;

                HAL_DMA_Init(&U1hdma_tx);
            
                __HAL_LINKDMA(huart, hdmatx, U1hdma_tx);

                HAL_NVIC_SetPriority(USARTx_DMA_TX_IRQn, 3, 1);
                HAL_NVIC_EnableIRQ(USARTx_DMA_TX_IRQn);

                HAL_NVIC_SetPriority(USARTx_IRQn, 3, 1);
                HAL_NVIC_EnableIRQ(USARTx_IRQn);   
            }
       if(huart->Instance==USART2)
             {   
               UsartG_RX_GPIO_CLK_ENABLE();

                RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
                RCC_PeriphClkInit.Usart234578ClockSelection = RCC_USART2CLKSOURCE_D2PCLK1;
                HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

                 __HAL_RCC_USART2_CLK_ENABLE();

                 __HAL_RCC_DMA1_CLK_ENABLE();

                GPIO_InitStruct.Pin       = UsartG_TX_PIN;
                GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Pull      = GPIO_PULLUP;
                GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
                GPIO_InitStruct.Alternate = UsartG_TX_AF;
                HAL_GPIO_Init(UsartG_TX_GPIO_PORT, &GPIO_InitStruct);
               
                GPIO_InitStruct.Pin = UsartG_RX_PIN;
                GPIO_InitStruct.Alternate = UsartG_RX_AF;
                HAL_GPIO_Init(UsartG_RX_GPIO_PORT, &GPIO_InitStruct);

              U2hdma_rx.Instance                 = UsartG_RX_DMA_STREAM;
              U2hdma_rx.Init.Request             = UsartG_RX_DMA_CHANNEL;
              U2hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
              U2hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
              U2hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;
              U2hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
              U2hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
              U2hdma_rx.Init.Mode                = DMA_NORMAL;
              U2hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;
              U2hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
              U2hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
              U2hdma_rx.Init.MemBurst            = DMA_MBURST_INC4;
              U2hdma_rx.Init.PeriphBurst         = DMA_PBURST_INC4;

              HAL_DMA_Init(&U2hdma_rx);
               
              __HAL_LINKDMA(huart, hdmarx, U2hdma_rx);

                HAL_NVIC_SetPriority(UsartG_DMA_RX_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(UsartG_DMA_RX_IRQn);

                HAL_NVIC_SetPriority(UsartG_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(UsartG_IRQn);
             }
            
        if(huart->Instance==USART3)
            {   
                UsartX_TX_GPIO_CLK_ENABLE();

                RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3;
                RCC_PeriphClkInit.Usart234578ClockSelection = RCC_USART3CLKSOURCE_D2PCLK1;
                HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

                UsartX_CLK_ENABLE();
   
                DMAX_CLK_ENABLE();
   
                GPIO_InitStruct.Pin       = UsartX_TX_PIN;
                GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Pull      = GPIO_PULLUP;
                GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
                GPIO_InitStruct.Alternate = UsartX_TX_AF;

                HAL_GPIO_Init(UsartX_TX_GPIO_PORT, &GPIO_InitStruct);

   
     
                U3hdma_tx.Instance                 = UsartX_TX_DMA_STREAM;
                U3hdma_tx.Init.Request             = UsartX_TX_DMA_CHANNEL;
                U3hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
                U3hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
                U3hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
                U3hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
                U3hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
                U3hdma_tx.Init.Mode                = DMA_NORMAL;
                U3hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
                U3hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
                U3hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
                U3hdma_tx.Init.MemBurst            = DMA_MBURST_INC4;
                U3hdma_tx.Init.PeriphBurst         = DMA_PBURST_INC4;

                HAL_DMA_Init(&U3hdma_tx);
            
                __HAL_LINKDMA(huart, hdmatx, U3hdma_tx);
               
              HAL_NVIC_SetPriority(UsartX_DMA_TX_IRQn, 1, 1);
              HAL_NVIC_EnableIRQ(UsartX_DMA_TX_IRQn);

                HAL_NVIC_SetPriority(UsartX_IRQn, 1, 1);
                HAL_NVIC_EnableIRQ(UsartX_IRQn);   
        }        
}


       以下是串口2的中断处理:
注:  GPS_UartHandle  是处理处理GPS 接收数据的一个Handle ,也就是串口2


void Usart2_IRQHandler(void)
{
  uint32_t tmp_flag = 0;
  uint32_t temp;
  //HAL_UART_IRQHandler(&GPS_UartHandle);
  tmp_flag = __HAL_UART_GET_FLAG(&GPS_UartHandle,UART_FLAG_IDLE);                  // 这里是获取空闲标志
    if((tmp_flag ==SET))                                                            
  {               
         __HAL_UART_CLEAR_IDLEFLAG(&GPS_UartHandle);                                            // 清除空闲标志      
          temp=__HAL_DMA_GET_COUNTER(GPS_UartHandle.hdmarx);                          // 获取接收缓存的剩余字节数
          HAL_UART_DMAStop(&GPS_UartHandle);                                                            /// 停止 串口2的DMA接收
          rx_len = (RXBUFFERSIZE - temp);                                                                       // 计算 接收到的数据长度   
         recv_end_flag = 1;                                                                                              // 置位接收完成标志,在main中提示处理接收到的数据
          temp =0;                  
  }
    __HAL_UART_CLEAR_IT(&GPS_UartHandle,UART_CLEAR_PEF                                //  清除 其他的中断标志 等
                                     |UART_CLEAR_FEF
                                     |UART_CLEAR_NEF
                                     |UART_CLEAR_OREF
                                   //|UART_CLEAR_IDLEF
                                      |UART_CLEAR_TCF
                                      |UART_CLEAR_LBDF
                                      |UART_CLEAR_CTSF
                                      |UART_CLEAR_RTOF
                                      |UART_CLEAR_WUF
                                      |UART_CLEAR_CMF
                                      |UART_CLEAR_TXFECF);
   
}


恳请 知道原因的大牛指点一二,谢谢

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。