使用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 */ }