• 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 重定向*************
      ");
          printf("**********USART_IDLE 不定长接收**********
      ");
          
        /* 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);
              }
        }    

    运行结果

    STM32F429IGT6 & STM32F767IGT6

    配置工程:

    • 工程配置与 STM32F103ZET6 相同。

    配置程序:

    • 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     UsartTy// printf重定向
      // 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->NDTR;                                  // Read DMA stream x number of data register 
              huart->hdmarx->Instance->NDTR = 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);
        __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
          
        printf("**************C print 重定向*************
      ");
        printf("**********USART_IDLE 不定长接收**********
      ");
        /* USER CODE END 2 */
      
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
              if(UsartType1.RX_flag)
              {
                  HAL_UART_Transmit(&huart1, UsartType1.RX_pData, UsartType1.RX_Size, 0xff);
                  UsartType1.RX_flag =  0;
              }
              
        /* USER CODE END WHILE */
      
        /* USER CODE BEGIN 3 */
      
        }

    运行结果:

  • 相关阅读:
    【CSS】419- 彻底搞懂word-break、word-wrap、white-space
    【Webpack】418- 深度优化 Webpack 性能,翻倍构建性能
    【React】417- React中componentWillReceiveProps的替代升级方案
    巩固java(二)----JVM堆内存结构及垃圾回收机制
    巩固java(一)----java与对象
    Latex 公式换行问题,(换行,等号对齐)
    Android FoldingLayout 折叠布局 原理及实现(二)
    19.最省钱的app发短信方法
    Android FoldingLayout 折叠布局 原理及实现(一)
    18.app后端如何实现LBS
  • 原文地址:https://www.cnblogs.com/icefree/p/9227039.html
Copyright © 2020-2023  润新知