一、工程配置
开启USART1,打开串口中断,打开DMA request,选择USART1_RX,模式选择Normal,其他选项默认即可。



二、添加代码
1.使用USART DMA传输数据,可以通过串口的空闲中断来判断数据传输结束,要在DMA开始传输之前使能串口空闲中断,在main函数中添加代码:
/* USER CODE BEGIN 2 */
/*为了方便,把头文件放在此处*/
#include "usart_it.h"
//使能串口空闲中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
//开启DMA传输
HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200);
/* USER CODE END 2 */
使能串口空闲中断和开启一次DMA传输。
2.新建一个.c/.h文件,在.c文件中自定义一个空闲中断处理函数,用于判断数据传输结束。
void USART1_IDLE_Handler()
{
if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) //判断是否是空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除空闲中断标志(否则会一直不断进入中断)
HAL_UART_DMAStop(&huart1);
//获取数据长度
USART1_Stru.RxLen = 200 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
//数据回传
HAL_UART_Transmit(&huart1,USART1_Stru.RxBuff,USART1_Stru.RxLen,1000);
HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200); //重启开始DMA传输
}
}
该函数需要放到串口中断回调中进行判断,在stm32f4xx_it.c中找到USART1_IRQHandler函数,将自定义的处理函数放到USART1_IRQHandler里。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
#include "usart_it.h"
USART1_IDLE_Handler();
/* USER CODE END USART1_IRQn 1 */
}
编译过程可能会出现标识符hdma_usart1_rx未定义的错误,需要在usart.h中添加extern关键字进行声明
![]()

下面是串口管理文件(.c/.h)的完整代码
#include "usart_it.h"
#include <stdio.h>
#if 1
#pragma import(__use_no_semihosting) // 确保没有从 C 库链接使用半主机的函数
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用
{
USART1->DR = (uint8_t) ch;//发送
while((USART1->SR & 0X40) == 0);//等待发送完成
return ch;
}
FILE __stdout;
struct __FILE
{
int handle;
};
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x=x;
}
#endif
USART1_Structure USART1_Stru = { 0 };
void USART1_IDLE_Handler()
{
if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) //判断是否是空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除空闲中断标志(否则会一直不断进入中断)
HAL_UART_DMAStop(&huart1);
//获取数据长度
USART1_Stru.RxLen = 200 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
//数据回传
HAL_UART_Transmit(&huart1,USART1_Stru.RxBuff,USART1_Stru.RxLen,1000);
HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200); //重启开始DMA传输
}
}
#ifndef _USART_IT_H
#define _USART_IT_H
#include "main.h"
#include "usart.h"
//最大接收数据长度
#define USART1RxLEN 200
typedef struct
{
uint8_t receive;
uint8_t RxBuff[USART1RxLEN];
uint8_t RxLen;
}USART1_Structure;
extern USART1_Structure USART1_Stru;
void USART1_IDLE_Handler(void);
#endif
三、实验现象
通过串口调试助手发送不固定长度的数据,单片机接收到后回传到调试助手。

这期的学习就到这里,下期学习ADC读取电压。
本文介绍了如何在STM32F4xx开发板上配置USART1,启用DMA并利用串口空闲中断实现数据的高效传输。通过自定义中断处理函数,确保了数据传输的完整性和DMA的重新启动。

7776

被折叠的 条评论
为什么被折叠?



