DMA-STM32
DMA(Direct Memory Access)直接存储器存取
DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源
12个独立可配置的通道:DMA1 (7个通道),DMA2 (5个通道)
每个通道都支持软件触发和特定的硬件触发
STM32F103C8T6DMA资源:DMA1(7个通道)
用于访问各个存储器的DMA总线
内部的多个通道,可以进行独立的数据转运
仲裁器,用于调度各个通道,防止产生冲突
AHB从设备,用于配置DMA参数
DMA请求,用于硬件触发DMA的数据转运
CPU或者DMA直接访问Flash的话,是只可以读而不可以写的
后SRAM是运行内存,可以任意读写
左边是外设寄存器站点
右边是存储器站点,包括Flash和SRAM
不够就补0,超就舍弃高位
例子
这里的数据转运是一种复制转运,转运完成后DataA的数据并不会消失
第一步,RCC开启DMA的时钟。
第二步,就可以直接调用DMA Init,初始化这里的各个参数了。包括外设和存储器站点的起始地址、数据宽度、地址是否自增。方向、传输计数器、是否需要自动重装、选择触发源。
用的是软件触发,所以通道可以任意选择。
最后:进行开关控制,DMA_Cmd
#include "stm32f10x.h" // Device header
uint16_t MyDMA_Size;
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{
MyDMA_Size = Size;
//¿ªÆôDMAʱÖÓ
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//ÅäÖÃDMA½á¹¹Ìå
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;//Ô´µØÖ·
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//×Ö½ÚÀàÐÍ´«Êä(8λ)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//ʹÄܵØÖ·×ÔÔö
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;//Ä¿±êµØÖ·
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//×Ö½ÚÀàÐÍ´«Êä(8λ)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ʹÄܵØÖ·×ÔÔö
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//Êý¾Ý´«Êä·½Ïò
DMA_InitStructure.DMA_BufferSize = Size;//Êý¾Ý¸öÊý
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//Õý³£Ä£Ê½
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;//Èí¼þ³ö·¢
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//ĬÈϹرտª¹ØʹÄÜ
DMA_Cmd(DMA1_Channel1, DISABLE);
}
void MyDMA_Transfer(void)
{
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
DMA_Cmd(DMA1_Channel1, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC1);
}
#ifndef __MYDMA_H
#define __MYDMA_H
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size);
void MyDMA_Transfer(void);
#endif