STM32 HAL库 CubeMX教程(六)DMA数据传输

STM32 HAL库 CubeMX教程(六)DMA数据传输


STM32 HAL库 CubeMX系列教程 目录

DMA简介

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

stm32有两个DMA控制器,共12个通道(DMA1有7个通道, DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。

DMA框图:
在这里插入图片描述
DMA1各个通道的请求映像:
在这里插入图片描述
DMA2各个通道的请求映像:
在这里插入图片描述
DMA 传输数据的方向有三个:从外设到存储器,从存储器到外设,从存储器到存储器。

外设一般是指外设的数据寄存器,比如 ADC、 SPI、 I2C 等外设的数据寄存器。存储器一般是指片内 SRAM、外部存储器、片内 Flash等。总结就是传输数据时使用 DMA 传输而不占用 CPU,解放 CPU,让 CPU 有足够的时间处理其它事情。

我们可以使用 DMA 传输把指定存储器数据转移到 USART 寄存器内,并发送至 PC 端, 由串口调试助手显示。

CubeMX配置

  1. 时钟配置和之前相同
  2. 串口1复用到PB6,PB7,采用异步模式,并使能中断
    PA9与LED相连,设置为输出模式
    在这里插入图片描述
    在这里插入图片描述
  3. DMA配置
    在这里插入图片描述

DMA初始化

DMA_ InitTypeDef 初始化结构体 :
在这里插入图片描述

  1. Direction:传输方向选择,可选外设到存储器、存储器到外设以及存储器到存储
    器。它设定 DMA_SxCR 寄存器的 DIR[1:0]位的值。
  2. PeripheralInc:如果配置为 DMA_PINC_ENABLE,使能外设地址自动递增功能,
    它设定 DMA_CCR 寄存器的 PINC 位的值;一般外设都是只有一个数据寄存器,
    所以一般不会使能该位。
  3. MemoryInc:如果配置为 DMA_MINC_ENABLE,使能存储器地址自动递增功能,
    它设定 DMA_CCR 寄存器的 MINC 位的值;我们自定义的存储区一般都是存放多
    个数据的,所以要使能存储器地址自动递增功能。
  4. PeriphDataAlignment:外设数据宽度,可选字节(8 位)、半字(16 位)和字(32 位),
    它设定 DMA_SxCR 寄存器的 PSIZE[1:0]位的值。 ADC 数据寄存器只有低 16 位数
    据有效,使用半字数据宽度。
  5. Mode: DMA 传输模式选择,可选一次传输或者循环传输,它设定 DMA_SxCR 寄
    存器的 CIRC 位的值。我们希望 ADC 采集是持续循环进行的,所以使用循环传输
    模式。
  6. 软件设置数据流的优先级,有 4 个可选优先级分别为非常高、高、中和低,它设
    定 DMA_SxCR 寄存器的 PL[1:0]位的值。 DMA 优先级只有在多个 DMA 数据流同
    时使用时才有意义,这里我们设置为高优先级就可以了。
    hdma_usart1_tx.Instance = DMA1_Channel4; //DAMAͨµÀ
    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_CIRCULAR;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_HIGH;

DMA-UART数据收发

我们使用DMA将数据从内部flash转移到 USART 寄存器内,并发送至 PC 端, 由串口调试助手显示。
主函数编写:

  1. 定义发送和接收数据的缓冲区
/* USER CODE BEGIN 0 */
uint8_t aRxBuffer;                      
uint8_t aTxBuffer[SENDBUFF_SIZE];       
/* USER CODE END 0 */
  1. 定义要发送的数据到缓冲区,我们平时定义的常量都存储在单片机内部存储器中
    同时使能接收串口中断,启动DMA发送
/* USER CODE BEGIN 2 */
 for(uint16_t i=0;i<SENDBUFF_SIZE;i++)
  aTxBuffer[i]='h';
 HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);
 HAL_UART_Transmit_DMA(&huart1,aTxBuffer,SENDBUFF_SIZE);
  /* USER CODE END 2 */
  1. 中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart1,&aRxBuffer,1,0);
  HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);
}
  1. 为了验证DMA传输时不占用单片机的CPU,我们在while内使LED不停地闪烁
while (1)
{
  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9);
  HAL_Delay(500);
}
  1. 串口助手不断地显示’h’,同时LED不停地闪烁
    在这里插入图片描述
    由于DMA传输速率很快,记得及时点击清除接收清屏,防止串口助手卡死!

参考资料

  1. 硬石YS-F1Pro开发板开发手册(HAL库版本20170104更新).pdf
  2. STM32F10xxx参考手册.pdf
  3. 【野火】《STM32+HAL+库开发实战指南—基于F103-MINI》.pdf
发布了14 篇原创文章 · 获赞 18 · 访问量 7668

猜你喜欢

转载自blog.csdn.net/weixin_43116606/article/details/104233238