STM32 HAL库实现DMA串口通信

前言

  • 软件版本

STM32CubeMX 6.4 0
Keil 531

  • 硬件

STM32F103C8T6

1 DMA简介

DMA 全称Direct Memory Access,即直接存储器访问

DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的

DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节。

我们知道,数据传输,首先需要的是数据的源地址、数据传输位置的目标地址、传递数据多少的数据传输量、进行多少次传输的传输模式。DMA所需要的核心参数,便是这四个。每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。

因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理

在这里插入图片描述
DMA传输方式

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

  • 外设到内存
  • 内存到外设
  • 内存到内存
  • 外设到外设

DMA的主要特征

每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置;

  • 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推);
  • 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;
  • 支持循环的缓冲器管理;
  • 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
  • 存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;
  • 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;
  • 可编程的数据传输数目:最大为65535。

2 通过CubeMX创建项目

不懂的步骤可以看我另一篇博客:https://blog.csdn.net/apple_52030329/article/details/127232960

2.1 设置RCC

在这里插入图片描述
之后照样配置时钟

2.2 设置USART1

  • 选择异步通信,参数选择默认
    在这里插入图片描述

  • 使能串口
    在这里插入图片描述

  • 添加两个通道
    在这里插入图片描述

2.3 创建项目

老样子配置项目

在这里插入图片描述

3 Keil配置项目

打开刚才配置好的项目

3.1 修改main代码

int main(void)
{

  HAL_Init();

	uint8_t message[] = "DMA communication test\n";  //定义数据发送数组

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();

  while (1)
  {
    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)message, sizeof(message));
	  HAL_Delay(1000);
  }
}

3.2 烧录

烧录工具选择 mcuisp
在这里插入图片描述

4 实现效果

通过串口调试助手查看,效果如下

在这里插入图片描述

总结

串口通信的实现方式有多种,轮询、中断以及使用DMA处理等,各有利弊。本文学习使用了DMA方式,实现了简单的串口通信程序


参考
https://blog.csdn.net/isyuuun/article/details/121074067
https://blog.csdn.net/qq_47281915/article/details/121063896?spm=1001.2014.3001.5501
https://blog.csdn.net/as480133937/article/details/104827639/

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32HAL库中使用DMA进行串口通信的步骤如下: 1. 初始化串口和DMA。 2. 配置DMA传输方向、数据长度、传输模式等参数。 3. 启动DMA传输。 4. 在DMA传输完成中断中处理接收到的数据。 下面是一个使用DMA进行串口接收的示例代码: ```c /* 初始化串口和DMA */ UART_HandleTypeDef huart; DMA_HandleTypeDef hdma_usart_rx; void MX_USART_UART_Init(void) { /* ... */ /* 初始化串口 */ if (HAL_UART_Init(&huart) != HAL_OK) { Error_Handler(); } /* 初始化DMA */ __HAL_RCC_DMA1_CLK_ENABLE(); hdma_usart_rx.Instance = DMA1_Channel5; hdma_usart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart_rx.Init.Mode = DMA_CIRCULAR; hdma_usart_rx.Init.Priority = DMA_PRIORITY_HIGH; if (HAL_DMA_Init(&hdma_usart_rx) != HAL_OK) { Error_Handler(); } /* 关联DMA和串口 */ __HAL_LINKDMA(&huart, hdmarx, hdma_usart_rx); /* ... */ } /* 启动DMA传输 */ void HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { /* 关闭DMA传输 */ HAL_DMA_Abort(huart->hdmarx); /* 配置DMA传输参数 */ hdma_usart_rx.Instance->CNDTR = Size; hdma_usart_rx.Instance->CPAR = (uint32_t)&huart->Instance->DR; hdma_usart_rx.Instance->CMAR = (uint32_t)pData; /* 启动DMA传输 */ HAL_DMA_Start(huart->hdmarx, (uint32_t)&huart->Instance->DR, (uint32_t)pData, Size); } /* 在DMA传输完成中断中处理接收到的数据 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* 处理接收到的数据 */ } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日常脱发的小迈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值