要求: 使用DMA将串口UART接收到的数, 重新返回给串口端
分析:
串口的接收中断 -> 中断回调 (经过CPU控制)
DMA 的串口接收 -> DMA的回调 (绕过CPU)
与STM32U575单片机通过串口和按键中断两种方式切换模式_stm32实现模式的切换-CSDN博客不同的是,之前的方式是UART中断后,是CPU取值-译码-执行的步骤获取到的值,而使用DMA搬运USART数据不经过CPU处理,速度更快。
之前调用的中断函数:HAL_UART_Receive_IT(&huart1, (uint8_t *)buf, 3);中断的同时,CPU已经处理好了UART-RX的3个长度字节。
这次需要使用另外的UART中断函数:__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);只进行中断使能,就需要在中断向量表中对应的中断函数增加对应的动作,以实现使用DMA搬运USART数据。
使用STM32cubeMX工具配置
代码如下:

void USART1_IRQHandler(void)
{
extern uint8_t RecvBuf[2048]; //DMA接收uart的buf
HAL_UART_IRQHandler(&huart1);
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)
{
//关闭DMA-USART, 防止新的数据与旧的数据 合并
HAL_UART_DMAStop(&huart1);
//清除空闲中断标志位
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
printf((char *)"%s\n\r",RecvBuf);
huart1.pRxBuffPtr = RecvBuf; //重新初始化缓存区
huart1.RxXferCount = 2048; //重新初始化接受的长度
memset(RecvBuf,0,sizeof(RecvBuf));
HAL_UART_Receive_DMA(&huart1,RecvBuf,2048);
}
}
主函数:
uint8_t RecvBuf[2048];
int main(void)
{
HAL_Init();
SystemClock_Config();
SystemPower_Config();
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_USART1_UART_Init();
MX_ICACHE_Init();
//开启DMA接收
HAL_UART_Receive_DMA(&huart1, RecvBuf, sizeof(RecvBuf));
//开启空闲中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
while (1)
{
printf("delay5s\n\r");
HAL_Delay(5000);
}
}
效果如下,功能为每5s打印一次delay5s,在此期间键盘输入的hello world每输入一个字符就自动打印: