easy 发表于 2023-4-6 23:03:25

求助STM32F103的USART接收,没找到合适的板块发,请版主手下留情

我用DMA+USART接收,回调函数中想看看是不是能处理 接收完成、半完成和空闲,但是半完成和空闲分支完全进不去。
debug时,空闲能进。请大拿帮忙解释一下,谢谢!
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{   
if( huart->Instance == USART1 )
{   

    if( RESET !=(__HAL_UART_GET_FLAG(huart, UART_FLAG_TC)))
    {
      __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
      u1RxCpltFlg++;      
    }

    if(SET == __HAL_DMA_GET_IT_SOURCE(&hdma_usart1_rx,DMA_IT_HT))
    {
      u1RxHlfFlg++;
      return;
    }
    if(RESET != __HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE))      
    {
      __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_IDLE);
      u1RxidlFlg++;   
    }
}

eric2013 发表于 2023-4-7 17:49:07

方便的话,完整的配置贴下

easy 发表于 2023-4-7 20:22:32

串口是这么配置的:
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
    Error_Handler();
}

        __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //enable U1 IDLE Interrupt
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */

/* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9   ------> USART1_TX
    PA10   ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA1_Channel4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */

/* USER CODE END USART1_MspInit 1 */
}
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */

/* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9   ------> USART1_TX
    PA10   ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmarx);
    HAL_DMA_DeInit(uartHandle->hdmatx);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */

/* USER CODE END USART1_MspDeInit 1 */
}
}

主函数里面
int main(void)
{
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
        MX_DMA_Init();
        MX_USART1_UART_Init();
       
        sprintf(u1SndBuf,"Counting RxHlfCplt/RxCplt/RxIdle times:");
      memset(u1RcvBuf,0,BUF_SIZE);
      uint8_t SndLen=strlen(u1SndBuf);       

      HAL_UARTEx_ReceiveToIdle_DMA(huart,u1RcvBuf,Size);
        while (1)
        {                  
                if( u1RxCpltFlg||u1RxCpltFlg||u1RxidlFlg )
                {
                        sprintf(u1SndBuf+SndLen,"%d/%d/%d\n",u1RxHlfFlg,u1RxCpltFlg,u1RxidlFlg);
                        HAL_UART_Transmit_DMA(&huart1, (uint8_t *)u1SndBuf, strlen(u1SndBuf));                                                     
                }   
      HAL_UARTEx_ReceiveToIdle_DMA(huart,u1RcvBuf,Size);               
        }
}

eric2013 发表于 2023-4-8 01:54:36

你的DMA时钟初始化放在了那里

easy 发表于 2023-4-9 18:08:07

在dma.c文件里,应该没问题,数据能收到。
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}

eric2013 发表于 2023-4-10 08:56:54


函数HAL_UARTEx_ReceiveToIdle_DMA(huart,u1RcvBuf,Size)是非阻塞的,你不能一直执行的这个函数,一直执行就出问题了。

把这个函数的返回值加上,记得做个判断。

HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
HAL_StatusTypeDef status;

/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    __HAL_LOCK(huart);

    /* Set Reception type to reception till IDLE Event*/
    huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;

    status =UART_Start_Receive_DMA(huart, pData, Size);

    /* Check Rx process has been successfully started */
    if (status == HAL_OK)
    {
      if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
      {
      __HAL_UART_CLEAR_IDLEFLAG(huart);
      SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
      }
      else
      {
      /* In case of errors already pending when reception is started,
         Interrupts may have already been raised and lead to reception abortion.
         (Overrun error for instance).
         In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
      status = HAL_ERROR;
      }
    }

    return status;
}
else
{
    return HAL_BUSY;
}
}

easy 发表于 2023-4-11 22:18:57

谢谢eric2013指导! :)
在你的指导下,我修改了对HAL_UARTEx_ReceiveToIdle_DMA的调用,在while中不调用HAL_UARTEx_ReceiveToIdle_DMA,在HAL_UARTEx_RxEventCallback中调用。
但是结果还是但是半完成和空闲分支完全进不去;debug时,空闲能进。:dizzy::'(:'(

eric2013 发表于 2023-4-12 15:59:48

easy 发表于 2023-4-11 22:18
谢谢eric2013指导!
在你的指导下,我修改了对HAL_UARTEx_ReceiveToIdle_DMA的调用,在while中不调用HA ...

别的问题你自己再找找吧
页: [1]
查看完整版本: 求助STM32F103的USART接收,没找到合适的板块发,请版主手下留情