eefeef001 发表于 2019-8-23 18:57:26

STM32F0C8T6使用空闲中断+DMA,接收数据不正常


问题是这样的:
      空闲中断接收,复位后,接收大于1个字节,只能收到第一个字节。
                              复位后,单次接收一个字节,第一次正常,第二次数据会出现在接收数组的第二位中,第三次及往后都正常,接收多字节也正常。







void DMA_Usart2Init(uint32_t bound)
{
    UART2_Handler.Instance = USART2;
    UART2_Handler.Init.BaudRate = bound;
    UART2_Handler.Init.StopBits = UART_STOPBITS_1;
    UART2_Handler.Init.Parity = UART_PARITY_NONE;
    UART2_Handler.Init.Mode = UART_MODE_TX_RX;
    UART2_Handler.Init.WordLength = UART_WORDLENGTH_8B;
    UART2_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UART2_Handler.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
//      UART2_Handler.Init.OneBitSampling =
      UART2_Handler.Init.OverSampling = UART_OVERSAMPLING_16;
    if(HAL_UART_Init(&UART2_Handler) != HAL_OK)
    {
      Error_Handler();
    }
      
    HAL_NVIC_SetPriority(USART2_IRQn,0,0);//第二个数字,对于Core M0无用
    HAL_NVIC_EnableIRQ(USART2_IRQn);
      
      HAL_NVIC_SetPriority(DMA1_Channel4_5_IRQn, 0, 0);
      HAL_NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
      
      __HAL_UART_ENABLE_IT(&UART2_Handler,UART_IT_IDLE);//使用空闲中断,不用接收中断
//      __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);
      HAL_UART_Receive_DMA(&UART2_Handler,USART2_ReceiveBuf,128);
}








/**
* @brief      串口初始化回调函数.
* @param      huart   串口号USART1,USART2         
* @retval      无.
* @note                2019/07/31.
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStruct;
    if(huart->Instance==USART2)
    {
      USART2_RX_GPIO_CLK_ENABLE();                        //使能GPIOA时钟
      USART2_TX_GPIO_CLK_ENABLE();
                __HAL_RCC_DMA1_CLK_ENABLE();
      USART2_CLK_ENABLE();                        //使能USART2时钟

      GPIO_InitStruct.Alternate = USART2_TX_AF;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pin = USART2_TX_PIN;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
      HAL_GPIO_Init(USART2_TX_PORT, &GPIO_InitStruct);

      GPIO_InitStruct.Alternate = USART2_RX_AF;
      GPIO_InitStruct.Pin = USART2_RX_PIN;
      HAL_GPIO_Init(USART2_RX_PORT, &GPIO_InitStruct);

#ifdef DMA_Usart
      /* USART2 DMA Init */
      /* USART2_RX Init */
      hdma_usart2_rx.Instance = DMA1_Channel5;
      hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
      hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
      hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
      hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      hdma_usart2_rx.Init.Mode = DMA_NORMAL;
      hdma_usart2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;      
      if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
      {
            Error_Handler();
      }

      __HAL_LINKDMA(huart,hdmarx,hdma_usart2_rx);

      /* USART2_TX Init */
      hdma_usart2_tx.Instance = DMA1_Channel4;
      hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
      hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
      hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
      hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      hdma_usart2_tx.Init.Mode = DMA_NORMAL;
      hdma_usart2_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
      if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
      {
            Error_Handler();
      }
      __HAL_LINKDMA(huart,hdmatx,hdma_usart2_tx);
#else
#endif
    }
}














/**
* @brief      USART2中断服务函数.
* @param      无
* @retval      无.
* @note                2019/07/31.
*/
void USART2_IRQHandler(void)
{
    uint32_t timeout = 0;
    HAL_UART_IRQHandler(&UART2_Handler);      //调用HAL库中断处理公用函数      该函数会清空中断标志,取消中断使能,并间接调用回调函数

                if((__HAL_UART_GET_FLAG(&UART2_Handler,UART_FLAG_IDLE) != RESET))
                {
                        __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);
                  __HAL_UART_CLEAR_IT(&UART2_Handler,UART_FLAG_IDLE);      
                        __HAL_DMA_CLEAR_FLAG(hdma_usart2_rx,DMA_FLAG_TC5);
                        USART2->ICR |= 1<<4;
                        HAL_UART_DMAStop(&UART2_Handler); //
                        len = 128 - (__HAL_DMA_GET_COUNTER(&hdma_usart2_rx));
                        HAL_UART_Receive_DMA(&UART2_Handler,USART2_ReceiveBuf,128);
                        if(len <= 128)
                        {
                              
                        }
                }
}






wenyangzeng 发表于 2019-8-23 19:06:33

IDLE中断根本没有处理任何接收数据,如果不使用接收中断则无法随时向缓冲区写入接收数据,当IDLE中断到来时数据就不正确。
页: [1]
查看完整版本: STM32F0C8T6使用空闲中断+DMA,接收数据不正常