DMA传输数据

前言

  DMA即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。本篇文章以STM32F4为例,不同型号可能略有不同。

一.DMA特性简介

  STM32F4有两个DMA控制器,一个控制器有8个数据流,一个数据流有8个通道(请求)
  值得注意的是,DMA1仅支持外设P->M,M->P,而不支持M->M,而DMA2全都支持。这是因为DMA1的存储区端口相比DMA2的要减少AHB2外设的访问权,同时DMA1外设端口是没有连接至总线矩阵的,只有连接到 APB1 外设,所以DMA1不能实现存储器到存储器传输。
image

二.代码配置

这里仅实现简单的M->M,传输一次即可,并将结果通过串口打印。代码如下
首先是初始化DMA:

//DMA_Streamx设置DMA控制器和数据流,如DMA2_Stream0
//chx设置通道
//par设置发送地址
//mar设置接收地址
//ndtr设置数据传输量
void MYDMA_Init(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
{
    DMA_InitTypeDef  DMA_InitStructure;
if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
{
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
}else
{
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能 
}
  DMA_DeInit(DMA_Streamx); 
  while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待 DMA 可配置

/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = chx;  //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址,其实就是传输起始地址
DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址,数据接收地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量 
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable ;//外设增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式,一次传输,存储器到存储器只能一次模式 
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不用FIFO        
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream,初始化数据流
	
DMA_Cmd(DMA_Streamx, ENABLE); //开启 DMA 传输

}

主函数代码如下

uint8_t DataA[] = {0x01, 0x02, 0x03, 0x04};
uint8_t DataB[] = {0, 0, 0, 0};

int main(void)
{
uart_init(115200);
delay_init(84);
//delay_ms(500);
printf(“t:%d\r\n”,DataB[0]);
printf(“t:%d\r\n”,DataB[1]);
printf(“t:%d\r\n”,DataB[2]);
printf(“t:%d\r\n”,DataB[3]);
MYDMA_Init(DMA2_Stream0,DMA_Channel_4,(uint32_t) DataA,(uint32_t) DataB,4);
delay_ms(500);
printf(“t:%d\r\n”,DataB[0]);
printf(“t:%d\r\n”,DataB[1]);
printf(“t:%d\r\n”,DataB[2]);
printf(“t:%d\r\n”,DataB[3]);
while(1){
}
}

三.实验结果

通过串口查看数组B在DMA传输前后的数据,结果如下:
image
可知数据搬运成功。

DMA传输数据
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值