STM32CUBEMX 使用教程5 — DMA配置 & 串口结合DMA实现数据搬运

STM32CUBEMX 使用文章:

STM32CUBEMX 使用教程4 — 串口 (USART) 配置、重定向 printf 输出

STM32CUBEMX 使用教程3 — 外部中断(EXTI)的使用

STM32CUBEMX 使用教程2 — GPIO的使用、输入/输出

STM32CUBEMX 使用教程 1 — 配置环境、新建工程

STM32CUBEMX 详细安装教程

一、DMA简介

DMA(Direct Memory Access),直接存储器访问(或数据搬运),是STM32中很实用的一个外设。

DMA 传输数据方式不需要 CPU 参与控制传输,也不用中断处理的方式进行数据搬运处理,纯粹通过硬件为 RAM 与 I/O 设备之间开辟一条直接传送数据的通路,使 CPU 的效率大大提高。

由于我手头上使用的是STM32F103ZET6,所以按照这个进行讲解,同型号不同规格的有些差异,具体的请参考指导手册。

STM32F103ZET6 有两个 DMA 控制器,DMA1 和 DMA2,其中,DMA1 有 7 个通道,DMA2 有 5 个通道, 不同的 DMA 控制器映射不同的的外设请求。映射表如下:

DMA控制器的框图如下:

从上图中可以看到:

(1)DMA传输数据请求

外设想要通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求,DMA 收到 请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕。

(2)DMA通道映射

DMA1 有 7 个通道,DMA2 有 5 个通道,每个通道对应不同的外设的 DMA 请求。

虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

(3)多请求仲裁机制

当有多个 DMA 通道请求传输时,由仲裁器管理先后响应的顺序问题。

仲裁器管理 DMA 通道请求分为两个阶段:第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高,高,中和低四个优先级。

第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道 0 高于通道 1。

本文通过 DMA1 和 USART1 演示,将内存缓存区的数据(Data_buffer)通过DMA搬运到 USART1 输出。

从上面可以知道,USART1_TX 映射到 DMA1 的 4 通道。

二、STM32CUBEMX 配置DMA

(1)打开上期的USART 的配置工程,并开启DMA功能。

USART的配置参考我上一期的文章:

STM32CUBEMX 使用教程4 — 串口 (USART) 配置、重定向 printf 输出

选择 USART1 的 TX 并增加 DMA ,如下图:

(2)增加 DMA 通道映射到 USART1_TX,如下图:

(3)DMA的通道映射方向为 Memory --> Peripheral,其他的设置如下:

说明一下:

Direction:传输方向。有两种:

Memory to Periphral:内存到外设;

Periphral to Memory:外设到内存;

Mode:模式,有两种:

Normal:正常模式,DMA初始化完成以后传输一次,后面想要再次传输时要重新初始化一次DMA。

Circular:循环模式,DMA初始化完成以后会一直传输。

DMA 数据宽度:

Byte:字节

Half Word:半字

Word:字

代码生成之后,DMA初始化代码如下:

void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();


  /* DMA interrupt init */
  /* DMA1_Channel4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
}

USART 与 DMA 的相关代码配置如下:

/* USART1 DMA Init */
    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA1_Channel4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }


    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

因为本文配置的是从内存通过DMA把数据搬运到USART,所以需要定义发送数据的区域。如下:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t Tx_data[] = {"DMA Test, 微信公众号:嵌入式之入坑笔记!\r\n"};
/* USER CODE END 0 */

调用API接口发送数据:

HAL_UART_Transmit_DMA(&huart1, (uint8_t*)Tx_data, sizeof(Tx_data));

实验现象如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式之入坑笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值