首页 > 其他分享 >DMA——STM32F407ZGT6

DMA——STM32F407ZGT6

时间:2024-09-04 20:22:34浏览次数:14  
标签:DMA STM32F407ZGT6 存储器 FIFO 传输 InitStructure 外设

DMA简介

DMA(Direct Memory Access)直接存储器存取

DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源。

DMA的作用就是解决大量数据转移过度消耗CPU资源的问题,有了DMA得CPU可以更加专注的实用的的操作——计算、控制等。外围设备可以通过DMA控制器直接访问内存,与此同时,CPU可以继续执行程序。DMA传输期间,DMA控制器接管了总线的控制权。在DMA传输结束后,DMA控制器将总线的控制权交给CPU。通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。(CPU控制DMA开启、关闭)

附:存储器映像

STM32F407的DMA

        STM32的两个 DMA 控制器总共有 16 个数据流(每个控制器 8 个通道),每一个 DMA 控制器都用于管理 一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8 个通道(或称请求)。每个通道都有一个仲裁器,用于处理 DMA 请求间的优先级。

        每个通道都支持软件触发(存储器到存储器)和特定的硬件触发(存储器到外设,触发一次转运一次)

DMA 的数据传输方向方式共有四种:

1.外设到内存

2.内存到外设

3.内存到内存

4.外设到外设(保留模式,基本不用)

DMA控制器提供两个 AHB 主端口:AHB 存储器端口(用于连接存储器)和 AHB 外设端口 (用于连接外设)。但是,要执行存储器到存储器的传输,AHB 外设端口必须也能访问存储器。

但需要注意的是,只有DMA2能够实现内存到内存的传输。

DMA基本结构

DMA请求

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

数据宽度与对齐

数据转运+DMA

ADC扫描模式+DMA

通道选择

DMA1和DMA2均有8个数据流,每个数据流都与一个 DMA 请求相关联,此 DMA 请求可以从 8 个可能的通道请求中选出。 每个通道都有一个仲裁器,用于处理DMA 请求间的优先级。此选择由 DMA_SxCR 寄存器中的 CHSEL[2:0] 位控制。

下面为DMA1和DMA2的请求映射关系:

仲裁器

仲裁器为两个 AHB 主端口(存储器和外设端口)提供基于请求优先级的 8 个 DMA 数据流请 求管理,并启动外设/存储器访问序列。

优先级管理分为软件和硬件,软件部分由数据流的优先级(DMA_SxCR寄存器种)决定,硬件部分由流的编号决定,机制类似中断硬件编号。

FIFO直接模式和阈值突发模式

1.直接模式(禁止FIFO):不使用FIFO 的阈值级别控制。每完成一次从外设到FIFO 的数据传输后,相应的数据立即就会移出并存储到目标中。

注:存储器到存储器传输时不得使用直接模式

2.FIFO阈值突发模式:在此模式下,每次产生外设请求.数据流都会启动数据源到FIFO的传输。达到FIFO的阈值级别时,FIFO的内容移出并存储到目标中。

  FIFO用于在源数据传输到目标之前临时存储这些数据。每个数据流都有一个独立的(总容量16字节)FIFO,FIFO临时存储数据最多为16字节,FIFO的存储阈值级别可由软件配置为1/4(4字节)、1/2(8字节)、3/4(12字节)或满(16字节)。

DMA传输模式

DMA传输方向使用 DMA_SxCR 寄存器中的 DIR[1:0] 位进行配置,有三种可能的传输方向:存储器到外设、外设到存储器或存储器到存储器。

以存储器到外设模式为例,框图如下:

  1. 在此模式下数据流会立即启动传输,从数据源完全填充FIFO。每次发生外设请求,FIFO 的内容都会移出并存储到目标中。当 FIFO 的级别小于或等于预定义的阈值级别时,将使用存储器中的数据完全重载 FIFO。

  2. 如果传输完成或外设请求停止传输或软件关闭通道,传输会立即停止。

  3. 直接模式下,使能了数据流,DMA 便会预装载第一个数据,将其传输到内部 FIFO。一旦外设请 求数据传输,DMA 便会将预装载的值传输到配置的目标。每次传输都会将数据先装载至内部FIFO。

  4. 预装载的数据大小为 DMA_SxCR 寄存器中 PSIZE 位字段的值。

  5. 数据流在经过仲裁后才可以访问源或目标端口

指针递增

外设和存储器指针在每次传输后可以自动向后递增或保持常量。

如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1(对于字节)、2(对于半字)或 4(对于字)。

单个寄存器访问外设源或目标数据时,禁止递增模式

普通模式与循环模式

普通模式:DMA搬运了设定长度的数据后,CNDTR清0,会产生中断标志,然后DMA就停止工作了,如果再有数据也不接收了。需关断 DMA 使能后再重新配置后才能继续传输。

循环模式: DMA搬运了设定长度的数据后,CNDTR清0,会产生中断标志,如果再有数据,DMA会循环保存到内存中,覆盖前面的数据。在CNDTR=0时DMA会自动装载初始化时的配置,CNDTR重置为初始值。

代码

1.DMA.c

#include "DMA.h"
#include "stm32f4xx.h"


uint8_t data[4] = {0x01,0x02,0x03,0x04};
u16 MyDMA_size;

void dma_usart_init()
{
    DMA_InitTypeDef DMA_InitStructure;    
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
   
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;  //串口对应的通道4
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;      //串口地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)data;                        //内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                          //内存到外设    
    DMA_InitStructure.DMA_BufferSize = 4;                                                         //传输数据大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设非增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                            //内存增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度1字节
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                    //内存数据长度1字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                             //普通模式    
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                //中等优先级
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;                            //不使用FIFO
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;             //满缓冲
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                    //内存单节拍存储
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    //外设单节拍存储
    
    //DMA_DeInit(DMA2_Stream7);//复位,清除FIFO缓冲区里的数据
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);
    
    DMA_Cmd(DMA2_Stream7, ENABLE);
}


void dma_usart_start()
{
    //1.去使能关闭传输
    DMA_Cmd(DMA2_Stream7, DISABLE);
    
    //2.确保可以正常工作
    while(DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)
        
    //3.开始数据传输
    DMA_SetCurrDataCounter(DMA2_Stream7, MyDMA_size);
        
    //4.使能
    DMA_Cmd(DMA2_Stream7, ENABLE);

    //判断传输是否完成
    if(DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) == SET)
    {
        DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);//清空标志位
    }
    
}

2.DMA.h

#ifndef _DMA_H
#define _DMA_H
#include "stm32f4xx.h"
void dma_usart_init(void);
void dma_usart_start(void);
#endif

3.main.c

int main(void)
{

    uint8_t data[8] = {1,2,3,4,5,6,7,8};
    uint8_t databuf[8];
    SysTick_Init();
    
    USART_Init_Config();
    
    dma_usart_init();
    
    USART_DMACmd(USART1,USART_DMAReq_Tx, ENABLE);
    
    while(1)
    {
        dma_usart_start();
        //printf("\r\n");
        Delay_ms(1000);
    }    
}

串口效果

标签:DMA,STM32F407ZGT6,存储器,FIFO,传输,InitStructure,外设
From: https://blog.csdn.net/luckyluckypolar/article/details/141902619

相关文章

  • 解决podman: ERRO[0000] running newuidmap: write to uid_map failed: Invalid argum
    报错ERRO[0000]running/usr/bin/newuidmap27115520100011100000655366553710000065537:newuidmap:writetouid_mapfailed:InvalidargumentError:cannotsetupnamespaceusing"/usr/bin/newuidmap":shouldhavesetuidorhavefilecapssetu......
  • 流式dma和一致性dma的区别
    流式DMA(StreamingDMA)和一致性DMA(ConsistentDMA)是两种不同的内存映射模式,用于DMA(直接内存访问)操作。它们的主要区别在于缓存一致性、性能和使用场景。以下是这两者的详细区别:1.流式DMA(StreamingDMA)缓存一致性:流式DMA不保证缓存的一致性。在进行DMA操作前,需要显式......
  • 局域网通信时,解决在一些设备上NsdManager发现服务失败的问题
    1.背景:Google提供了NsdManagerApi以支持局域网发现服务,但是在实际中,一些个别型号手机设备上,NsdManager发现服务失败,mdns解析失败,找不到对应的服务名称,进而无法解析出本地网络内的host和端口。可能存在的问题原因:1.1设备兼容性问题硬件限制:一些低端或较老的设备可......
  • 启动应用程序出现SebBackgroundManagerPolicy.dll找不到问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个SebBackgroundManagerPolicy.dll文件(挑选合......
  • 三、STM32F103标准库DMA+USART接收不定长数据
    项目中常用到串口通信,当需要使用串口中断接不定长数据时,可以参考以下示例:本实例使用DMA+USART空闲中断来进行不定长数据接受,在数据接收完成后将数据透传。结果将通过另一个串口信息显示。1、主函数配置#include"stm32f10x.h"#include"printfsupport.h"#include"usar......
  • 八、2 DMA数据转运 DMA函数介绍
    把数组定义在Flash中,可以节省SRAM的空间去掉const不会影响程序运行,但会占用SRAM的空间1、步骤(1)RCC开启DMAD的时钟(2)调用DMA_Init,初始化参数(3)调用DMA_Cmd,通道使能若使用硬件触发,要调用×××_DMACmd开启对应外设的触发信号的输出;若需要DMA的中断,就调用DMA_ITConfig,开......
  • 【STM32 Blue Pill编程】-UART数据发送与接收(DMA模式)
    UART数据发送与接收(DMA模式)文章目录UART数据发送与接收(DMA模式)1、DMA介绍2、STM32的UART端口3、硬件准备及接线4、UART配置5、代码实现在本文中,我们将展示如何使用STM32BluePillUART通过直接内存访问(DMA)来发送和接收数据。这一过程而无需涉及CPU。......
  • 基于STM32F407ZGT6用BH1750在OLED显示屏上显示光照数据,根据光照强度控制小灯亮灭(路灯
    占空比:高电平占整个电平周期的持续时长,从而控制小灯的亮度,小灯亮度的控制需用定时器的输出比较功能。PWM部分可以参考这篇文章PWM——基于STM32F407ZGT6开发板-CSDN博客此外我们还需要了解IIC的工作原理1.pwm.c   #include"public.h"/*pwm控制led实现呼吸灯1.......
  • 探索未来家居,3DMAX室内设计实战精英班
    ✨【空间魔术师,等你来变身!】✨你是否渴望用设计改变世界,让冰冷的房间焕发生机?3DMAX室内设计实战研修班,是你通往梦想设计殿堂的钥匙。......
  • STM32F4 timer定时器触发ADC采集,DMA转运数据 (标准库)
    硬件平台:STM32F401RCT6项目需求:需要实现100hzADC采集用于FFT频谱分析,同时要支持切换采集通道,每次采集之前改变数据存储地址与buff长度直接说配置过程的重点在DMA和ADC初始化之后,要处于disable状态,每次采集之前enable。如果一开始处于enable状态,没有采集,执行了disable再enabl......