硬汉嵌入式论坛

 找回密码
 立即注册
查看: 910|回复: 7
收起左侧

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

[复制链接]

3

主题

6

回帖

15

积分

新手上路

积分
15
发表于 2023-4-6 23:03:25 | 显示全部楼层 |阅读模式
我用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++;   
    }
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2023-4-7 17:49:07 | 显示全部楼层
方便的话,完整的配置贴下
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 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);               
        }
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2023-4-8 01:54:36 | 显示全部楼层
你的DMA时钟初始化放在了那里
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 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);
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 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;
  }
}
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2023-4-11 22:18:57 | 显示全部楼层
谢谢eric2013指导!
在你的指导下,我修改了对HAL_UARTEx_ReceiveToIdle_DMA的调用,在while中不调用HAL_UARTEx_ReceiveToIdle_DMA,在HAL_UARTEx_RxEventCallback中调用。
但是结果还是但是半完成和空闲分支完全进不去;debug时,空闲能进。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2023-4-12 15:59:48 | 显示全部楼层
easy 发表于 2023-4-11 22:18
谢谢eric2013指导!
在你的指导下,我修改了对HAL_UARTEx_ReceiveToIdle_DMA的调用,在while中不调用HA ...

别的问题你自己再找找吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-26 03:36 , Processed in 0.170494 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表