全部例程

DMA

W55MH32

更新于 2026年8月12日

本篇总结

使用 DMA,实现内存到内存的数据搬运。

🔑 KEIL MDK、UART调试、DMA

W55MH32L 内置 12 通道 DMA 控制器,支持外设到内存、内存到外设和内存到内存三种传输模式。本示例演示内存到内存的数据搬运,32 个 32 位数据通过 DMA 自动传输。

前置工具准备

开始本例程前,请确认以下工具已安装:

  • WIZ UartTool V1.0:串口收发测试工具:点击下载

硬件连接

本例程为内存到内存传输,无需外部硬件连接。USART1 用于输出传输结果。

引脚功能方向模式
PA9USART1_TX开发板 → PC复用推挽输出 (AF_PP)
PA10USART1_RXPC → 开发板浮空输入 (IN_FLOATING)

工程结构

工程位于 SDK 内 1.SDK\ModuleDemo\DMA\,核心文件如下:

DMA/
├── USER/
│   ├── main.c            ← DMA配置 + 内存到内存传输 + 数据验证
│   ├── w55mh32_conf.h    ← 外设头文件集中包含
│   ├── w55mh32_it.c/h    ← 中断服务函数(DMA传输完成中断)
│   ├── system_w55mh32.c/h← 系统初始化(时钟配置)
│   └── startup_w55mh32.s ← 启动文件
└── SYSTEM/
    └── delay/
        └── delay.c/h      ← SysTick 延时函数

步骤1:DMA 配置与传输完成中断

函数:DMA_Configuration() — 配置 DMA1 Channel1 为内存到内存传输,32 个 32 位数据,传输完成后触发中断验证数据。


#define BUFFER_SIZE 32

uint32_t SRC_Buffer[BUFFER_SIZE] = {
    0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
    0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
    0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
    0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
    0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
    0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
    0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
};
uint32_t DST_Buffer[BUFFER_SIZE];

void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    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         = BUFFER_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_High;
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Enable;

    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    /* 传输完成中断 */
    NVIC_InitStructure.NVIC_IRQChannel                   = DMA1_Channel1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

    DMA_Cmd(DMA1_Channel1, ENABLE);
}

void DMA1_Channel1_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA1_IT_TC1) != RESET)
    {
        DMA_ClearITPendingBit(DMA1_IT_TC1);
        printf("DMA Transfer Complete!\n");

        /* 验证数据 */
        uint8_t i, match = 1;
        for (i = 0; i < BUFFER_SIZE; i++)
        {
            if (DST_Buffer[i] != SRC_Buffer[i])
            {
                match = 0;
                break;
            }
        }
        printf("Data %s\n", match ? "Match!" : "Mismatch!");
    }
}
  

关键配置:DMA_M2M_Enable 使能内存到内存模式(此时外设地址实际为源内存地址),DMA_Mode_Normal 单次传输模式(传输一次后停止),源地址和目标地址均自增,数据宽度为 32 位字。传输完成中断中逐字对比源数据和目标数据。

如果你想自定义

  • 改传输数据量 → 修改 BUFFER_SIZE 和源数据数组
  • 改为循环传输 → 将 DMA_Mode_Normal 改为 DMA_Mode_Circular
  • 改数据宽度 → 选择 Byte(8位)、HalfWord(16位) 或 Word(32位)

编译与下载

Keil MDK 中打开 DMA.uvprojxF7 编译,确认 0 Error(s)。连接 DEBUG USB 口到 PC,F8 下载。

运行验证

打开 WIZ UartTool V1.0,波特率 115200 / 8N1。下载固件并按 RESET 后,串口打印 "DMA Transfer Complete!" 和 "Data Match!",表示 32 个 32 位数据已成功从源地址搬运到目标地址且数据一致。

DMA内存到内存传输串口输出
WIZ UartTool V1.0 显示 DMA 传输完成和数据验证结果

常见问题

Q: DMA 传输完成后数据不匹配

检查源地址和目标地址是否正确设置,数据宽度是否一致(Word/HalfWord/Byte)。确认源地址和目标地址都使能了自增(DMA_PeripheralInc_Enable 和 DMA_MemoryInc_Enable)。

Q: DMA 传输完成中断不触发

确认 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE) 已调用。检查 NVIC 中断是否使能,中断服务函数名是否正确(DMA1_Channel1_IRQHandler)。

Q: 内存到内存模式不工作

内存到内存模式必须设置 DMA_M2M_Enable。注意 M2M 模式下不能使用循环模式与外设请求,传输由软件启动(DMA_Cmd 使能后立即开始)。

总结

本文基于 W55MH32L 的 DMA1 控制器实现了内存到内存的数据搬运:

  • DMA1 Channel1 配置为内存到内存模式,32 个 32 位数据自动搬运
  • 单次传输模式(Normal),传输一次后自动停止
  • 传输完成中断中逐字对比源数据和目标数据,验证数据完整性
  • W55MH32L 内置 12 通道 DMA 控制器,支持外设到内存、内存到外设和内存到内存三种模式

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5 配套开发板

Andy

W5500 技术支持专家