stm32f10x_dma
STM32F10x DMA 外设标准库函数参考文档
数据类型定义
DMA_InitTypeDef - DMA初始化结构体
typedef struct
{
uint32_t DMA_PeripheralBaseAddr; /* 外设基地址 */
uint32_t DMA_MemoryBaseAddr; /* 存储器基地址 */
uint32_t DMA_DIR; /* 传输方向 */
uint32_t DMA_BufferSize; /* 缓冲区大小 */
uint32_t DMA_PeripheralInc; /* 外设地址递增模式 */
uint32_t DMA_MemoryInc; /* 存储器地址递增模式 */
uint32_t DMA_PeripheralDataSize; /* 外设数据宽度 */
uint32_t DMA_MemoryDataSize; /* 存储器数据宽度 */
uint32_t DMA_Mode; /* 传输模式 */
uint32_t DMA_Priority; /* 通道优先级 */
uint32_t DMA_M2M; /* 存储器到存储器模式 */
} DMA_InitTypeDef;成员说明:
DMA_PeripheralBaseAddr:指定DMA通道的外设基地址DMA_MemoryBaseAddr:指定DMA通道的存储器基地址DMA_DIR:指定传输方向,可选值见 @ref DMA_data_transfer_directionDMA_BufferSize:指定缓冲区大小,以数据单元为单位(1-65535)DMA_PeripheralInc:外设地址是否递增,可选值见 @ref DMA_peripheral_incremented_modeDMA_MemoryInc:存储器地址是否递增,可选值见 @ref DMA_memory_incremented_modeDMA_PeripheralDataSize:外设数据宽度,可选值见 @ref DMA_peripheral_data_sizeDMA_MemoryDataSize:存储器数据宽度,可选值见 @ref DMA_memory_data_sizeDMA_Mode:传输模式,可选值见 @ref DMA_circular_normal_modeDMA_Priority:通道优先级,可选值见 @ref DMA_priority_levelDMA_M2M:存储器到存储器传输使能,可选值见 @ref DMA_memory_to_memory
枚举类型定义
DMA传输方向
#define DMA_DIR_PeripheralDST ((uint32_t)0x00000010) /* 存储器到外设 */
#define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000) /* 外设到存储器 */说明:
DMA_DIR_PeripheralDST:数据从存储器传输到外设DMA_DIR_PeripheralSRC:数据从外设传输到存储器
DMA外设地址递增模式
#define DMA_PeripheralInc_Enable ((uint32_t)0x00000040) /* 外设地址递增使能 */
#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000) /* 外设地址递增禁用 */DMA存储器地址递增模式
#define DMA_MemoryInc_Enable ((uint32_t)0x00000080) /* 存储器地址递增使能 */
#define DMA_MemoryInc_Disable ((uint32_t)0x00000000) /* 存储器地址递增禁用 */DMA外设数据宽度
#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) /* 8位数据宽度 */
#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) /* 16位数据宽度 */
#define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200) /* 32位数据宽度 */DMA存储器数据宽度
#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) /* 8位数据宽度 */
#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) /* 16位数据宽度 */
#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) /* 32位数据宽度 */DMA传输模式
#define DMA_Mode_Circular ((uint32_t)0x00000020) /* 循环传输模式 */
#define DMA_Mode_Normal ((uint32_t)0x00000000) /* 正常传输模式 */说明:
DMA_Mode_Circular:循环传输模式,传输完成后自动重新开始DMA_Mode_Normal:正常传输模式,传输完成后停止
DMA通道优先级
#define DMA_Priority_VeryHigh ((uint32_t)0x00003000) /* 非常高优先级 */
#define DMA_Priority_High ((uint32_t)0x00002000) /* 高优先级 */
#define DMA_Priority_Medium ((uint32_t)0x00001000) /* 中等优先级 */
#define DMA_Priority_Low ((uint32_t)0x00000000) /* 低优先级 */DMA存储器到存储器模式
#define DMA_M2M_Enable ((uint32_t)0x00004000) /* 存储器到存储器模式使能 */
#define DMA_M2M_Disable ((uint32_t)0x00000000) /* 存储器到存储器模式禁用 */DMA中断标志定义
基本中断类型
#define DMA_IT_TC ((uint32_t)0x00000002) /* 传输完成中断 */
#define DMA_IT_HT ((uint32_t)0x00000004) /* 半传输中断 */
#define DMA_IT_TE ((uint32_t)0x00000008) /* 传输错误中断 */DMA1具体中断标志
#define DMA1_IT_GL1 ((uint32_t)0x00000001) /* DMA1通道1全局中断 */
#define DMA1_IT_TC1 ((uint32_t)0x00000002) /* DMA1通道1传输完成中断 */
#define DMA1_IT_HT1 ((uint32_t)0x00000004) /* DMA1通道1半传输中断 */
#define DMA1_IT_TE1 ((uint32_t)0x00000008) /* DMA1通道1传输错误中断 */
/* ... 其他通道中断标志 ... */DMA2具体中断标志
#define DMA2_IT_GL1 ((uint32_t)0x10000001) /* DMA2通道1全局中断 */
#define DMA2_IT_TC1 ((uint32_t)0x10000002) /* DMA2通道1传输完成中断 */
#define DMA2_IT_HT1 ((uint32_t)0x10000004) /* DMA2通道1半传输中断 */
#define DMA2_IT_TE1 ((uint32_t)0x10000008) /* DMA2通道1传输错误中断 */
/* ... 其他通道中断标志 ... */DMA状态标志定义
DMA1状态标志
#define DMA1_FLAG_GL1 ((uint32_t)0x00000001) /* DMA1通道1全局标志 */
#define DMA1_FLAG_TC1 ((uint32_t)0x00000002) /* DMA1通道1传输完成标志 */
#define DMA1_FLAG_HT1 ((uint32_t)0x00000004) /* DMA1通道1半传输标志 */
#define DMA1_FLAG_TE1 ((uint32_t)0x00000008) /* DMA1通道1传输错误标志 */
/* ... 其他通道状态标志 ... */DMA2状态标志
#define DMA2_FLAG_GL1 ((uint32_t)0x10000001) /* DMA2通道1全局标志 */
#define DMA2_FLAG_TC1 ((uint32_t)0x10000002) /* DMA2通道1传输完成标志 */
#define DMA2_FLAG_HT1 ((uint32_t)0x10000004) /* DMA2通道1半传输标志 */
#define DMA2_FLAG_TE1 ((uint32_t)0x10000008) /* DMA2通道1传输错误标志 */
/* ... 其他通道状态标志 ... */标准库函数详解
1. DMA_DeInit
/**
* @brief 将 DMA 通道寄存器恢复为复位默认值,用于重新配置前清空旧传输状态
* @param DMAy_Channelx: 指定的DMA通道,可以是DMA1_Channel1到DMA1_Channel7或DMA2_Channel1到DMA2_Channel5
* @retval 无
* @example
* DMA_DeInit(DMA1_Channel1); // 复位DMA1通道1
*/
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);功能说明:
- 清除方向、地址、计数等全部通道配置
- 切换传输源/目的或模式前先 DeInit
- 传输异常后可重置通道再 Init
2. DMA_Init
/**
* @brief 初始化 DMA 通道(源/目的地址、方向、宽度、模式等),建立外设与内存间的搬运路径
* @param DMAy_Channelx: 指定的DMA通道
* @param DMA_InitStruct: 指向DMA_InitTypeDef结构体的指针,包含配置信息
* @retval 无
* @example
* DMA_InitTypeDef DMA_InitStructure;
* DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
* DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer;
* DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
* DMA_InitStructure.DMA_BufferSize = 100;
* DMA_Init(DMA1_Channel5, &DMA_InitStructure);
*/
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);功能说明:
- 配置外设到内存、内存到外设或内存到内存
- 设置数据宽度、地址是否递增、循环/普通模式
- 需在 DMA_Cmd 前完成,并匹配外设 DMA 请求线
3. DMA_StructInit
/**
* @brief 将 DMA_InitTypeDef 成员填为安全默认值,避免未赋值字段导致随机配置
* @param DMA_InitStruct: 指向DMA_InitTypeDef结构体的指针
* @retval 无
* @example
* DMA_InitTypeDef DMA_InitStructure;
* DMA_StructInit(&DMA_InitStructure);
*/
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);功能说明:
- 提供合理的默认地址、宽度、优先级等
- 先 StructInit 再按需修改各成员
- 降低多字段 DMA 配置的遗漏风险
4. DMA_Cmd
/**
* @brief 启动或停止 DMA 通道;ENABLE 后按配置自动搬运,DISABLE 后暂停
* @param DMAy_Channelx: 指定的DMA通道
* @param NewState: DMA通道的新状态,可以是ENABLE或DISABLE
* @retval 无
* @example
* DMA_Cmd(DMA1_Channel1, ENABLE); // 启动DMA传输
* DMA_Cmd(DMA1_Channel1, DISABLE); // 停止DMA传输
*/
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);功能说明:
- Init 完成且外设 DMA 请求使能后 ENABLE 开始传输
- DISABLE 可中止当前传输(剩余计数停止递减)
- 修改 CNDTR 前须先 DISABLE 通道
5. DMA_ITConfig
/**
* @brief 打开/关闭 DMA 中断(传输完成/半传输/错误),配合 NVIC 获知搬运进度
* @param DMAy_Channelx: 指定的DMA通道
* @param DMA_IT: 指定的DMA中断源,可以是DMA_IT_TC、DMA_IT_HT、DMA_IT_TE的组合
* @param NewState: 中断的新状态,可以是ENABLE或DISABLE
* @retval 无
* @example
* DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); // 使能传输完成中断
*/
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);功能说明:
- TC:整缓冲传完,常用于通知应用处理数据
- HT:半缓冲完成,适合双缓冲乒乓操作
- TE:传输错误,需排查地址或总线问题
6. DMA_SetCurrDataCounter
/**
* @brief 设置本次传输的数据单元个数,决定 DMA 搬多少数据后停止
* @param DMAy_Channelx: 指定的DMA通道
* @param DataNumber: 要传输的数据数量(1-65535)
* @retval 无
* @example
* DMA_SetCurrDataCounter(DMA1_Channel1, 1024); // 设置传输1024个数据单元
*/
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); 功能说明:
- 仅在通道 DISABLE 时写入 CNDTR
- 重复启动传输前需重新设置计数
- 单元大小由 Init 中的 Memory/Periph DataSize 决定
7. DMA_GetCurrDataCounter
/**
* @brief 读取通道剩余未传输的数据单元数,用于监控进度或判断完成
* @param DMAy_Channelx: 指定的DMA通道
* @retval 剩余的数据传输数量
* @example
* uint16_t remaining = DMA_GetCurrDataCounter(DMA1_Channel1);
*/
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);功能说明:
- 传输进行中 CNDTR 递减,为 0 表示完成
- 可计算已传输量 = 初始值 - 剩余值
- 轮询等待完成时可替代中断
8. DMA_GetFlagStatus
/**
* @brief 查询 DMA 标志位(TC/HT/TE),判断传输完成、半完成或错误
* @param DMAy_FLAG: 指定的DMA标志位
* @retval FlagStatus: 标志位状态(SET或RESET)
* @example
* if (DMA_GetFlagStatus(DMA1_FLAG_TC1) == SET) {
* // 传输完成处理
* }
*/
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);功能说明:
- 轮询模式下等待 TC 再处理缓冲
- TE 置位表示传输错误
- 标志与通道号对应(如 TC1 对应 Channel1)
9. DMA_ClearFlag
/**
* @brief 清除 DMA 标志位,避免重复检测到同一完成/错误事件
* @param DMAy_FLAG: 指定要清除的DMA标志位
* @retval 无
* @example
* DMA_ClearFlag(DMA1_FLAG_TC1); // 清除传输完成标志
*/
void DMA_ClearFlag(uint32_t DMAy_FLAG);功能说明:
- 轮询处理 TC/HT 后必须清除
- 中断模式下也可配合使用
- 未清除会导致误以为再次完成
10. DMA_GetITStatus
/**
* @brief 在中断服务程序中判断具体 DMA 中断源是否挂起
* @param DMAy_IT: 指定的DMA中断标志
* @retval ITStatus: 中断状态(SET或RESET)
* @example
* if (DMA_GetITStatus(DMA1_IT_TC1) == SET) {
* // 处理传输完成中断
* }
*/
ITStatus DMA_GetITStatus(uint32_t DMAy_IT);功能说明:
- 检查使能位与挂起位组合
- ISR 中区分 TC/HT/TE 分支
- 比 GetFlagStatus 更适合中断上下文
11. DMA_ClearITPendingBit
/**
* @brief 清除 DMA 中断挂起位,ISR 处理完毕后必须调用以免重复进中断
* @param DMAy_IT: 指定要清除的DMA中断挂起位
* @retval 无
* @example
* DMA_ClearITPendingBit(DMA1_IT_TC1); // 清除传输完成中断挂起位
*/
void DMA_ClearITPendingBit(uint32_t DMAy_IT);功能说明:
- 处理完 TC/HT/TE 中断后调用
- 未清除会导致中断反复触发
- 与 ClearFlag 配合确保状态干净
使用示例
USART接收DMA配置示例
#include "stm32f10x.h"
#define BUFFER_SIZE 100
uint8_t rx_buffer[BUFFER_SIZE];
void DMA_USART_RX_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 复位DMA通道
DMA_DeInit(DMA1_Channel5);
// 配置DMA初始化结构体
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rx_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BUFFER_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_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
// 初始化DMA通道
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
// 使能DMA传输完成中断
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
// 启动DMA传输
DMA_Cmd(DMA1_Channel5, ENABLE);
}存储器到存储器传输示例
#define DATA_SIZE 1024
uint32_t src_buffer[DATA_SIZE];
uint32_t dst_buffer[DATA_SIZE];
void DMA_M2M_Transfer(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 复位DMA通道
DMA_DeInit(DMA1_Channel1);
// 配置存储器到存储器传输
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)src_buffer;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)dst_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = DATA_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
// 初始化并启动DMA传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
// 等待传输完成
while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC1);
}注意事项
-
通道选择:不同外设对应特定的DMA通道,需要查阅参考手册确认正确的通道映射
-
数据对齐:确保外设和存储器的数据宽度配置正确,避免数据对齐错误
-
缓冲区大小:DMA_BufferSize的有效范围是1-65535,超出范围会导致不可预期的行为
-
循环模式限制:存储器到存储器传输不能使用循环模式
-
中断处理:使用中断时,必须在中断服务程序中清除相应的中断标志位
-
优先级冲突:多个DMA通道同时工作时,硬件优先级为DMA1 > DMA2,通道号小的优先级高
-
地址递增:根据实际需求配置地址递增模式,FIFO类外设通常不递增地址
-
传输监控:可以通过DMA_GetCurrDataCounter()函数实时监控传输进度
总结
STM32F10x DMA外设提供了强大的数据传输功能,支持外设到存储器、存储器到外设以及存储器到存储器的传输。通过合理配置DMA参数,可以大大减轻CPU负担,提高系统整体性能。DMA的关键特性包括多种传输模式、可配置的优先级、灵活的数据宽度支持以及完善的中断机制,是高效数据传输的理想选择。