全部例程

DAC - 输出正弦波

W55MH32

更新于 2026年8月12日

本篇总结

使用 DAC + DMA + TIM,输出连续正弦波形。

🔑 KEIL MDK、UART调试、DAC、DMA、TIM

W55MH32L 内置 2 个 12 位 DAC(数模转换器),可将数字值转换为模拟电压输出。本示例使用 DAC1 通道 1(PA4 引脚)配合 DMA 和 TIM2 定时器,通过 32 点正弦波查找表循环输出连续正弦波。TIM2 每次溢出触发 DAC 转换,DMA 自动将查表数据搬运到 DAC 数据寄存器,无需 CPU 干预。

前置工具准备

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

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

硬件连接

本例程使用 DAC1 的通道 1(PA4 引脚)输出模拟正弦波。PA4 配置为模拟输出模式(AIN),可通过示波器探头测量波形。USART1 用于输出调试信息。

引脚功能方向模式
PA4DAC1_OUT(正弦波输出)开发板 → 示波器模拟输入 (AIN)
PA9USART1_TX开发板 → PC复用推挽输出 (AF_PP)
PA10USART1_RXPC → 开发板浮空输入 (IN_FLOATING)

工程结构

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

DAC/
├── USER/
│   ├── main.c            ← DAC配置 + DMA配置 + TIM触发 + 正弦查表
│   ├── w55mh32_conf.h    ← 外设头文件集中包含
│   ├── w55mh32_it.c/h    ← 中断服务函数
│   ├── system_w55mh32.c/h← 系统初始化(时钟配置)
│   └── startup_w55mh32.s ← 启动文件
└── SYSTEM/
    └── delay/
        └── delay.c/h      ← SysTick 延时函数

步骤1:DAC 与 DMA 配置

函数:DAC_Configuration() — 配置 PA4 为模拟输出,DAC1 使用 TIM2 触发、12 位右对齐、使能 DMA,DMA2 Channel3 循环搬运 32 点正弦查表数据。


/* 正弦波查找表(32点,12位) */
const uint16_t Sine12bit[32] = {
    2048, 2447, 2831, 3185, 3495, 3750, 3939, 4056,
    4095, 4056, 3939, 3750, 3495, 3185, 2831, 2447,
    2048, 1648, 1264,  910,  600,  345,  156,   39,
       0,   39,  156,  345,  600,  910, 1264, 1648
};

void DAC_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef  DAC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    /* PA4: DAC1_OUT → 模拟输出 */
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* DAC1: DMA使能 + 定时器触发 + 12位右对齐 */
    DAC_InitStructure.DAC_Trigger        = DAC_Trigger_T2_TRGO;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
    DAC_InitStructure.DAC_OutputBuffer   = DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);

    /* DMA配置:内存→DAC1,循环模式 */
    DMA_DeInit(DMA2_Channel3);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR12R1;
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)Sine12bit;
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize         = 32;
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);
    DMA_Cmd(DMA2_Channel3, ENABLE);

    DAC_DMACmd(DAC_Channel_1, ENABLE);
    DAC_Cmd(DAC_Channel_1, ENABLE);
}
  

32 点正弦查找表覆盖一个完整周期,每个点为 12 位值(0~4095)。DAC 使用 DAC_Trigger_T2_TRGO(TIM2 触发),DMA 循环模式保证数据连续输出。DAC_OutputBuffer_Enable 使能内部输出缓冲器,增强驱动能力。

如果你想自定义

  • 改波形频率 → 修改 TIM2 的 TIM_Period,频率 = 72M / (Period+1) / 32
  • 改波形类型 → 替换 Sine12bit[] 为三角波、方波等查表数据
  • 改分辨率 → 修改查表点数(如 64 点、128 点),同时修改 DMA_BufferSize

步骤2:TIM2 定时触发配置

函数:TIM_Configuration() — TIM2 定时器溢出时产生 TRGO 信号触发 DAC 转换。


void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    /* TIM2 定时触发 DAC 输出 */
    /* DAC输出频率 = TIM_CLK / (Prescaler+1) / (Period+1) / 32(查表点数) */
    TIM_TimeBaseStructure.TIM_Prescaler     = 0;
    TIM_TimeBaseStructure.TIM_Period        = 225;   /* 72MHz / 226 / 32 ≈ 9.95kHz */
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
    TIM_Cmd(TIM2, ENABLE);
}
  

输出频率 = TIM_CLK / (Period+1) / 查表点数 = 72MHz / 226 / 32 ≈ 9.95kHz。TIM_TRGOSource_Update 表示每次定时器溢出(更新事件)时输出触发信号。

编译与下载

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

运行验证

下载固件并按 RESET 后,用示波器探头测量 PA4 引脚,可观察到连续的正弦波形,频率约 10kHz,峰峰值约 3.3V。串口打印系统时钟和测试提示信息。如无示波器,可用万用表测量 PA4 平均电压约为 1.65V(正弦波中点)。

由于 DAC 输出为模拟信号,需使用示波器观察波形。本例程无串口截图,请在 PA4 引脚连接示波器验证正弦波输出。

常见问题

Q: PA4 无波形输出

确认 PA4 配置为 GPIO_Mode_AIN(模拟输入模式,DAC 输出时使用此模式)。检查 DAC_Cmd(DAC_Channel_1, ENABLE) 和 DMA_Cmd(DMA2_Channel3, ENABLE) 是否调用。确认 TIM2 已使能。

Q: 波形频率不正确

输出频率 = TIM2_CLK / (Period+1) / 查表点数。TIM2 时钟为 APB1 时钟(默认 36MHz),若 APB1 预分频不为 1,则 TIM2 时钟为 APB1 × 2 = 72MHz。调整 TIM_Period 改变频率。

Q: 波形失真或有台阶

增加查表点数(如 64 点或 128 点)可提高波形精度。确保 DAC_OutputBuffer_Enable 已使能以增强驱动能力。查表数据应均匀覆盖一个完整正弦周期。

总结

本文基于 W55MH32L 的 DAC1 配合 DMA 和 TIM2 实现了正弦波输出:

  • 32点正弦查表:12 位精度(0~4095),覆盖一个完整周期
  • DMA2 Channel3 循环模式自动搬运查表数据到 DAC 数据寄存器,无需 CPU 干预
  • TIM2 定时触发:每次溢出产生 TRGO 信号触发 DAC 转换,输出频率 ≈ 10kHz
  • PA4 引脚输出连续正弦波,峰峰值约 3.3V,可通过示波器观察验证

下载本章例程

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

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

Andy

W5500 技术支持专家