datasheet

STM32学习笔记一一DMA传输

2019-01-09来源: eefocus 关键字:STM32  DMA传输

1.简介

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


STM32 最多有 2 个 DMA 控制器(DMA2 仅存在大容量产品中), DMA1 有 7 个通道。 DMA2 有 5个通道。每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁起来协调各个 DMA 请求的优先权。


2.STM32 DMA特性

●每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。这些功能通过软件来配置。


●在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相等优先权时由硬件决定(请求 0 优先于请求 1,依此类推) 。


●独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程,源和目标地址必须按数据传输宽度对齐。


●支持循环的缓冲器管理


●每个通道都有 3 个事件标志(DMA 半传输, DMA 传输完成和 DMA 传输出错),这 3 个事件标志逻辑或成为一个单独的中断请求。


●存储器和存储器间的传输


●外设和存储器,存储器和外设的传输


●闪存、 SRAM、外设的 SRAM、 APB1 APB2 和 AHB 外设均可作为访问的源和目标。


●可编程的数据传输数目:最大为 65536


从外设(TIMx、 ADC、 SPIx、 I2Cx 和 USARTx)产生的 DMA 请求,通过逻辑或输入到 

DMA 控制器,这就意味着同时只能有一个请求有效。外设的 DMA 请求,可以通过设置相应的 

外设寄存器中的控制位,被独立地开启或关闭。



3.相关寄存器

DMA 中断状态寄存器(DMA_ISR)

 

如果开启了 DMA_ISR 中这些中断,在达到条件后就会跳到中断服务函数里面去,即使没开启,我们也可以通过查询这些位来获得当前 DMA 传输的状态。这里我们常用的是 TCIFx,即通道 DMA 传输完成与否的标志。注意此寄存器为只读寄存器,所以在这些位被置位之后,只能通过其他的操作来清除。


DMA 中断标志清除寄存器(DMA_IFCR)


该寄存器的各位描述如下图:



DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 1 清除。在 DMA_ISR 被置位后,我们必须通过向该位寄存器对应的位写入 1 来清除。


DMA 通道 x 配置寄存器(DMA_CCRx)(x=1~7)


该寄存器控制着 DMA 的很多相关信息,包括数据宽度、外设及存储器的宽度、通道优先级、增量模式、传输方向、中断允许、使能等都是通过该寄存器来设置的。所以 DMA_CCRx 是 DMA 传输的核心控制寄存器。




DMA 通道 x 传输数据量寄存器(DMA_CNDTRx)


这个寄存器控制 DMA 通道 x 的每次传输所要传输的数据量。其设置范围为 0~65535。并且该寄存器的值会随着传输的进行而减少,当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。所以可以通过这个寄存器的值来知道当前 DMA 传输的进度。


DMA 通道 x 的外设地址寄存器(DMA_CPARx)


该寄存器用来存储 STM32 外设的地址,比如我们使用串口 1,那么该寄存器必须写入 0x40013804(其实就是&USART1_DR)。如果使用其他外设,就修改成相应外设的地址就行了。


DMA 通道 x 的存储器地址寄存器(DMA_CMARx) 

该寄存器和 DMA_CPARx 差不多,但是是用来放存储器的地址的。比如我们使用SendBuf[5200]数组来做存储器,那么我们在DMA_CMARx 中写入&SendBuff 就可以了。


4.库函数下 DMA1 通道 4 的配置步骤

(1)使能 DMA 时钟


RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟


(2) 初始化 DMA 通道 4 参数


DMA 通道配置参数种类比较繁多,包括内存地址,外设地址,传输数据长度,数据宽度,通道优先级等等。这些参数的配置在库函数中都是在函数 DMA_Init 中完成.


函数定义:


void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,DMA_InitTypeDef* DMA_InitStruct)


第一个参数:指定初始化的 DMA 通道号; 

第二个参数: 跟其他外设一样,同样是通过初始化结构体成员变量值来达到初始化的目的。


DMA_InitTypeDef 结构体的定义:


typedef struct

        {

        uint32_t DMA_PeripheralBaseAddr;

        uint32_t DMA_MemoryBaseAddr;

        uint32_t DMA_DIR;

        uint32_t DMA_BufferSize;

        uint32_t DMA_PeripheralInc;

        uint32_t DMA_MemoryInc;

        uint32_t DMA_PeripheralDataSize;

        uint32_t DMA_MemoryDataSize;

        uint32_t DMA_Mode;

        uint32_t DMA_Priority;

        uint32_t DMA_M2M;

        }DMA_InitTypeDef;


第一个参数 :DMA_PeripheralBaseAddr 用来设置 DMA 传输的外设基地址,比如要进行串口 DMA 传输,那么外设基地址为串口接受发送数据存储器 USART1->DR 的地址,表示方法为 

&USART1->DR。


第二个参数 :DMA_MemoryBaseAddr为内存基地址,也就是我们存放 DMA传输数据的内存地址。


第三个参数: DMA_DIR 设置数据传输方向,决定是从外设读取数据到内存还送从内存读取数据发送到外设,也就是外设是源地还是目的地,这里我们设置为从内存读取数据发送到串口, 

所以外设自然就是目的地了,所以选择值为 DMA_DIR_PeripheralDST。


第四个参数: DMA_BufferSize 设置一次传输数据量的大小。


第五个参数 :DMA_PeripheralInc 设置传输数据的时候外设地址是不变还是递增。如果设置 

为递增,那么下一次传输的时候地址加 1,这里因为我们是一直往固定外设地址&USART1->DR 

发送数据,所以地址不递增,值为 DMA_PeripheralInc_Disable;


第六个参数 :DMA_MemoryInc 设置传输数据时候内存地址是否递增。 这个参数和 

DMA_PeripheralInc 意思接近,只不过针对的是内存。这里我们的场景是将内存中连续存储单 

元的数据发送到串口,毫无疑问内存地址是需要递增的,所以值为 DMA_MemoryInc_Enable。


第七个参数 :DMA_PeripheralDataSize 用来设置外设的的数据长度是为字节传输(8bits),半字传输 (16bits)还是字传输 (32bits),这里我们是 8 位字节传输,所以值设置为DMA_PeripheralDataSize_Byte。


第八个参数 :DMA_MemoryDataSize 是用来设置内存的数据长度,和第七个参数意思接近,这里我们同样设置为字节传输 DMA_MemoryDataSize_Byte。


第九个参数: DMA_Mode 用来设置 DMA 模式是否循环采集,也就是说,比如我们要从内存中采集 64 个字节发送到串口,如果设置为重复采集,那么它会在 64 个字节采集完成之后继续从内存的第一个地址采集,如此循环。这里我们设置为一次连续采集完成之后不循环。所以设置值为 DMA_Mode_Normal。在我们下面的实验中,如果设置此参数为循环采集,那么你会看到串口不停的打印数据,不会中断。


第十个参数:是设置 DMA 通道的优先级,有低,中,高,超高三种模式,这里设置优先级别为中级,所以值为 DMA_Priority_Medium。如果要开启多个通道,那么这个值就非常有意义。


第 十 一 个 参 数 :DMA_M2M 设 置 是 否 是 存 储 器 到 存 储 器 模 式 传 输 , 这 里 我 们 选 择DMA_M2M_Disable。


(3)使能串口 DMA 发送


进行 DMA 配置之后,我们就要开启串口的 DMA 发送功能,使用的函数是:


USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);


如果是要使能串口 DMA 接受,那么第二个参数修改为 USART_DMAReq_Rx 即可。


(4)使能 DMA1 通道 4,启动传输。


使能串口 DMA 发送之后,我们接着就要使能 DMA 传输通道:


DMA_Cmd(DMA_CHx, ENABLE);


通过以上 3 步设置,我们就可以启动一次 USART1 的 DMA 传输了。


(5)查询 DMA 传输状态


在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是:


FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)


比如我们要查询 DMA 通道 4 传输是否完成,方法是:


DMA_GetFlagStatus(DMA2_FLAG_TC4);


这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:


uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)


比如我们要获取 DMA 通道 4 还有多少个数据没有传输,方法是:


DMA_GetCurrDataCounter(DMA1_Channel4);


5.软件实现

(1)DMA实现


#include "dma.h"


DMA_InitTypeDef DMA_InitStructure;

u16 DMA1_MEM_LEN;//保存 DMA 每次数据传送的长度


//DMA1 的各通道配置

//这里的传输形式是固定的,这点要根据不同的情况来修改

//从存储器->外设模式/8 位数据宽度/存储器增量模式

//DMA_CHx:DMA 通道 CHx

//cpar:外设地址

//cmar:存储器地址

//cndtr:数据传输量


void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)

{

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟

    DMA_DeInit(DMA_CHx); //将 DMA 的通道 1 寄存器重设为缺省值

    DMA1_MEM_LEN=cndtr;

    DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA 外设 ADC 基地址

    DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向内存到外设

    DMA_InitStructure.DMA_BufferSize = cndtr; //DMA 通道的 DMA 缓存的大小

DMA_InitStructure.DMA_Periph

[1] [2]

关键字:STM32  DMA传输

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2019/ic-news010942853.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32学习笔记一一内存管理
下一篇:最后一页

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32程序移植技巧总结

1. 工程更换不同的STM32芯片eg:stm32f103rct6 ---->stm32f103c8t6:1.1. 修改芯片点击魔术棒,在出来的菜单栏里,Device 选项重新选择芯片1.2. 修改启动文件此处举例是 RCT6 修改为 C8T6,因为 flash 容量大小不一样,所以需要对应修改启动文件,如果是 flash 大小相同,此步骤不需要。此处由:startup_stm32f10x_hd.s修改为startup_stm32f10x_md.s1.3. 修改全局宏定义同样先点击魔术棒,在菜单栏选择 C/C++。进而修改全局宏定义。此处:STM32F10X_HD–>STM32F10X_MD1.4. 重新添加FLASH
发表于 2019-01-09
STM32程序移植技巧总结

STM32学习笔记一一FLASH 模拟 EEPROM

1. 简述STM32 本身没有自带 EEPROM,但是 STM32 具有在应用编程(IAP:In Application Programming)功能,可以把它的 FLASH 当成 EEPROM 来使用。不同型号的 STM32,其 FLASH 容量也有所不同,最小的只有 16K 字节,最大的则达到了1024K 字节。MiniSTM32 开发板选择的 STM32F103RCT6 的 FLASH 容量为 256K 字节,属于大容量产品,闪存模块组织如下图:1.1 主存储器:该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。**注意:**小容量和中容量产品则每页
发表于 2019-01-09
STM32学习笔记一一FLASH 模拟 EEPROM

STM32学习笔记一一HEX文件和BIN文件格式

1. 引言今天看串口的 IAP ,平时我们通过 JTAG 等工具下载的都是 HEX 文件,都没有思考一下 HEX 的文件组成。而串口 IAP 下载的是 BIN 文件,刚好在这里区分学习一下。我们平时烧写 HEX 文件是不需要设置地址信息的,因为已经包含在文件里面,而使用 BIN 烧写,需要在程序中指定地址。2. 简述Intel hex 文件是记录文本行的 ASCII 文本文件,在 Intel HEX 文件中,每一行是一个 HEX 记录,由十六进制数组成的机器码或者数据常量。Intel HEX 文件经常被用于将程序或数据传输存储到 ROM、EPROM,大多数编程器和模拟器使用Intel HEX文件。2.1 HEX文件HEX 文件是包括
发表于 2019-01-09
STM32学习笔记一一HEX文件和BIN文件格式

STM32学习笔记一一串口 IAP

(Bootloader 程序)必须通过其它手段,如 JTAG 或 ISP 烧入;第二部分代码(APP 程序)可以使用第一部分代码 IAP 功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新时再通过第一部分 IAP代码更新。他们存放在 STM32 FLASH 的不同地址范围,一般从最低地址区开始存放 Bootloader,紧跟其后的就是 APP 程序。2 .STM32程序流程2.1 STM32 正常的程序运行流程下图为 STM32 正常的程序运行流程:STM32 的内部闪存(FLASH)地址起始于 0x08000000,一般情况下,程序文件就从此地址开始写入。此外STM32是基于Cortex-M3内核的微控制器,其内部通过一张
发表于 2019-01-09
STM32学习笔记一一串口 IAP

STM32学习笔记一一待机唤醒

1. 简述1.1 低功耗模式:在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如:等待某个外部事件时,常见的按键唤醒。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。1.2 STM32F10X系列的低功耗模式STM32F10xxx有三种低功耗模式:–模式– –特点—睡眠模式 Cortex-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行停止模式 所有的时钟都已停止待机模式 1.8V电源关闭在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需 2uA 左右的电流。停机模式
发表于 2019-01-09
STM32学习笔记一一待机唤醒

STM32学习笔记一一红外遥控

}2.2 中断捕获u8 RmtSta=0;u16 Dval;u32 RmtRec=0;u8 RmtCnt=0;void TIM5_IRQHandler(void){ if(TIM_GetITStatus(TIM5,TIM_IT_Update)!= RESET) { if(RmtSta&0x80)//数据接收到标志位 { RmtSta &= ~0x10;//取消上升沿捕获标记 if((RmtSta&0x0F)==0x00) RmtSta |= 1<<6; if((RmtSta&0x0F)<14) RmtSta++; else { RmtSt
发表于 2019-01-09
STM32学习笔记一一红外遥控

小广播

何立民专栏

单片机及嵌入式宝典

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

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved
pt type="text/javascript" src="//v3.jiathis.com/code/jia.js?uid=2113614" charset="utf-8">