DMA(直接存储器存取)

DMA介绍

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

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

12个独立可配置的通道: DMA17个通道), DMA25个通道)

每个通道都支持软件触发和特定的硬件触发

STM32F103C8T6 DMA资源:DMA17个通道)

存储器映像

ROM (Read Only Memory) 只读存储器

RAM (Random Access Memory)  随机存取存储器

DMA框图

DMA基本结构

DMA请求映像

DMA配置

开启AHB外设时钟

操作的是AHB外设时钟使能寄存器 (RCC_AHBENR)

参数一:选择AHB总线上的外设

参数二:使能或失能

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

 DMA_InStruct结构体

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_Priority

设置 DMA 通道的优先级,有低,中,高,超高三种模式,这里我们设置优先级别为中级,所以值为 DMA_Priority_Medium。优先级可以随便设置,因为我们只有一个数据流被开启了。假设有多个数据流开启(最多 8 个),那么就要设置优先级了,DMA 仲裁器将根据这些优先级的设置来决定先执行那个数据流的 DMA。优先级越高的,越早执行,当优先级相同的时候,根据硬件上的编号来决定哪个先执行(编号越小越优先)。

DMA_M2M存储器到存储器模式,使用存储器到存储器时用到,可启动存储器到存储器模式。

初始化DMA

操作以下寄存器:

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

DMA通道x传输数量寄存器(DMA_CNDTRx)(x = 1…7)

DMA通道x外设地址寄存器(DMA_CPARx)(x = 1…7)

DMA通道x存储器地址寄存器(DMA_CMARx)(x = 1…7)

DMA_Init(DMAy_Channelx,&DMA_InitStruct);

 使能DMA 

操作以下寄存器:

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

DMA_Cmd(DMAy_Channelx, ENABLE);

 配置全代码如下:

#include "DMA.h"

//内存地址
unsigned char DMA_MemoryBaseAddr[] = {"mmmmm"};
uint32_t DMA_BufferSize = sizeof(DMA_MemoryBaseAddr);

/*DMA初始化*/
void DMA_InitA(DMA_Channel_TypeDef* DMAy_Channelx)
{
	/*使能DMA时钟*/
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	
	DMA_InitTypeDef DMA_InitStructure;
	
	/*配置DMA参数*/
	
	//配置内存地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DMA_MemoryBaseAddr;
	//配置外设地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; 
	//配置数据传输方向 外设作为数据传输目的地(外设作为数据源)
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	//配置数据传输大小
	DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;
	//禁止外设地址递增
	DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	//允许内存地址是否递增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	//配置外设数据单位 8位字节传输
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	//配置内存数据单位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	//配置DMA模式 单次传输(循环传输)
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	//配置DMA优先级
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	//配置是否使能从内存到内存传输
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	//配置DMA通道初始化
	DMA_Init(DMAy_Channelx,&DMA_InitStructure);
	DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
	//使能DMA
	DMA_Cmd(DMAy_Channelx,ENABLE);

}


/*DMA发送函数*/
void DMASend(DMA_Channel_TypeDef* DMAy_Channelx,unsigned char* MBuff,unsigned int MBuffSize)
{
	DMA_Cmd(DMAy_Channelx,DISABLE);
	 
	DMAy_Channelx->CMAR = (u32)MBuff;
	
	DMAy_Channelx->CNDTR = MBuffSize;
	DMA_Cmd(DMAy_Channelx,ENABLE);
	
}

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值