STM32 DMA模块的配置与使用

发布者:andyliow1980最新更新时间:2016-12-27 来源: eefocus关键字:STM32  DMA模块  配置与使用 手机看文章 扫描二维码
随时随地手机看文章

DMA有什么用?

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

有多少个DMA资源?

       有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。

数据从什么地方送到什么地方?

       外设到SRAM(I2C/UART等获取数据并送入SRAM);

       SRAM的两个区域之间;

       外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比);

       SRAM到外设(SRAM中预先保存的数据送入DAC产生各种波形);

       ……还有一些目前还搞不清楚的。

DMA可以传递多少数据?

       传统的DMA的概念是用于大批量数据的传输,但是我理解,在STM32中,它的概念被扩展了,也许更多的时候快速是其应用的重点。数据可以从1~65535个。

直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道 CPU。在同等程度的CPU负担下,DMA是一种快速的数据传送方式。它允许不同速度的硬件装置来沟通,而不需要依于 CPU的大量中断请求。【摘自Wikipedia】

现在越来越多的单片机采用DMA技术,提供外设和存储器之间或者存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。STM32就有一个DMA控制器,它有7个通道,每个通道专门用来管理一个或多个外设对存储器访问的请求,还有一个仲裁器来协调各个DMA请求的优先权。

DMA 控制器和Cortex-M3核共享系统数据总线执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求可能会停止 CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。

在发生一个事件后,外设发送一个请求信号到DMA控制器。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问外设的时候,DMA控制器立即发送给外设一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果发生更多的请求时,外设可以启动下次处理。

简单来说:

DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM 与I/O设备开辟一条直接传送数据的通路,能使CPU 的效率大为提高。

       STM32中 DMA1有7个通道,DMA2有5个通道(DMA2 仅存在大容量产品中)。DMA挂载的时钟为AHB总线,其时钟为72Mhz,所以可以实现高速数据搬运。
       STM32F103RBT6 只有1 个DMA控制器,DMA1 ,下面我们就针对DMA1 进行介绍。
       从外设(TIMx、ADC、SPIx 、I2Cx 和USARTx )产生的DMA请求,通过逻辑或输入到DMA控制器,这就意味着同时只能有一个请求有效。外设的DMA请求,可以通过设置相应的外设寄存器中的控制位,被独立地开启或关闭。

       DMA1各通道一览:

这里我们要使用的是串口 1 的 DMA 传送,也就是要用到通道 4。

 

1、DMA的配置

要配置的有DMA传输通道选择,传输的成员和方向、普通模式还是循环模式等等。

void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    //DMA设置:
    //设置DMA源:内存地址&串口数据寄存器地址
    //方向:内存-->外设
    //每次传输位:8bit
    //传输大小DMA_BufferSize=SENDBUFF_SIZE
    //地址自增模式:外设地址不增,内存地址自增1
    //DMA模式:一次传输,非循环
    //优先级:中
    DMA_DeInit(DMA1_Channel4);//串口1的DMA传输通道是通道4
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设作为DMA的目的端
    DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//传输大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不增加
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址自增1
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

    //DMA_Mode_Normal(只传送一次), DMA_Mode_Circular (不停地传送)
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//(DMA传送优先级为中等)
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}

注:

1、传输通道:通过查表,串口1的发送对应的是DMA的通道4,所以此处选择通道4.

2、DMA传输方式:

(1) DMA_Mode_Normal,正常模式,当一次DMA数据传输完后,停止DMA传送,对于上例而言,就是DMA_PeripheralDataSize_Byte个字节的传送完成后,就停止传送。

(2) DMA_Mode_Circular

循环模式,当传输完一次后,重新接着传送,永不停息。

2、外设的DMA方式设置

将串口1设置成DMA模式:

每一个外设都有一个类似以下的一个DMA调用函数:xxx_DMACmd();

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//发送就为USART_DMAReq_Tx;读取就为USART_DMAReq_Rx

3、待传输数据的定义和初始化

#define SENDBUFF_SIZE   10240
vu8 SendBuff[SENDBUFF_SIZE];

    for(i=0;i    {
        SendBuff[i] = i%10+'0';
    }
4、开始DMA传输(使能对应的DMA通道)
DMA_Cmd(DMA1_Channel4, ENABLE);

5、DMA传输的完成

 while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)
 {
       LED_1_REV;      //LED翻转
       Delay();        //浪费时间
 }

当传输完成后,就会跳出上面的死循环。

 

当然,使用串口作为外设的时候,还需要对串口进行初始化。


关键字:STM32  DMA模块  配置与使用 引用地址:STM32 DMA模块的配置与使用

上一篇:使用USART接口进行STM32F0的在线升级
下一篇:STM32之独立看门狗与窗口看门狗总结

推荐阅读最新更新时间:2024-03-16 15:27

单片机串口处理获得的经验(stm32
最近搞了一个stm32串口数据帧批处理代码,遇到了很多问题,作为刚工作的我,经验太缺乏,实在是需要总结一番,以避免以后再出现同样的错误。 大致情况罗列如下: 1、串口接收中断处理 在学校的时候根本没有接触过什么循环处理的方法,到现在我也讲不上来这个方法的名字是什么,反正自己会运用了。大致的情况是环形数组处理,代码如下: //====================== 接收数据中断 if( USART_GetITStatus( COM_USARTx, USART_IT_RXNE ) != RESET ) { if( COM_Rx_Sign == 1 )
[单片机]
stm32定时器外部时钟3使用外部时钟源模式2进行定时的步骤
stm32中的通用定时器的计数时钟有三种,内部时钟、外部时钟源、内部触发输入这三种,其中内部时钟是大家都比较常用的,也是在应用中比较多的,我们现在主要来讲一下外部时钟源的模式2外部时钟模式2:外部触发输入。 编程步骤: 配置TIM3_ETR引脚为输入引脚PD2,硬件上需要将脉冲连接到该引脚,我这里是使用6.78MHz的晶振 配置定时器3:包括使能定时器3对应的时钟引脚,配置定时器3的周期、预分频参数 因为我们使用了定时器3中断,所以需要给定时器设置优先级,在timerx_nvic_init()中的关于TIM3部分操作 将SMCR中的ETF、ETPS、ETP和ECE进行配置 执行完了以上步骤之后还需要操作triggle中断
[单片机]
(五)stm32工程代码HardFault异常查错调试方法
一、导致异常的原因很多,例如:直接使用未分配空间的指针、栈溢出等一场非法操作便会使程序进入HardFault异常状态。下面介绍怎么找出程序中的异常。 接下来在keil_MDK工程中,编译代码,并debug,之后全速运行,可以看到如下图所示程序进入HardFault异常。 如下所示我们找到SP寄存器,0x200045B8即为栈地址,栈里面的值依次为R0~R3、R12、PC(Return address)、xPSR(CPSR或SPSR)、LR。如图我们看到划红线的地方,注意从右往左看。分别为0x0800427D和0x08004BFA。 在show code at address中输入0x08004BFA,点击go to即找
[单片机]
(五)<font color='red'>stm32</font>工程代码HardFault异常查错调试方法
STM32配置多个定时器同时为光电编码模式的注意事项
我在做一个小车项目中使用STM32f103中的3个定时器同时配置为编码器模式是出现的一个问题,作为一个STM32的入门者在使用编码器模式时可能出现这样的情况:按照网上的一些程序配置一个定时器为编码器模式时不会出现大问题,但是当你用同样的配置程序,同时去配置多个定时器为编码器模式是就会出现有些编码器不能计数。其实很多网上的程序都只是把定时器的配置程序提供给你,而没有把相关的中断配置程序放上去,如果你是一名初学者可能不会发现,就可能会出现上面的问题。
[单片机]
STM32单片机中FLASH空间的分配之bootloader
根据程序运行流程: 正常的程序启动流程:从FLASH启动时,首先从闪存的物理地址入口0x08000000进入,然后是复位中断跳转到复位中断服务程序;复位中断服务程序执行完成后,再跳转到main函数入口,main函数一般为死循环;当外部中断发生时,跳转到中断向量查找表,通过查找表找到对应的中断服务程序地址,跳转到对应的中断服务程序;中断服务程序结束后再次跳转到main函数,这样不断的循环,这是我们的应用程序段; 当需要进行系统升级的时候,则需要在这个过程中添加一个bootloader程序段; 那么bootloader程序段存在什么位置呢? 一般是低地址区域存放bootloader程序段,紧接着的高地址区域存放应用程序段; 那么b
[单片机]
意法半导体推出STM32互连型系列微控制器
      2009年3月11日,微控制器IC全球领先供应商意法半导体(纽约证券交易所代码:STM)推出一全新系列的STM32微控制器,新产品以片上集成各种高性能工业标准接口为主打特色,且STM32不同型号产品在引脚和软件上具有完美的兼容性,这将让更多的应用从中受益。       全新STM32互连型(Connectivity)系列微控制器增加一个全速USB(OTG)接口,使终端产品在连接另一个USB设备时既可以充当USB主机又可充当USB从机;还增加一个硬件支持IEEE1588精确时间协议(PTP)的以太网接口,用硬件实现这个协议可降低CPU开销,提高实时应用和联网设备同步通信的响应速度。       全新互连型系列还是
[半导体设计/制造]
STM32 Flash详解
本文将根据ST官方Flashprogramming manual,文档编号:PM0059,讲解STM32F207内部Flash编程。 01、概述 这里的flash是指STM32F207内部集成的Flash Flash存储器有以下特点 最大1M字节的能力 128位,也就是16字节宽度的数据读取 字节,半字,字和双字写入 扇区擦除和批量擦除 存储器的构成 主要存储区块包含4个16K字节扇区,1个64K字节扇区和7个128K字节扇区。 系统存储器是用于在系统boot模式启动设备的。这一块是预留给ST的。包括bootloader程序,boot程序用于通过以下接口对Flash进行编程。USART1、USART3、CAN2、
[单片机]
<font color='red'>STM32</font> Flash详解
STM32启动文件分析——startup_stm32f10x_hd.s
一、启动文件的作用 (关于启动代码的作用,前面已经提到过了,这里再啰嗦一下) (1)初始化堆栈指针 SP; (2)初始化程序计数器指针 PC; (3)设置堆、栈的大小; (4)设置异常向量表的入口地址; (5)配置外部 SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部 SRAM); (6)设置 C库的分支入口__main(最终用来调用 main函数); (7)在 3.5版的启动文件还调用了在 system_stm32f10x.c文件中的SystemIni()函数配置系统时钟。 二、启动文件中提到的汇编指令 指令 作用 EQU 给数字常量取一个符号名,相当于 C 语言中的
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved