STM32F103 DAC双通道实战同步触发下的差异化三角波输出在嵌入式信号生成领域STM32F103的DAC功能常被低估。许多开发者仅停留在单通道基础波形输出的阶段却不知其双通道DAC能实现更复杂的信号组合。本文将揭示如何通过TIM2同步触发两个DAC通道在PA4和PA5引脚上输出频率相同但幅度各异的三角波——这种技术在差分信号模拟、双路可调电源等场景中具有重要应用价值。1. 硬件架构与寄存器精要1.1 双DAC通道的物理特性STM32F103C8T6芯片内置两个独立的12位DAC转换器分别对应GPIOA的PA4(DAC1)和PA5(DAC2)引脚。关键特性包括独立数据寄存器DAC_DHR12R1/DAC_DHR12R2联合数据寄存器DAC_DHR12RD支持双通道同步写入触发源共享支持TIM2/4/6/7、EXTI线9等触发源注意使用前必须将GPIO配置为模拟输入模式(GPIO_Mode_AIN)否则输出将被阻断。1.2 三角波生成原理DAC内置的三角波发生器通过以下寄存器协同工作寄存器位功能描述配置要点DAC_CR.TENx触发使能位必须置1才能启动波形生成DAC_CR.WAVEx波形选择(10三角波)通道独立配置DAC_CR.MAMPx幅度控制(0000-1111)决定峰值电压对应的计数值三角波实际输出值遵循公式DORx (DHRx 三角波计数器) mod (MAMPx 1)2. 同步触发系统搭建2.1 定时器TIM2配置作为公共触发源TIM2需要精确计算周期。假设我们需要输出1kHz三角波每个周期256步TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Prescaler 72 - 1; // 72MHz/72 1MHz TIM_InitStruct.TIM_Period 4 - 1; // 1MHz/4 250kHz触发频率 TIM_InitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_InitStruct); TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);2.2 双通道DAC初始化关键配置差异体现在幅度设置DAC_InitTypeDef DAC_InitStruct; DAC_InitStruct.DAC_Trigger DAC_Trigger_T2_TRGO; DAC_InitStruct.DAC_WaveGeneration DAC_WaveGeneration_Triangle; DAC_InitStruct.DAC_OutputBuffer DAC_OutputBuffer_Disable; // 通道1配置4095对应3.3V DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude DAC_TriangleAmplitude_4095; DAC_Init(DAC_Channel_1, DAC_InitStruct); // 通道2配置2047对应1.65V DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude DAC_TriangleAmplitude_2047; DAC_Init(DAC_Channel_2, DAC_InitStruct);3. 数据写入与同步控制3.1 双通道数据寄存器操作推荐使用联合数据寄存器实现原子操作// 同时设置两个通道的初始值12位右对齐 DAC_SetDualChannelData(DAC_Align_12b_R, 0, 0);等效的寄存器级操作为DAC-DHR12RD ((uint32_t)ch2_value 16) | (uint32_t)ch1_value;3.2 相位同步技巧通过调整DHRx初始值可实现相位差// 通道2滞后90度256步周期的1/4 DAC_SetChannel2Data(DAC_Align_12b_R, 64);4. 调试与性能优化4.1 示波器观测要点触发模式设为正常而非自动时基调整到能显示5-10个完整周期使用XY模式可观察李萨如图形4.2 常见问题排查表现象可能原因解决方案无输出GPIO未配置为AIN模式检查GPIO_Init配置波形不连续触发频率过高增大TIM2周期值幅度不符MAMPx配置后未禁用TENx修改按顺序配置MAMP→TEN→触发使能通道间不同步未使用DHR12RD寄存器改用双通道联合写入4.3 动态调整技巧运行时修改幅度需临时禁用触发DAC-CR ~DAC_CR_TEN1; // 禁用通道1触发 DAC-CR | DAC_CR_MAMP1_2 | DAC_CR_MAMP1_0; // 新幅度设置(51023) DAC-CR | DAC_CR_TEN1; // 重新使能触发通过CubeMX生成的代码往往缺少这种精细控制能力这正是寄存器级操作的价值所在。我在设计可编程信号源时发现配合DMA还能实现更复杂的波形序列——但这需要另辟专题讨论了。