DMA简介:
存储器映像:
注意:FLASH是只读的,DMA不能写入,但是可以读取写到其他存储器里
变量是存在运行内存SRAM里的,常量(const)是放在程序存储器FLASH里的
DMA框图:
简图:
创输计数器是DMA转运的次数,会自减,减到0就不再转运,自增的地址也恢复到起始地址
由硬件还是软件触发由M2M这个决定
DMA请求映像:
数据宽度与对齐:
例1:
源地址填DataA,目的地址填DataB,源和目的端都自增地址,传输计数器给7,自动重装不需要,采用软件触发
例2:
源地址写ADC_DR的地址,不自增,目的地址写ADValue,自增,数据宽带选择半字(16位,因为ADC_DR是16位的)传输计数器写7,连续扫描自动重装写7,单次可以不用自动重装,选择ADC硬件触发。
——————————————————————————————————————————
存储器之间转运代码:
#include "stm32f10x.h"
uint16_t MyDMA_Size;//用来记录传输计数器的值
//三个参数,第一个参数是源地址,第二个参数是目的地址,第三个参数是传输计数器的值
//STM32中地址都是32位的,每个地址代表一个字节
void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)
{
DMA_InitTypeDef DMA_InitStructure;//DMA初始化结构体
MyDMA_Size = Size;//记录传输计数器的值
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//打开DMA的时钟
DMA_InitStructure.DMA_BufferSize = Size;//传输计数器的值
//方向是从外设存储器到存储器(其实这里的外设并不一定是外设寄存器,只是这么叫而已)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;//由软件触发
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;//存储器地址设为AddrB
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//宽度设为字节
//设为地址自增(自增大小是宽带的字节数,因为一个字节对应一个地址)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//设置DMA工作模式为普通模式,即不采用重装载
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//外设存储器地址(同理的,这个外设存储器也不一定是外设存储器)设为AddrA
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//宽度设为字节
//设为地址自增(自增大小是宽带的字节数,因为一个字节对应一个地址)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
//优先级设为中等优先级
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1,&DMA_InitStructure);//传参,配置DMA1的1通道
打开DMA1的1通道
DMA_Cmd(DMA1_Channel1,DISABLE);
}
void MyDMA_Transfer(void)
{
DMA_Cmd(DMA1_Channel1,DISABLE);//失能DMA1通道1,因为改变传输计数器的值要关闭DMA
DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size);//重新写入传输计数器的值
DMA_Cmd(DMA1_Channel1,ENABLE);//使能
while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//判断是否传输完成
DMA_ClearFlag(DMA1_FLAG_TC1);//清空标志位
}