当前位置: 首页 > news >正文

STM32F103 DAC双通道输出不同幅度三角波:一个定时器触发两个波形的实战配置

STM32F103 DAC双通道独立控制实战:用定时器触发实现高精度三角波输出

在工业控制、测试测量和音频处理等领域,经常需要同时生成多路独立可控的模拟信号。STM32F103系列MCU内置的双通道DAC配合定时器触发功能,为这类需求提供了经济高效的解决方案。本文将深入探讨如何利用单个定时器同步触发两个DAC通道,实现相位同步但幅度可调的三角波输出,这种技术在电机驱动测试、传感器激励信号生成等场景中尤为实用。

1. 硬件架构与工作原理

STM32F103的DAC模块包含两个独立的12位数字模拟转换器,每个转换器对应一个输出通道(PA4对应DAC1,PA5对应DAC2)。其核心特性包括:

  • 双通道独立控制:每个通道可单独配置幅度、波形和触发方式
  • 内置波形发生器:支持噪声波和三角波生成,减轻CPU负担
  • 灵活触发源:支持定时器、外部引脚和软件触发
  • 同步更新功能:确保多通道输出时序一致性

三角波生成原理如下图所示:

DAC工作流程: 定时器触发 → 三角波计数器增减 → 与DHRx值相加 → 输出到DORx → 模拟输出

关键寄存器配置要点:

寄存器关键位域配置说明
DAC_CRWAVEx[1:0]10=三角波模式
MAMPx[3:0]设置三角波峰值幅度
TENx必须置1使能触发
DAC_DHR12RDDACC1DHR/DACC2DHR双通道12位右对齐数据保持寄存器

注意:MAMPx必须在DAC使能前配置,否则无法修改。三角波实际输出值为(DHRx + 三角波计数器值) mod (MAMPx+1)

2. 工程环境搭建与基础配置

2.1 硬件连接准备

典型的最小系统连接方式:

  • PA4(DAC1_OUT) → 示波器通道1
  • PA5(DAC2_OUT) → 示波器通道2
  • 确保VREF+引脚接入稳定参考电压(通常3.3V)

2.2 软件初始化流程

以下是完整的初始化代码框架:

#include "stm32f10x.h" void DAC_TriWave_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; DAC_InitTypeDef DAC_InitStruct; TIM_TimeBaseInitTypeDef TIM_InitStruct; // 1. 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 2. GPIO配置(模拟输入模式) GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStruct); // 3. 定时器基础配置(TIM2作为触发源) TIM_InitStruct.TIM_Period = 71; // 决定波形频率 TIM_InitStruct.TIM_Prescaler = 0; TIM_InitStruct.TIM_ClockDivision = 0; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_InitStruct); TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // 4. DAC通道配置 DAC_InitStruct.DAC_Trigger = DAC_Trigger_T2_TRGO; DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_Triangle; DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // 通道1配置(全幅度) DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095; DAC_Init(DAC_Channel_1, &DAC_InitStruct); // 通道2配置(半幅度) DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_2047; DAC_Init(DAC_Channel_2, &DAC_InitStruct); // 5. 使能模块 DAC_Cmd(DAC_Channel_1, ENABLE); DAC_Cmd(DAC_Channel_2, ENABLE); TIM_Cmd(TIM2, ENABLE); }

关键参数计算公式:

  • 输出频率 = TIM2时钟 / (TIM_Period * (TIM_Prescaler+1))
  • 幅度分辨率 = VREF+ / 4095(12位模式)

3. 高级配置技巧与实战优化

3.1 双通道相位同步控制

要实现严格的相位同步,必须注意:

  1. 使用DAC_DualSoftwareTriggerCmd()同时触发双通道
  2. 或者通过TIM_SelectOutputTrigger()确保两个通道使用相同的硬件触发源
  3. 在初始化最后一步才使能定时器,避免配置过程中的误触发

3.2 动态幅度调整方案

通过修改MAMPx值实时改变波形幅度:

void Set_DAC_Amplitude(DAC_Channel_TypeDef channel, uint32_t amplitude) { DAC_InitTypeDef DAC_InitStruct; // 必须先禁用DAC才能修改MAMP DAC_Cmd(channel, DISABLE); // 重新初始化配置 DAC_InitStruct.DAC_Trigger = DAC_Trigger_T2_TRGO; DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_Triangle; DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable; DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = amplitude; DAC_Init(channel, &DAC_InitStruct); DAC_Cmd(channel, ENABLE); }

可用幅度常量(对应MAMP[3:0]):

DAC_TriangleAmplitude_1 // 2^1-1 DAC_TriangleAmplitude_3 // 2^2-1 ... DAC_TriangleAmplitude_4095 // 2^12-1 (全幅度)

3.3 输出频率精确控制

通过TIM2参数调整输出频率时需考虑:

  • APB1时钟通常为36MHz(系统时钟72MHz二分频)
  • 实际波形周期 = (TIM_Period+1) * (TIM_Prescaler+1) / APB1_clock
  • 最小间隔需大于3个APB1周期(DAC硬件限制)

示例频率配置表:

目标频率TIM_PrescalerTIM_Period实际频率
100kHz0359100kHz
10kHz0359910kHz
1kHz359991kHz

4. 常见问题排查与性能优化

4.1 典型问题诊断

  1. 无输出信号

    • 检查GPIO是否配置为模拟输入模式
    • 确认TIM2和DAC时钟已使能
    • 测量VREF+电压是否正常
  2. 波形失真

    • 确保TIM_Period值≥3(满足DAC硬件要求)
    • 尝试启用输出缓冲(DAC_OutputBuffer_Enable)
    • 检查电源稳定性,必要时增加滤波电容
  3. 通道间相位差

    • 使用DAC_DualSoftwareTriggerCmd()强制同步
    • 检查是否意外修改了DAC_CR的TENx位

4.2 性能优化建议

  • 降低CPU干预:配置DMA自动更新DHR寄存器
  • 提高精度:校准VREF+电压,使用12位右对齐模式
  • 多通道扩展:通过外部运放组合多个DAC输出
  • 低功耗设计:在波形稳定后关闭TIM2时钟

实际项目中,我在电机测试平台上使用这种配置时发现,当需要生成高频信号(>50kHz)时,建议:

  1. 将TIM_Prescaler设为0以获得最高定时器分辨率
  2. 适当降低MAMP值可以提高三角波斜率
  3. 禁用所有未使用的外设时钟以减少噪声干扰
http://www.jsqmd.com/news/680006/

相关文章:

  • Carsim联合仿真避坑指南:为什么你的Simulink控制信号没生效?可能是输入模块的Initial Value在搞鬼
  • 基于DSP28335的三电平有源电力滤波器方案:全套软硬件资料,直接量产的智能化电力管理方案
  • 网盘下载加速神器完全指南:解锁八大平台直链获取的终极方案
  • Windows/Mac/Linux三平台通用!EISeg图像标注工具保姆级安装教程(附模型下载)
  • 手把手教你配置UART:9600 8N1模式下的数据传输实战(含示波器截图)
  • 我的MX450跑AI:从安装Pytorch-GPU到跑通第一个模型的完整记录(Win10 + CUDA 11.1)
  • 3分钟免费AI语音修复终极指南:让模糊录音变清晰的VoiceFixer
  • 从单层感知机到MLP:为什么加了几层‘隐层’,AI就突然开窍了?
  • 2026年比较好的实木运动木地板公司哪家好 - 行业平台推荐
  • 从立创EDA到AD20:一个PCB新手的完整避坑与实战布局指南
  • 基于 MATLAB 实现的二值图像中的信息隐藏
  • 从调频信号(Chirp)到故障诊断:手把手教你用MATLAB玩转瞬时频率分析
  • 2026年Q2聚氨酯砂浆彩砂地面采购指南:固耐特聚氨酯砂浆、广东固耐特、广州固耐特、聚氨酯砂浆地坪厂家、聚氨酯砂浆地坪材料选择指南 - 优质品牌商家
  • 从Transformer到AI Agent的深度解析,带你领略大型语言模型的核心技术!
  • STM32H7的USB虚拟串口,从CubeMX配置到Python测速,保姆级避坑指南
  • # 发散创新:基于Python的虚拟原型快速构建实践与实战代码解析在现代软件开发流程中,**虚拟原型(Virtual Prototy
  • 2026年4月燕窝十大品牌盘点:燕窝品牌、东南燕都、官燕苑常温鲜炖燕窝、官燕苑燕窝、官燕苑现炖燕窝、官燕苑生态燕窝选择指南 - 优质品牌商家
  • 宝塔面板无法识别数据库配置_检查配置文件是否存在乱码
  • 从面试题到Verilog实战:用两个半加器搭建全加器的完整思路与代码
  • Java工程师正在悄悄淘汰ThreadPoolExecutor?Loom响应式编程准入门槛已降至3天,你还在手动管理Future吗?
  • 好的推客系统,让商家越做越轻松
  • 手机拍HDR总有重影?聊聊动态场景多帧融合的演进与手机摄影中的实际应用
  • 如果外星人用‘微信’:从射电信号到中微子通信,地外文明可能用什么技术?
  • 从电路图到代码:蓝桥杯开发板外设(LED/数码管/电机)控制逻辑全梳理
  • 从‘NoneType‘错误看Python代码健壮性:我的5个防御性编程习惯
  • 用Verilog HDL手把手教你实现半加器和全加器(附完整代码和仿真测试)
  • Java 25虚拟线程上线即崩?:4个被官方文档隐瞒的JVM参数配置雷区与72小时热修复方案
  • STM32F405RG主频降到84MHz才稳定?聊聊MotorControl Workbench工程里那些硬件坑
  • Rdkit|分子可视化实战:从基础绘制到批量生成与3D展示
  • 避坑指南:OpenFOAM造波算例初始场设置常见错误与setFields替代方案