在串口通信中,很多时候我们需要的是接收一帧不确定长度的数据,而不是单个字节或者固定长度,这时我们就需要利用STM32的空闲中断(IDLE)来实现不定长数据的接收,首先我们打开STM32Cumebx建立一个工程,配置管脚图:
这里我们采用三线SWD下载方式,加一个LED灯交替闪烁,串口中断+DMA来接收不定长数据,串口采用默认配置,打开串口中断,采用DMA方式进行发送和接收:
然后保存工程生成代码。
生成代码后先定义以下变量:
uint8_t rx_buffer[100];
char BUFFER_SIZE=100;
然后在主函数中加入串口接收回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_DMAStop(&huart1);
uint8_t data_length = BUFFER_SIZE - hdma_usart1_rx.Instance->CNDTR;
HAL_UART_Transmit(&huart1,rx_buffer,data_length,200);
data_length = 0;
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
}
我用的Firmware Package 版本是STM32Cube FW_L4 V1.13.0,需要在库函数stm32l4xx_hal_uart.c中的第2366行加入如下代码段
if(((isrflags & USART_ISR_IDLE)!= RESET) &&((cr1its & USART_CR1_IDLEIE)!=RESET))
{
//clear IDLE flag
__HAL_UART_CLEAR_IDLEFLAG(huart);
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
huart->RxCpltCallback(huart);
#else
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return;
}
这段代码的位置如下图所示:
主函数中我们自己添加的代码:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//这是我们自己添加的代码,让LED灯循环闪烁。
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_Delay(200);
}
/* USER CODE END 3 */
}
当然我们的主函数没有意义,实际功能是在串口回调函数中实现的,目的就是把接收到的数据重新返回给串口助手,效果图如下:
可以看到 当我们给单片机发送一帧数据时,单片机会把同样的数据返回给我们。
注意:在串口初始化程序中我们一定要添加以下两行代码:
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
/* USER CODE END USART1_Init 2 */
并且在串口回调函数中,接收完一帧数据后,需要重新打开串口的DMA接收。
在串口通信中,很多时候我们需要的是接收一帧不确定长度的数据,而不是单个字节或者固定长度,这时我们就需要利用STM32的空闲中断(IDLE)来实现不定长数据的接收,首先我们打开STM32Cumebx建立一个工程,配置管脚图:
这里我们采用三线SWD下载方式,加一个LED灯交替闪烁,串口中断+DMA来接收不定长数据,串口采用默认配置,打开串口中断,采用DMA方式进行发送和接收:
然后保存工程生成代码。
生成代码后先定义以下变量:
uint8_t rx_buffer[100];
char BUFFER_SIZE=100;
然后在主函数中加入串口接收回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_DMAStop(&huart1);
uint8_t data_length = BUFFER_SIZE - hdma_usart1_rx.Instance->CNDTR;
HAL_UART_Transmit(&huart1,rx_buffer,data_length,200);
data_length = 0;
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
}
我用的Firmware Package 版本是STM32Cube FW_L4 V1.13.0,需要在库函数stm32l4xx_hal_uart.c中的第2366行加入如下代码段
if(((isrflags & USART_ISR_IDLE)!= RESET) &&((cr1its & USART_CR1_IDLEIE)!=RESET))
{
//clear IDLE flag
__HAL_UART_CLEAR_IDLEFLAG(huart);
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
huart->RxCpltCallback(huart);
#else
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return;
}
这段代码的位置如下图所示:
主函数中我们自己添加的代码:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//这是我们自己添加的代码,让LED灯循环闪烁。
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_Delay(200);
}
/* USER CODE END 3 */
}
当然我们的主函数没有意义,实际功能是在串口回调函数中实现的,目的就是把接收到的数据重新返回给串口助手,效果图如下:
可以看到 当我们给单片机发送一帧数据时,单片机会把同样的数据返回给我们。
注意:在串口初始化程序中我们一定要添加以下两行代码:
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
/* USER CODE END USART1_Init 2 */
并且在串口回调函数中,接收完一帧数据后,需要重新打开串口的DMA接收。
举报