STM32F407ZG DMA

news/2024/11/7 18:16:06/

STM32F407ZG开发板学习(11)

  • 直接存储器访问 DMA
    • 简介
    • 原理及框图
    • 寄存器
      • 中断状态寄存器 LISR HISR
      • 中断标志清零寄存器 LIFCR HIFCR
      • 数据流 x 配置寄存器 DMA_SxCR (x = 0..7)
      • 数据 x 数据项数寄存器
      • 数据流 x 外设地址寄存器 DMA_SxPAR (x = 0..7)
      • 数据流 x 存储器地址寄存器
      • 数据流 x FIFO 控制寄存器 SxFCR (x = 0..7)
  • 实验
    • DMA1 配置步骤
    • 代码
    • 实验结果

直接存储器访问 DMA

简介

直接存储器访问(Direct Memory Access,DMA)。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路, 能使 CPU 的效率大为提高。
STM32F4最多有 2 个 DMA 控制器( DMA1 和 DMA2), 共 16 个数据流(每个控制器 8 个), 每
一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8 个通道(或称请求)。每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。

特性1
特性2

原理及框图

框图
因为采用AHB主总线,DMA 可以控制 AHB 总线矩阵来启动 AHB 事务。它可以执行下列事务:

  1. 外设到存储器的传输
  2. 存储器到外设的传输
  3. 存储器到存储器的传输

这里特别注意一下,存储器到存储器需要外设接口可以访问存储器,而仅DMA2的外设接口可以访问存储器,所以仅DMA2控制器支持存储器到存储器的传输,DMA1不支持。

如图所示,经过通道选择和仲裁器,我们最多可以有8×8=64种组合。其中通道选择由下图所示。
通道选择
两个DMA的各个通道映射不一致,实验中我使用了USART3的发送,它在DMA1中,如下图:
DMA1

寄存器

中断状态寄存器 LISR HISR

分别管理8个通道的中断标志,两个寄存器是只读的。
ISR
ISR

中断标志清零寄存器 LIFCR HIFCR

由于ISR是只读的,需要采用其他方法清零,因此这里使用另两个中断标志清零寄存器,来对ISR的各位进行清除。

IFCR
IFSR

数据流 x 配置寄存器 DMA_SxCR (x = 0…7)

DMA_ SxCR 是 DMA 传输的核心控制寄存器。该寄存器控制着 DMA 的很多相关信息,包括数据宽度、外设及存储器的宽度、优先级、增量模式、传输方向、中断允许、使能等。
详情见官方文档。

SxCR

数据 x 数据项数寄存器

这个寄存器控制 DMA 数据流 x 的每次传输所要传输的数据量。其设置范围为 0~65535 。并且该寄存器的值会随着传输的进行而减少,当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。所以可以通过这个寄存器的值来知道当前 DMA 传输的进度。 特别注意,这里是数据项数目,而不是指的字节数。比如设置数据位宽为 16 位,那么传输一次(一个项)就是 2 个字节。

SxNDTR

数据流 x 外设地址寄存器 DMA_SxPAR (x = 0…7)

该寄存器用来存储 STM32F4 外设的地址。

数据流 x 存储器地址寄存器

包括 数据流 x 存储器 0 地址寄存器 DMA_SxM0AR数据流 x 存储器 1 地址寄存器 DMA_SxM1AR ,后者仅在双缓冲模式下有效。

数据流 x FIFO 控制寄存器 SxFCR (x = 0…7)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验

DMA1 配置步骤

  1. 使能 DMA1 时钟。另外,要对配置寄存器( DMA_SxCR )进行设置,必须先等待其最低位为 0 (也就是 DMA 传输禁止了),才可以进行配置。
  2. 创建 DMA_InitTypeDef 类型的结构体初始化 DMA1 数据流 3 (USART3_TX)。
  3. 使能串口 USART3 的 DMA 发送。USA RT_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
  4. 使能 DMA1 的 数据流3 。即 DMA_Cmd(DMA1_Stream3, ENABLE);
  5. 在DMA 传输过程中,查询 DMA 传输通道的状态,使用的函数有:
    是否传输完成:FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);
    当前剩余数据量:uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);
    设置数据流传输的数据量:void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);

代码

dma.c

/*函数名:配置DMA参数:DMAy_Streamx 选择数据流 DMA1_Stream0~7/DMA2_Stream0~7channelx 通道选择 DMA_Channel_0~7par 外设地址mar 存储器地址ndtr 数据传输量返回值:无
*/
void mydma_config(DMA_Stream_TypeDef *DMAy_Streamx, uint32_t channelx, uint32_t par, uint32_t mar, uint16_t ndtr)
{DMA_InitTypeDef DMA_InitStructure;//根据参数使能DMA1/DMA2时钟if((uint32_t)DMAy_Streamx > (uint32_t)DMA2){RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);}else {RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);}DMA_DeInit(DMAy_Streamx);//等待到可以配置while(DMA_GetCmdStatus(DMAy_Streamx) != DISABLE);DMA_InitStructure.DMA_BufferSize = ndtr; //数据量DMA_InitStructure.DMA_Channel = channelx; //DMA通道选择DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //FIFO禁止DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //FIFO阈值水平DMA_InitStructure.DMA_Memory0BaseAddr = mar; //存储器0地址基址DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器单词传输DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度8位DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //普通模式DMA_InitStructure.DMA_PeripheralBaseAddr = par; //外设地址DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设单次传输DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度8位DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级DMA_Init(DMAy_Streamx, &DMA_InitStructure);
}void mydma_enable(DMA_Stream_TypeDef *DMAy_Streamx, uint16_t ndtr)
{DMA_Cmd(DMAy_Streamx, DISABLE);while(DMA_GetCmdStatus(DMAy_Streamx) != DISABLE);DMA_SetCurrDataCounter(DMAy_Streamx, ndtr);DMA_Cmd(DMAy_Streamx, ENABLE);
}

main.c

#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "dma.h"#define SEND_BUF_SIZE 24000
uint8_t send_buf[SEND_BUF_SIZE];
const uint8_t send_str[] = "八个细胞 DMA 串口实验";int main(void)
{uint8_t t = 0, mask = 0;uint8_t len;uint16_t i;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2delay_init(168);		//延时初始化usart_init(); //串口初始化波特率为115200mydma_config(DMA1_Stream3, DMA_Channel_4, (uint32_t)&USART3->DR, (uint32_t)send_buf, SEND_BUF_SIZE);KEY_Init();LED_Init(); //初始化与LED连接的硬件接口len = sizeof(send_str);for(i=0; i < SEND_BUF_SIZE; i++) //填充 ASCII 字符集数据{if(t >= len) //加入换行符{if(mask){send_buf[i] = 0x0a;t=0;}else{send_buf[i] = 0x0d;mask++;}}else{mask = 0;send_buf[i] = send_str[t];t++;}}i = 0;mask = 0;while(1){t = KEY_Scan(0);if(t == KEY0_PRES){LED0 = 0;USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE); //使能串口 3 的 DMA 发送mydma_enable( DMA1_Stream3, SEND_BUF_SIZE); //开始一次 DMA 传输!while(1){if(DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) != RESET){DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);LED1 = 1;break;}mask++;delay_ms(10);if(mask == 20){LED1 = !LED1;mask = 0;}}}i++;delay_ms(10);if(i == 20){LED0 = !LED0;i = 0;}}
}

实验结果

当按下一次按钮0时,使能一次 DMA 发送到串口,发送期间 LED0 常亮,LED1 闪烁,非发送时间 LED0 闪烁,LED1 熄灭。
串口助手接收如下:
实验结果


http://www.ppmy.cn/news/601481.html

相关文章

STM32CubeMX + AD7606 + FSMC 使用FSMC完成对8080并口的数据读取

AD7606部分 AD7606是一款采样率最高200ksps、8通道、16位AD芯片&#xff0c;可使用8080并口、按字节并口、SPI串行等方式读取AD转换的原始数据。 实验时使用的是安富莱的AD7606模块。 各引脚的作用&#xff1a; OS2/OS1/OS2 : 组合状态选择过采样模式。 000表示无过采样&am…

16、STM32——DMA详解

1、DMA简介 DMA(Direct Memory Access) &#xff1a;直接存储器存取&#xff0c;是单片机的一个外设&#xff0c;它的主要功能是用来搬数据&#xff0c;但是不需要占用 CPU&#xff0c;即在传输数据的时候&#xff0c; CPU 可以干其他的事情&#xff0c;好像是多线程一样。数据…

stm32 DAC+DMA 输出100K正弦波杠杠的!!!

之前想用stm32的DAC输出正弦波&#xff0c;才用的方案是在死循环里面用for循环输出36点的电压值模拟成一个完整的正弦波。发现最多只能输出个20KHz的波形&#xff0c;在示波器下面能够看到明显的梯度。后来用DMAADC的模式发现可以上100K&#xff08;不过频率有点飘&#xff09;…

STM32 DMA详解

目录 1、综述 2、DMA事务 3、通道选择 4、仲裁器 5、DMA数据流 6、源、目标和传输模式 6.1、外设到存储器模式 6.2 存储器到外设模式 6.3 存储器到存储器模式 7、指针递增 8、循环模式 9、双缓冲模式 10、可编程数据宽度、封装/解封、字节顺序 11、单次传输和突发…

STM32:DMA

一、DMA简介&#xff1a; DMA&#xff0c;全称为&#xff1a;Direct Memory Access&#xff0c;即直接存储器访问。 DMA传输将数据从一个地址复制空间复制到另外一个地址空间&#xff0c;当CPU初始化这个传输动作之后&#xff0c;传输动作本身是由DMA控制器来实现和完成的。DM…

STM32 DAC+TIMER+DMA输出正弦波

前段时间学习了STM32使用DAC模块输出正弦波的功能&#xff0c;在学习过程中遇到了一些问题&#xff0c;在此和各位分享。 DAC是数字/模拟转换模块的简称&#xff0c;STM32中的DAC是12位数字输入&#xff0c;这个就决定了其精度。STM32的DAC模块具有两个通道&#xff0c;可单独进…

STM32F103ZET6:CubeMX配置FSMC接口驱动SSD1963-7寸 TFTLCD

配置方法 FSMC接口驱动SSD1963-7寸 TFTLCD 芯片&#xff1a;STM32F103ZET6 引脚&#xff1a; LCD_RS----PF0(FSMC_A0) LCD_CS----PG12(FSMC_NE4) LCD_WR----PD5(FSMC_NWE) LCD_RD----PD4(FSMC_NOE) 时钟&#xff1a;系统时钟配置为72M 操作&#xff1a;通过杜邦线将液晶屏连接…

STM32的DMA

文章目录 DMA介绍F407的DMA有多少数据流与通道&#xff1f;F407的DMA如何判定DMA请求的优先级&#xff1f; DMA框图F407的DMA源和目的的可选项&#xff1f;F407DMA的主要特性源与目的的方向配置DMA必要性仲裁器F407每个数据流对应请求映射 DMA结构DMA相关寄存器DMA 中断状态寄存…