文章主要参考了
https://blog.csdn.net/qq_42810361/article/details/106570373
Cubemx的配置
跳过基本的配置
1USART1 配置
中断配置
其他默认配置不改变
代码块
usart.c 这里要添加头文件#include<string.h>
ts_usart_type usart_nb_type;
void hal_uart_recv_init(void)
{
/* 1. 打开串口空闲中断 */
__HAL_UART_ENABLE_IT(&huart1 ,UART_IT_IDLE );
/* 2. 打开 DMA 接收 */
HAL_UART_Receive_DMA(&huart1 ,usart_nb_type.usart_dma_recv_buffer, USART_DMA_RECV_SIZE);
}
void hal_uart_irq_prejudge(void)
{
uint32_t temp;
/* 1. 判断空闲中断 */
if(__HAL_UART_GET_FLAG(&huart1 , UART_FLAG_IDLE) != RESET)
{
/* 2. 清除中断 */
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
/* 3. 停止 DMA 接收 */
HAL_UART_DMAStop(&huart1);
//清除 DMA 接收中断,只需读取一次状态寄存器和数据寄存器,即可实现
temp = huart1.Instance->ICR;
temp = huart1.Instance->RDR;
/* 4. 获取 DMA 接收数据长度 : NDTR 为递减计数器,故 SIZE - NDTR*/
temp = USART_DMA_RECV_SIZE -__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
usart_nb_type.usart_dma_recv_len = temp;
/* 5. 串口回调函数 */
HAL_UART_RxCpltCallback(&huart1);
}
}
void hal_uart_recv_judge(void)
{
/* 1. 判断是否有完整数据 */
if(usart_nb_type.usart_recv_flag == 1)
{
/* 2. 打印数据到指定串口 */
HAL_UART_Transmit(&huart1 ,usart_nb_type.usart_recv_buffer ,usart_nb_type.usart_recv_len ,100 );
/* 3. 清空接收缓存区 */
memset(usart_nb_type.usart_recv_buffer ,0 ,usart_nb_type.usart_recv_len);
/* 4. 清空数据接收标志 */
usart_nb_type.usart_recv_flag = 0;
/* 5. 清空数据接收长度 */
usart_nb_type.usart_recv_len = 0;
}
}
usart.h
#define USART_DMA_RECV_SIZE 256
#define USART_RECV_SIZE 1024
/* 串口数据类型 */
typedef struct
{
/* 数据接收标志 */
uint8_t usart_recv_flag;
/* 数据解析长度 */
uint16_t usart_recv_len;
/* DMA 数据长度 */
uint16_t usart_dma_recv_len;
/* 数据解析缓冲区 */
uint8_t usart_recv_buffer [USART_RECV_SIZE];
/* DMA 数据缓冲区 */
uint8_t usart_dma_recv_buffer [USART_DMA_RECV_SIZE];
}ts_usart_type;
extern ts_usart_type usart_nb_type;
void hal_uart_recv_judge(void);
void hal_uart_recv_init(void);
void hal_uart_irq_prejudge(void);
stm32g4xx_it.c中 添加usart.h头文件
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
hal_uart_irq_prejudge();
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
HAL_UART_Receive_DMA(&huart1 ,usart_nb_type.usart_dma_recv_buffer ,USART_DMA_RECV_SIZE);
/* USER CODE END USART1_IRQn 1 */
}
修改这个处理函数
main.c 中 添加头文件string.h
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* 1. 判断是否为 NB 串口 */
if(huart->Instance == huart1.Instance)
{
/* 2. 判断是否有未处理的数据 */
/* 有,从地址 0+old_len 开始获取 DMA 接收区数据。 */
if(usart_nb_type.usart_recv_len > 0)
{
memcpy(&usart_nb_type.usart_recv_buffer[usart_nb_type.usart_recv_len] ,usart_nb_type.usart_dma_recv_buffer ,usart_nb_type.usart_dma_recv_len);
usart_nb_type.usart_recv_len += usart_nb_type.usart_dma_recv_len;
}
/* 无,从地址 0 开始获取 DMA 接收区数据。 */
else
{
memcpy(usart_nb_type.usart_recv_buffer ,usart_nb_type.usart_dma_recv_buffer ,usart_nb_type.usart_dma_recv_len);
usart_nb_type.usart_recv_len = usart_nb_type.usart_dma_recv_len;
}
/* 3. 清空 DMA 接收区 */
memset(usart_nb_type.usart_dma_recv_buffer ,0 ,usart_nb_type.usart_dma_recv_len);
/* 4. 清空 DMA 接收长度 */
usart_nb_type.usart_dma_recv_len = 0;
/* 5. 置位数据接收标志 */
usart_nb_type.usart_recv_flag = 1;
hal_uart_recv_judge();
}
}
在while(1)之前初始化
hal_uart_recv_init();
while (1)