历史上的今天
返回首页

历史上的今天

今天是:2025年03月28日(星期五)

正在发生

2020年03月28日 | stm32---DMA基础

2020-03-28 来源:eefocus

DMA,意思为直接存储器访问。


DMA 可 用于实现外设与存储器之间或者存储器与存储器之间数据高效传输。


因为 DMA 传输数据移动过程无需 CPU 直接操作,这样节省的 CPU 资 源就可供其它操作使用。


从硬件层面来理解,DMA 就好像是 RAM 与 I/O 设备间数 据传输的通路,外设与存储器之间或者存储器与存储器之间可以直接在这条通路 上进行数据传输。


这里说的外设一般指外设的数据寄存器,比如 ADC、SPI、I2C、 DCMI 等外设的数据寄存器,存储器一般是指片内 SRAM、外部存储器、片内 Flash 等。


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


DMA1通道对应外设请求


DMA2通道对应外设请求

DMA就像一个中转站一样,里面有源地址和目标地址,多通道并用可以配置优先级,

只要开启DMA就可以直接实现源地址里的内容传送给目标地址,不需要CPU来管理,它就像个通道一样,开启就传输。


dma.c


#include "dma.h"

 

/*******************************************************************************

* 函 数 名         : DMAx_Init

* 函数功能         : DMA初始化函数

* 输    入         : 

                     DMAy_Channelx:DMA通道选择,@ref DMA_channel DMA_Channel_0~DMA_Channel_7

                     par:外设地址

                     mar:存储器地址

                     buff_size:数据传输量

* 输    出         : 无

*******************************************************************************/ 

void DMAx_Init(DMA_Channel_TypeDef* DMA1_Channelx,u32 par,u32 mar,u16 buff_size)

{

    DMA_InitTypeDef DMA_InitStructure;

    

    //1*开启相应时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    

    //2*DMA结构体配置

    DMA_InitStructure.DMA_PeripheralBaseAddr = par;  //外设目标地址

    DMA_InitStructure.DMA_MemoryBaseAddr = mar;   //存储器源地址

    DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST ;  //方向是DMA存储器到外设寄存器。方向还有外设到存储器,存储器到存储器

    DMA_InitStructure.DMA_BufferSize = buff_size; //传输的字节数目

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设寄存器地址自递增,外设通常是一个不需要递增

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryInc_Enable;  //传输数据多字节时需要地址自增,实现开启就全部传输完

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA传输模式,单次传输

    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  //优先级配置,用于多通道时

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //存储器到存储器时打开

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度为1Byte,8位

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设接收数据长度为必须要存储器发送数据长度一样

    DMA_Init(DMA1_Channelx,&DMA_InitStructure);

    

}

 

/*******************************************************************************

* 函 数 名         : DMAx_Enable

* 函数功能         : 开启一次DMA传输

* 输    入         : DMAy_Channelx:DMA通道选择,@ref DMA_channel DMA_Channel_0~DMA_Channel_7

                     buff_size:数据传输量,传输时再赋值一遍防止出错

* 输    出         : 无

*******************************************************************************/ 

//3*开启DMA

void DMAx_ENABLE(DMA_Channel_TypeDef* DMA1_Channelx,u16 buff_size)

{

 

    DMA_Cmd(DMA1_Channelx,DISABLE);   //先关闭DMA使能来赋

    DMA_SetCurrDataCounter(DMA1_Channelx,buff_size);

    DMA_Cmd(DMA1_Channelx,ENABLE);

}

dma.h


#ifndef _dma_H

#define _dma_H

 

#include "system.h"

 

 

void DMAx_Init(DMA_Channel_TypeDef* DMA1_Channelx,u32 par,u32 mar,u16 buff_size);

 

void DMAx_ENABLE(DMA_Channel_TypeDef* DMA1_Channelx,u16 buff_size); 

 

 

#endif

 

main.c


#include "systick.h"

#include "led.h"

#include "system.h"

#include "key.h"

#include "usart.h"

#include "dma.h"

 

#define data_size 5000

u8 data[data_size];

 

//数组赋值专用函数

void Data_zhuang(u8 *p)

{

    u16 i;

    for(i=0;i    {

        *p = '5';

        p++;

 

    }

}


int main()

{

    u8 i=0;

    u8 key;

    

    SysTick_Init(72);  //系统时钟初始

    LED_INIT(); 

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 

    USART1_Init(9600);

    KEY_INIT();

    

    Data_zhuang(data); //给数组赋值

    DMAx_Init(DMA1_Channel4,(u32)&USART1->DR,(u32)data,data_size); //DMA初始化,(u32)&USART1->DR是串口1的数据寄存器,(u32)data是我们在内存中造的数组

    

    while(1)

    { 

        key = KEY_Scan(0);

        if(key==KEY_UP)

        {

            USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //是哪个外设就开启哪个的DMA功能

            DMAx_ENABLE(DMA1_Channel4,data_size);  //使能DMA

            

            while(1)

            {

                if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==1) //判断DMA1的通道4是否传输完成

                {

                    DMA_ClearFlag(DMA1_FLAG_TC4);  //清除传输完成标志

                    break;

                }

                led2=!led2;

                delay_ms(300);

            }   

        }

    

        i++;

        if(i%20==0) //200ms变换一次

        {

            led1=!led1;

        }

    

    }

}

上一篇:stm32---DS18b20

下一篇:stm32---DAC

推荐阅读

史海拾趣

AC Interface Inc公司的发展小趣事

随着全球环保意识的增强,ABC Electronics Inc. 敏锐地捕捉到了绿色电子产品的市场潜力。公司开始研发和生产符合环保标准的产品,如低能耗的LED照明产品、可循环利用的电池等。同时,公司还优化了生产工艺,减少了生产过程中的环境污染。这些环保举措不仅赢得了消费者的青睐,也提升了公司的社会形象。

Fukushima Futaba Electric Co Ltd公司的发展小趣事

近年来,全球电子行业面临着诸多挑战,包括技术更新换代迅速、市场竞争加剧等。Futaba Electric积极应对这些挑战,不断加大研发投入,推出了一系列具有创新性和竞争力的新产品。同时,公司还注重与上下游产业链的合作与协同,通过整合资源、优化流程等方式降低成本、提高效率。此外,Futaba Electric还积极响应环保政策,推动绿色制造和可持续发展。这些努力使得公司在面对挑战时依然能够保持稳健的发展态势。

岑科(CENKER)公司的发展小趣事

岑科公司成立于2001年,初期主要从事电子元器件的贸易业务。在创始人蔡旌章的带领下,岑科以优质的服务和灵活的运营策略,在国内外市场上赢得了良好的口碑。这一时期,岑科的服务对象主要是海内外的电子元器件需求商,通过精准把握市场需求和优质的产品供应,逐渐在电子元器件贸易领域站稳了脚跟。随着业务的不断拓展,岑科开始思考如何进一步提升自身的竞争力,以实现更长远的发展。

APLUS Products公司的发展小趣事

在XXXX年,APLUS Products公司迎来了一次重要的技术突破。公司研发团队成功开发出了一款具有划时代意义的电子产品,该产品在性能、稳定性和用户体验等方面均达到了行业领先水平。这一技术突破不仅为公司赢得了大量订单,还进一步巩固了其在电子行业中的市场地位。

功得(CONQUER)公司的发展小趣事

为了保持在行业中的领先地位,功得公司不断加大技术研发投入。他们与多所高校和科研机构建立合作关系,共同开展前沿技术研究。在这些合作中,功得公司取得了一系列技术突破,推出了一系列具有行业领先水平的新产品。这些技术成果不仅提升了公司的核心竞争力,也为整个电子行业的发展做出了贡献。

Advanced Illumination Inc公司的发展小趣事

在成功开发出优质产品后,Ai公司开始积极拓展市场。公司通过参加各种行业展会、举办技术研讨会等方式,与潜在客户进行深入交流,成功将产品推广至全球范围。同时,公司还注重品牌建设,通过广告宣传、媒体报道等手段提升品牌知名度和美誉度。这些举措使得Ai公司的产品在市场上获得了广泛的认可。

问答坊 | AI 解惑

电容漏泄的测量

电容器是几乎所有电气设备上都会用到的主要器件。漏阻是电容器被测试的众多电气特征中的一个。漏阻通常被称为“IR”(Insulation Resistance,绝缘电阻),以“兆欧-微法”表示。在其它情况下,漏泄可能被表示为特定电压(通常为工作电压)下的漏 ...…

查看全部问答>

请教代替3sk318的双栅管

本帖最后由 jameswangsynnex 于 2015-3-3 19:56 编辑 请教各位高手,什么型号的双栅管可以代替3SK318(能直接替换最好) 谢谢! …

查看全部问答>

电动车跷跷板【F题,二等奖】

本帖最后由 paulhyde 于 2014-9-15 09:04 编辑 电动车跷跷板~~~~~~~~  …

查看全部问答>

2440 读 温度芯片,总是无法触发中断,请教有什么方法呀?

BSP包里通过应用层调用IIC文件夹不能正常工作,只好转入到bootloader层去做温度检测了,可是无论如何也不能触发中断,有经验的请指教,先谢谢了。…

查看全部问答>

谁有基于单片机数字电流表的设计报告?

只要电路原理图和c源程序。小弟在这拜谢了! 或者谁能帮我改下这电压表的程序成电流表的程序: #include    unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,0xf7,             &nbs ...…

查看全部问答>

Pci 网卡驱动

现在要开始搞pci网卡驱动想从Realtek 8139这个入手, 个位有甚么好的建议 linux device driver有個pci_skel框架, 不知道怎麼楊. …

查看全部问答>

深入浅出玩转 FPGA 特权同学的 书

深入浅出玩转 FPGA  特权同学的 书   大家东清楚,不用我介绍了吧!…

查看全部问答>

【号外】STM32F101也有USB

刚做的东西给几个小MM去贴片,把101当103贴上去了,居然USB也可以联机。但操作偶尔有问题,手工复位一般可以解决掉。听小道消息说,101是阉割的103,就像奔腾的cache有瑕疵变成赛扬一样。…

查看全部问答>

分享-最好用的串口终端

Bray++同志写的,俺用了好多年。这是最新版。 Terminal.rar (278.15 KB) 下载次数:190 2010-10-13 20:16 …

查看全部问答>

请教,这个I/O子程序是什么意思?

使能I/O口子程序,在CCS帮助文件中看到对该子程序 GPIO_Handle GPIO_open(   int chaNum,   Uint32 flags ); 的解释是: chaNum        GPIO channel to open: lags     & ...…

查看全部问答>