stm32之不定长接收

使用STM32CUBE_MAX配置工程,可以简化编程工作量,但是这样我们会遇到一些麻烦,比如利用串口接收不知道长度的数据的时候,我们可能会无从下手,前段时间看到他人程序中的串口不定长接收,此次特意总结,包括3类芯片串口不定长配置。

STM32F103ZET6

配置工程:

  • 选择USART1,配置波特率为115200,并开启串口中断,DMA中断

配置程序

  • 在配置工程后,我们需要在工程中重写printf重定向函数fputc()和串口接收函数 UsartReceive_IDLE()代码如下:
  • // 在头文件中定义结构体
    #define RX_LEN        1024
    
    typedef struct  
    {  
    uint8_t  RX_flag:1;        //IDLE receive flag
    uint16_t RX_Size;          //receive length
    uint8_t  RX_pData[RX_LEN]; //DMA receive buffer
    }USART_RECEIVETYPE;  
    
    void UsartReceive_IDLE(UART_HandleTypeDef *huart);
    extern    USART_RECEIVETYPE     UsartType1;
    //定义结构体
    USART_RECEIVETYPE     UsartType1;
    
    // printf重定向
    int fputc(int ch,FILE *f)
    {
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
        return ch;
    }
    
    // USART不定长接收
    void UsartReceive_IDLE(UART_HandleTypeDef *huart)  
    {  
        uint32_t temp;  
      
        if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  // Checks whether the specified UART idle flag is set or not.
        {   
            __HAL_UART_CLEAR_IDLEFLAG(huart);                     // Clears the UART IDLE pending flag.
            HAL_UART_DMAStop(huart);                              // Stops the DMA Transfer.
            temp = huart->hdmarx->Instance->CNDTR;                // Read DMA stream x number of data register 
            huart->hdmarx->Instance->CNDTR = 0;                   // Clear DMA stream x number of data register
            if(huart == &huart1)                                  // Checks whitch USART 
            {
                UsartType1.RX_Size =  RX_LEN - temp;   
                UsartType1.RX_flag=1;                             // Set RX_flag
                HAL_UART_Receive_DMA(&huart1,UsartType1.RX_pData,RX_LEN);  // start DMA interrupt and receives an amount of data in non blocking mode. 
            }
        }  
    } 

    配置完成后,需要在xxx_it.c中断函数中添加相应串口的UsartReceive_IDLE( ) 函数

  • /**
    * @brief This function handles USART1 global interrupt.
    */
    void USART1_IRQHandler(void)
    {
      /* USER CODE BEGIN USART1_IRQn 0 */
        UsartReceive_IDLE(&huart1);  
      /* USER CODE END USART1_IRQn 0 */
      HAL_UART_IRQHandler(&huart1);
      /* USER CODE BEGIN USART1_IRQn 1 */
    
      /* USER CODE END USART1_IRQn 1 */
    }

    在主函数中需要开启DMA接收中断,和串口空闲中断,程序如下:

  •   MX_GPIO_Init();
      MX_DMA_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
        
        HAL_UART_Receive_DMA(&huart1, UsartType1.RX_pData, RX_LEN);    // Receives an amount of data in non blocking mode. 
        __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                  // Enable the specified UART interrupt.                  
        
        printf("**************C print 重定向*************\r\n");
        printf("**********USART_IDLE 不定长接收**********\r\n");
        
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
            if(UsartType1.RX_flag )
            {
                UsartType1.RX_flag = 0;
                HAL_UART_Transmit(&huart1, UsartType1.RX_pData, UsartType1.RX_Size, 0xffff);
            }
      }    

运行结果

猜你喜欢

转载自www.cnblogs.com/icefree/p/9227039.html