全部例程

DAC-输出正弦波

W55MH32

更新于 2026年8月27日

本篇总结

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

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

硬件平台:本例程基于 W55MH32L-EVB 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W55MH32L-EVB

本示例演示 W55MH32 内置 DAC 的使用,通过 DAC 双通道(PA4 + PA5 引脚)配合 DMA 和 TIM2 定时器,通过 32 点正弦波查找表循环输出连续正弦波。TIM2 每次溢出触发 DAC 转换,DMA 自动将双通道查表数据搬运到 DAC 数据寄存器,无需 CPU 干预。

前置工具准备

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

硬件连接

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

引脚功能方向模式
PA4DAC1_OUT(正弦波输出)开发板 → 示波器模拟输入 (AIN)
PA5DAC2_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:GPIO 与 DAC 配置

函数:GPIO_Configuration() + DAC_Configuration() — 配置 PA4/PA5 为模拟输出,DAC 双通道均使用 TIM2 触发、12 位右对齐、使能 DMA。

/* 正弦波查找表(32点,12位) */
uint16_t Sine12bit[POINT_NUM] = {
    2048, 2460, 2856, 3218, 3532, 3786, 3969, 4072,
    4093, 4031, 3887, 3668, 3382, 3042, 2661, 2255,
    1841, 1435, 1054,  714,  428,  209,   65,    3,
      24,  127,  310,  564,  878, 1240, 1636, 2048
};

/* 双通道合并数据(高16位=DAC2,低16位=DAC1) */
uint32_t DualSine12bit[POINT_NUM];

/* DAC 寄存器地址宏 */
#define DAC1_DHR12RD_ADDRESS (DAC_BASE + 0x00000008 + DAC_Align_12b_R)
#define DAC2_DHR12RD_ADDRESS (DAC_BASE + 0x00000014 + DAC_Align_12b_R)

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* PA4 + PA5: DAC1_OUT + DAC2_OUT → 模拟输出 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void DAC_Configuration(void)
{
    DAC_InitTypeDef DAC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    /* DAC1 + DAC2: DMA使能 + TIM2触发 + 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);
    DAC_Init(DAC_Channel_2, &DAC_InitStructure);

    DAC_Cmd(DAC_Channel_1, ENABLE);
    DAC_Cmd(DAC_Channel_2, ENABLE);

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

32 点正弦查找表覆盖一个完整周期,每个点为 12 位值(0~4095)。双通道输出时,将同一正弦波数据合并到 32 位整数 DualSine12bit 中(高 16 位对应 DAC2,低 16 位对应 DAC1),由 main() 中的合并循环完成:DualSine12bit[i] = (Sine12bit[i] << 16) + Sine12bit[i]

如果你想自定义

  • 改波形频率 → 修改 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 / (Period+1) / 32(查表点数) */
    TIM_TimeBaseStructure.TIM_Period        = (20 - 1);  /* 72MHz / 20 / 32 = 112.5kHz */
    TIM_TimeBaseStructure.TIM_Prescaler     = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    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 / 20 / 32 = 112.5kHz。TIM_TRGOSource_Update 表示每次定时器溢出(更新事件)时输出触发信号。

步骤3:DMA 双通道搬运配置

函数:DMA_Configuration() — 配置 DMA2 通道 3 和通道 4,分别将双通道查表数据循环搬运到 DAC1 和 DAC2 的数据寄存器。

void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

    /* DMA2 Channel4 → DAC2 (PA5) */
    DMA_InitStructure.DMA_PeripheralBaseAddr = DAC2_DHR12RD_ADDRESS;
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)&DualSine12bit;
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize         = POINT_NUM;
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    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_Circular;
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;

    DMA_Init(DMA2_Channel4, &DMA_InitStructure);
    DMA_Cmd(DMA2_Channel4, ENABLE);

    /* DMA2 Channel3 → DAC1 (PA4) */
    DMA_InitStructure.DMA_PeripheralBaseAddr = DAC1_DHR12RD_ADDRESS;
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);
    DMA_Cmd(DMA2_Channel3, ENABLE);
}
  

DMA2 通道 4 对应 DAC2(PA5),通道 3 对应 DAC1(PA4)。两个通道均使用循环模式(DMA_Mode_Circular),数据宽度为 32 位(Word),因为 DualSine12bit 是 32 位数组(高 16 位 = DAC2,低 16 位 = DAC1)。

运行验证

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

由于 DAC 输出为模拟信号,需使用示波器观察波形。请在 PA4 和 PA5 引脚分别连接示波器验证双通道正弦波输出。

串口打印系统时钟和测试提示信息

常见问题

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 已使能以增强驱动能力。查表数据应均匀覆盖一个完整正弦周期。

总结

本文基于 W55MH32 的 DAC 双通道(DAC1 + DAC2)配合 DMA 和 TIM2 实现了双路正弦波输出:

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

下载本章例程

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

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

Andy

W5500 技术支持专家