DMA(Direct memory access)直接存储器存取,用来提供在外设和存储器之间或者存储
器和存储器之间的高速数据传输,无须CPU干预,数据可以通过DMA快速地移动,这就节
省了CPU的资源来做其他操作。
STM32有两个DMA控制器共12个通道(DMA1有7个通道,DMA2有5个通道),每个通
道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个
DMA请求的优先权。
3.1、DMA作用
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环
节,
主要涉及四种数据传输模式,其本质还是一样的,都是地址到地址的数据传
输。
外设到内存
内存到外设
内存到内存
外设到外设
3.2、
DMA传输相关参数
源地址
目标地址
数据传输量
...
3.3、DMA的主要特征
12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道,每个通
道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过
软件来配置:
同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很
高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)
独立数据源和目标数据区的传输宽度包括字节、半字、全字,源地址和目标地址
必须按数据传输宽度对齐。
支持循环的缓冲器管理
每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错)
FLASH、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和
目标
编程的数据传输数目:最大为65535
3.4、stm32DMA资源
3.4.1、DMA1控制器
从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、
2、3])产生的7个请求,通过逻辑或输入到DMA1控制器。
外设的DMA请求,可以通过设置相应外设寄存器中的控制位,被独立地开启或关闭
3.4.2、DMA2控制器
从外设(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)产生的5
个请
求,经逻辑或输入到DMA2控制器
外设的DMA请求,可以通过设置相应外设寄存器中的DMA控制位,被独立地开启或关闭
注意:DMA2控制器及相关请求仅存在于大容量产品和互联型产品中
3.5、stm32DMA相关固件库函数说明
3.5.1、初始化函数
1
void
DMA_Init
(
DMA_Channel_TypeDef
*
DMAy_Channelx
,
\
2
DMA_InitTypeDef
*
DMA_InitStruct
)
参数:
@DMAy_Channelx:DMA通道
y:1或2,用于选择DMA1或DMA2
x:对于DMA1:1-7,对于DMA2:1-5
@DMA_InitStruct:DMA配置结构体指针
1
typedef struct
2
{
3
uint32_t DMA_PeripheralBaseAddr
;
//
外设地址
4
uint32_t DMA_MemoryBaseAddr
;
//
存储器地址
5
uint32_t
DMA_DIR
;
//
传输方向
6
uint32_t DMA_BufferSize
;
//
输出大小
7
uint32_t DMA_PeripheralInc
;
//
外设地址增量模式
8
uint32_t DMA_MemoryInc
;
//
存储器地址增量模式
9
uint32_t DMA_PeripheralDataSize
;
//
外设数据宽度
10
uint32_t DMA_MemoryDataSize
;
//
存储器数据宽度
11
uint32_t DMA_Mode
;
//
模式选择
12
uint32_t DMA_Priority
;
//
通道优先级
13
uint32_t
DMA_M2M
;
//
存储器到存储器模式
14
}
DMA_InitTypeDef
;
传输方向:
1
#define
DMA_DIR_PeripheralDST
((
uint32_t
)
0x00000010
)
2
#define
DMA_DIR_PeripheralSRC
((
uint32_t
)
0x00000000
)
DMA通道x配置寄存器(DMA_CCRx):
外设地址增量模式:
1
#define
DMA_PeripheralInc_Enable
((
uint32_t
)
0x00000040
)
2
#define
DMA_PeripheralInc_Disable
((
uint32_t
)
0x00000000
)
存储器地址增量模式:
1
#define
DMA_MemoryInc_Enable
((
uint32_t
)
0x00000080
)
2
#define
DMA_MemoryInc_Disable
((
uint32_t
)
0x00000000
)
外设数据宽度:
1
#define
DMA_PeripheralDataSize_Byte
((
uint32_t
)
0x00000000
)
2
#define
DMA_PeripheralDataSize_HalfWord
((
uint32_t
)
0x00000100
)
3
#define
DMA_PeripheralDataSize_Word
((
uint32_t
)
0x00000200
)
存储器数据宽度
1
#define
DMA_MemoryDataSize_Byte
((
uint32_t
)
0x00000000
)
2
#define
DMA_MemoryDataSize_HalfWord
((
uint32_t
)
0x00000400
)
3
#define
DMA_MemoryDataSize_Word
((
uint32_t
)
0x00000800
)
4
模式选择(DMA_Mode):
1
#define
DMA_Mode_Circular
((
uint32_t
)
0x00000020
)
//
循环模式
2
#define
DMA_Mode_Normal
((
uint32_t
)
0x00000000
)
//
正常模式
通道优先级:
1
#define
DMA_Priority_VeryHigh
((
uint32_t
)
0x00003000
)
2
#define
DMA_Priority_High
((
uint32_t
)
0x00002000
)
3
#define
DMA_Priority_Medium
((
uint32_t
)
0x00001000
)
4
#define
DMA_Priority_Low
((
uint32_t
)
0x00000000
)
存储器到存储器模式:
1
#define
DMA_M2M_Enable
((
uint32_t
)
0x00004000
)
2
#define
DMA_M2M_Disable
((
uint32_t
)
0x00000000
)
3.5.2、DMA通道使能
1
void
DMA_Cmd
(
DMA_Channel_TypeDef
*
DMAy_Channelx
,
\
2
FunctionalState NewState
)
3.5.3、DMA中断配置
1
void
DMA_ITConfig
(
DMA_Channel_TypeDef
*
DMAy_Channelx
,
uint32_t
DMA_IT
,
\
2
FunctionalState NewState
)
3.5.4、其他辅助函数
DMA清除中断挂起
1
void
DMA_ClearITPendingBit
(
uint32_t DMAy_IT
)
DMA获取中断状态
1
ITStatus
DMA_GetITStatus
(
uint32_t DMAy_IT
)
获取传输剩余个数
1
uint16_t
DMA_GetCurrDataCounter
(
DMA_Channel_TypeDef
*
DMAy_Channelx
)
3.6、memory to memory实例
使用DMA的M2M模式从内嵌flash拷贝数据到sram中:
1
//32
个
4
字节数据
2
0x01020304
,
0x05060708
,
0x090A0B0C
,
0x0D0E0F10
,
3
0x11121314
,
0x15161718
,
0x191A1B1C
,
0x1D1E1F20
,
4
0x21222324
,
0x25262728
,
0x292A2B2C
,
0x2D2E2F30
,
5
0x31323334
,
0x35363738
,
0x393A3B3C
,
0x3D3E3F40
,
6
0x41424344
,
0x45464748
,
0x494A4B4C
,
0x4D4E4F50
,
7
0x51525354
,
0x55565758
,
0x595A5B5C
,
0x5D5E5F60
,
8
0x61626364
,
0x65666768
,
0x696A6B6C
,
0x6D6E6F70
,
9
0x71727374
,
0x75767778
,
0x797A7B7C
,
0x7D7E7F80
stm32的内嵌flash中存放的是code和const修饰的变量值
4.dma数据传输示例
1、User目录新建dma_mtom.h和dma_mtom.c文件,通过三色板文件添加按钮添加文件
2、编写dma_mtom.c代码
2.1在外设库定义文件找到RCC_AHBPeriphClockCmdASB总线的外部使能函数
3.编译
4.没有错误
5.下载程序到STM32单片机中进行调试
6.按下复位按键
7.黄灯和红灯亮了,代表p13的引脚写入成功