一、CubeMX配置
首先配置时钟源
打开调试
打开PC13板载小灯,方便观察板子是否正常运行
串口一、串口三 波特率选择9600
中断配置
DMA配置
rx选择正常(normal)模式
tx选择正常模式
选择好路径,生成代码
二、程序配置
串口一和串口三收发一帧数据配置
uart.c
/* USER CODE BEGIN 0 */ volatile uint8_t rx1_len = 0; //接收一帧数据的长度 volatile uint8_t recv1_end_flag = 0; //一帧数据接收完成标志 uint8_t rx1_buffer[20]={0}; //接收数据缓存数组 volatile uint8_t rx3_len = 0; //接收一帧数据的长度 volatile uint8_t recv3_end_flag = 0; //一帧数据接收完成标志 uint8_t rx3_buffer[20]={0}; //接收数据缓存数组 /* USER CODE END 0 */
/* USER CODE BEGIN USART1_Init 2 */ //下方为自己添加的代码 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断 //DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度 HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE1); /* USER CODE END USART1_Init 2 */
/* USER CODE BEGIN USART3_Init 2 */ __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE3); /* USER CODE END USART3_Init 2 */
uart.h
/* USER CODE BEGIN Private defines */ extern DMA_HandleTypeDef hdma_usart1_rx; extern DMA_HandleTypeDef hdma_usart1_tx; extern DMA_HandleTypeDef hdma_usart3_rx; extern DMA_HandleTypeDef hdma_usart3_tx; #define BUFFER_SIZE1 20 extern volatile uint8_t rx1_len ; //接收一帧数据的长度 extern volatile uint8_t recv1_end_flag; //一帧数据接收完成标志 extern uint8_t rx1_buffer[20]; //接收数据缓存数组 #define BUFFER_SIZE3 20 extern volatile uint8_t rx3_len ; //接收一帧数据的长度 extern volatile uint8_t recv3_end_flag; //一帧数据接收完成标志 extern uint8_t rx3_buffer[20]; //接收数据缓存数组 /* USER CODE END Private defines */
main.c
/* USER CODE BEGIN 0 */ void DMA_Usart1_Send(uint8_t *buf,uint8_t len)//串口发送封装 { if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数 { Error_Handler(); } } void DMA_Usart3_Send(uint8_t *buf,uint8_t len) { if(HAL_UART_Transmit_DMA(&huart3, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数 { Error_Handler(); } } void DMA_Usart1_Read(uint8_t *Data,uint8_t len)//串口接收封装 { HAL_UART_Receive_DMA(&huart1,Data,len);//重新打开DMA接收 } void DMA_Usart3_Read(uint8_t *Data,uint8_t len)//串口接收封装 { HAL_UART_Receive_DMA(&huart3,Data,len);//重新打开DMA接收 } /* USER CODE END 0 */
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(recv1_end_flag == 1) //接收完成标志 { DMA_Usart1_Send(rx1_buffer, rx1_len); rx1_len = 0;//清除计数 recv1_end_flag = 0;//清除接收结束标志位 memset(rx1_buffer,0,rx1_len); } HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE1);//重新打开DMA接收 if(recv3_end_flag == 1) //接收完成标志 { DMA_Usart3_Send(rx3_buffer, rx3_len); rx3_len = 0;//清除计数 recv3_end_flag = 0;//清除接收结束标志位 memset(rx3_buffer,0,rx3_len); } HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE3);//重新打开DMA接收 } /* USER CODE END 3 */
stm32f1xx_it.c
添加头文件
/* USER CODE BEGIN Includes */ #include "usart.h" /* USER CODE END Includes */
使用ctl+F搜索USART1_IRQHandle并添加进去
void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位 if((tmp_flag != RESET))//idle标志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位 //temp = huart1.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能 //temp = huart1.Instance->DR; //读取数据寄存器中的数据 //这两句和上面那句等效 HAL_UART_DMAStop(&huart1); // 停止DMA传输,防止 temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数 //temp = hdma_usart1_rx.Instance->NDTR;// 读取NDTR寄存器,获取DMA中未传输的数据个数, rx1_len = BUFFER_SIZE1 - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数 recv1_end_flag = 1; // 接受完成标志位置1 } /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ }
使用ctl+F搜索USART3_IRQHandle并添加进去
void USART3_IRQHandler(void) { /* USER CODE BEGIN USART3_IRQn 0 */ uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE); //获取IDLE标志位 if((tmp_flag != RESET))//idle标志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除标志位 HAL_UART_DMAStop(&huart3); // 停止DMA传输,防止 temp = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);// 获取DMA中未传输的数据个数 rx3_len = BUFFER_SIZE3 - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数 recv3_end_flag = 1; // 接受完成标志位置1 } /* USER CODE END USART3_IRQn 0 */ HAL_UART_IRQHandler(&huart3); /* USER CODE BEGIN USART3_IRQn 1 */ /* USER CODE END USART3_IRQn 1 */ }
运行效果
链接: https://pan.baidu.com/s/1CxrKHNUcLv8lplg5WZwiKA?pwd=yaf7 提取码: yaf7
原文链接
STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA___hal_dma_get_counter-CSDN博客