DMA 简介
输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。
两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自
于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
DMA控制器基于一个复杂的总线矩阵架构,结合了功能强大的双AHB主总线架构与独立的FIFO,以优化系统带宽。 两个DMA控制器共有16个数据流(stream),每个数据流可以编程与规定的通道中的一个搭配。
DMA 主要特性
● 12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过
软件来配置。
● 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、
中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目
标地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志
逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器、存储器和外设之间的传输
● 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65535
DMA工作过程:
1.外设向DMAC发出DMA传送请求;
2.DMAC通过连接到CPU的HOLD信号向CPU提出DMA请求;
3.CPU在完成当前总线操作后,会立即对DMA做出响应
①CPU将地址总线、控制总线、数据总线悬空(放弃总线控制权)
②CPU将有效的HLDA信号加到DMAC上,以通知DMAC CPU已经放弃了总线控制权
4.CPU将总线悬空,DMAC接管系统总线的控制权,并向外设送出DMA应答信号
5.DMAC送出地址信号和控制信号,实现外设与内存或内存与内存之间的大量数据传输
6.DMAC将数据传送完成后,通过给CPU发HLDA信号,撤销对CPU的DMA请求;CPU接收信号后,一方面使HDLA无效,一方面重新开始控制总线;
DMA数据传送
1.外设与存储器之间
DMAC只是输出地址信号和控制信号(IOR/IRW/MEMR/MEMW),数据传送直接在内存和外设端口之间进行,并不经过DMAC
2.存储器与存储器之间
先用一个DMA存储器读周期将数据从源地址读出,放到DMA的数据暂存器中,再利用一个DMA存储器写周期将数据写到目的区域
STM32F103 DMA 控制
相关寄存器介绍:
主要说一下DMA_CCRx(DMA通道x配置寄存器x=1…7)
14位:MEM2MEM存储器到存储器模式(手动),定义:0(非存储器到存储器模式),1(启动存储器到存储器模式)
13和12位:PL[1:0]通道优先级(手动),定义:00(低),01(中),10(高),11(最高)
11和10位:MSIZE[1:0]存储器数据宽度(手动)定义:00(8位),01(16位),10(32位),11(保留)
9和8位PSIZE[1:0]外设数据宽度(手动)定义:00(8位),01(16位),10(32位),11(保留)
7位:MINC存储器地址增量模式(手动)定义:0(不执行存储器地址增量操作),1(执行存储器地址增量操作)
6位:PINC外设地址增量模式(手动)定义:0(不执行存储器地址增量操作),1(执行存储器地址增量操作)
5位:CIRC循环模式(手动)定义:0(不执行循环操作),1(执行循环操作)
4位:DIR数据传输方向(手动)定义:0(从外设读),1(从存储器读)
3位:TEIE允许传输错误中断(手动)定义:0(禁止TE中断),1(允许TE中断)
2位:HEIE允许半传输中断(手动)定义:0(禁止TE中断),1(允许TE中断)
1位:TCIE允许传输完成中断(手动)定义:0(禁止TE中断),1(允许TE中断)
0位:EN开启通道(手动)定义:0(不工作),1(开启)
//库函数版
u8 SendBuff[SENDBUFF_SIZE];
void USART_DMA_init()
{
u16 i;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;// 设置外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;//设置内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //设置方向:从内存到外设
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;// 一次传输数据量的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设增量
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存增量
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据长度
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;//是否循环采集
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级设置
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//是否是内存到内存
DMA_Init(DMA1_Channel4, &DMA_InitStructure); //初始化相关通道(此处选用uart1)
DMA_Cmd (DMA1_Channel4,ENABLE); //使能通道
for(i=0;i<SENDBUFF_SIZE;i++)
{
SendBuff[i] = 'A';
}
}
//寄存器版
void DMA_RESET(DMA_Channel_TypeDef *DMA_chx)//设置为缺省值
{
//
DMA_chx->CCR=0;
DMA_chx->CMAR=0;
DMA_chx->CPAR=0;
DMA_chx->CNDTR=0;
//判断通道清除标志位
if(DMA_chx==DMA1_Channel1)
{
DMA1->IFCR=(uint32_t)0x0F;
}
else if(DMA_chx==DMA1_Channel2)
{
DMA1->IFCR=(uint32_t)0x0F<<4;
}
else if(DMA_chx==DMA1_Channel3)
{
DMA1->IFCR=(uint32_t)0x0F<<8;
}
else if(DMA_chx==DMA1_Channel4)
{
DMA1->IFCR=(uint32_t)0x0F<<12;
}
else if(DMA_chx==DMA1_Channel5)
{
DMA1->IFCR=(uint32_t)0x0F<<16;
}
else if(DMA_chx==DMA1_Channel6)
{
DMA1->IFCR=(uint32_t)0x0F<<20;
}
else if(DMA_chx==DMA1_Channel7)
{
DMA1->IFCR=(uint32_t)0x0F<<24;
}
else if(DMA_chx==DMA2_Channel1)
{
DMA1->IFCR=(uint32_t)0x0F;
}
else if(DMA_chx==DMA2_Channel2)
{
DMA1->IFCR=(uint32_t)0x0F<<4;
}
else if(DMA_chx==DMA2_Channel3)
{
DMA1->IFCR=(uint32_t)0x0F<<8;
}
else if(DMA_chx==DMA2_Channel4)
{
DMA1->IFCR=(uint32_t)0x0F<<12;
}
else if(DMA_chx==DMA2_Channel5)
{
DMA1->IFCR=(uint32_t)0x0F<<16;
}
}
void DMA_config(DMA_Channel_TypeDef *DMA_chx,uint32_t par,uint32_t mar,uint16_t lenght,uint32_t ccr)
{
DMA_chx->CMAR = mar;//内存地址
DMA_chx->CPAR = par;//外设地址
DMA_chx->CNDTR= lenght;//数据长度
DMA_chx->CCR = ccr;//控制寄存器相关值设置
}
void DMA_ENABLE(DMA_Channel_TypeDef *DMA_chx)//使能
{
DMA_chx->CCR|=(uint32_t)~0x01;
DMA_chx->CCR|=(uint32_t)0x01;
}
主要用于内存与外设之间的数据搬运工作,若用于内存与内存之间,DMA存储器到存储器模式不限定通道。