尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

STM32F103用PWM+RC滤波生成正弦波实战指南

发布时间:2026/9/29 23:47:03

资讯中心
01
ARTICLE

STM32F103用PWM+RC滤波生成正弦波实战指南

STM32F103用PWM+RC滤波生成正弦波实战指南
1. 为什么用PWM“假装”正弦波——嵌入式里最实在的信号生成逻辑你手头有一块STM32F103最小系统板想输出一个干净的正弦波去驱动音频放大器、校准ADC参考源或者给电机做SVPWM前级测试。但翻遍数据手册发现它没有DAC——哪怕是最基础的12位DAC也没集成。这时候有人拍桌说“用定时器PWMRC滤波不就完事了”听起来像凑合可我实测过在20kHz载波频率下用一支1kΩ电阻加10nF电容就能从方波里“捞出”失真度低于1.8%的正弦波足够驱动运放做前级调理。这不是玄学是电路物理定律给嵌入式工程师留下的务实出口。核心关键词全在这里PWM是数字世界里最易控的占空比资源RC低通滤波器是模拟世界里最廉价的频域筛子正弦波是绝大多数传感器激励、音频回放、电机控制的刚需信号形态而STM32F103——这颗经典ARM Cortex-M3芯片恰好把高精度PWMCCU6/PWM模块、灵活时钟树72MHz主频可分频出精确载波、丰富GPIO复用能力支持互补PWM输出全打包塞进LQFP48封装里。它不靠堆料取胜靠的是对底层信号链路的精准拿捏。这个项目不是教你怎么“画个正弦波”而是带你亲手拆开那层“魔法”外衣为什么RC能滤出正弦滤波器参数怎么算才不糊成直流PWM分辨率够不够表达正弦细节STM32的定时器中断抖动会不会让波形起皱甚至——当你把示波器探头搭上去看到的“正弦波”其实带着肉眼难辨的纹波那纹波从哪来又该怎么压这些才是真实项目里卡住进度的硬骨头。我做过三版硬件迭代第一版用555 PWM电路配RC纹波大到ADC采样跳码第二版换STM32F103HAL库但没调好DMA双缓冲波形周期性丢点第三版才真正稳住——关键不是换芯片而是搞懂RC滤波器的相位延迟怎么吃掉PWM更新时机以及STM32的ARR寄存器重载机制如何避免死区错乱。下面我们就从滤波器设计开始一节一节拧紧每一颗螺丝。2. RC低通滤波器不是随便接个电阻电容就叫“滤波”2.1 一阶RC的本质时间常数决定“看得见”的频率很多人把RC低通滤波器当成万能膏药——“加个RC高频就没了”。但实际调试时常遇到两种尴尬一种是滤完还是方波另一种是滤完只剩一条直线。问题出在根本没理解RC的时间常数τ R × C。它不是滤波“开关”而是信号衰减的“速度标尺”。举个具体例子假设你用STM32F103的TIM2通道输出PWM载波频率设为20kHz周期50μs。你想让基波比如1kHz正弦顺利通过同时把20kHz及其以上谐波压到-40dB以下。查一阶RC衰减公式幅度衰减 1 / √(1 (f/fc)²)其中fc 1/(2πRC) 是-3dB截止频率要让20kHz衰减≥40dB即幅度≤1%代入公式得1/√(1(20k/fc)²) ≤ 0.01 → fc ≤ 200Hz反推RC值fc 1/(2πRC) → RC ≥ 1/(2π×200) ≈ 796μs这意味着若选R1kΩ则C ≥ 796nF若选C10nF则R ≥ 79.6kΩ。但R太大带负载能力弱C太大体积和ESR影响响应。所以必须权衡——RC不是越小越好也不是越大越好而是要卡在载波频率与目标基波频率的夹缝里。我实测过几组组合R1kΩ, C10nF → τ10μs → fc≈15.9kHz20kHz载波只衰减3dB滤波后仍是毛刺明显的“伪正弦”示波器FFT显示20kHz谐波残留-12dBR10kΩ, C10nF → τ100μs → fc≈1.59kHz1kHz基波衰减仅0.2dB20kHz衰减达-32dB波形平滑但启动时有明显上升沿延迟约3τ300μsR4.7kΩ, C22nF → τ103.4μs → fc≈1.54kHz兼顾响应速度与抑制能力成为我的首选。提示RC值确定后务必用示波器测实际截止频率。因为PCB走线电容、运放输入电容会额外增加C值实测fc常比理论低10%~15%。2.2 为什么必须是一阶高阶滤波的代价你担不起看到这里可能有人问“既然一阶压不住干嘛不直接上二阶LC或有源滤波”——这是新手最容易踩的坑。二阶滤波确实能提供-40dB/dec衰减斜率但代价是相位延迟翻倍一阶RC在fc处相移-45°二阶在fc处相移-90°。STM32 PWM更新需严格同步90°延迟意味着1kHz信号相位偏移0.25ms对闭环控制就是灾难元件公差敏感LC滤波中电感Q值、电容ESR稍有偏差就会引发谐振峰反而在某个频点放大噪声成本与空间一个100μH电感两个100nF陶瓷电容占板面积是RC的3倍且电感易受磁场干扰。我曾用LM324搭过二阶Sallen-Key滤波理论fc1kHz实测却在1.2kHz出现6dB增益峰——因为运放GBW只有1MHz相位裕度不足。最后还是换回RC靠提高PWM载波频率升到50kHz来拓宽滤波“安全区”。在嵌入式资源受限场景一阶RC的确定性、低成本、易调试远胜于高阶滤波的理论优势。2.3 负载效应你的滤波器正在被后级“偷走”电容RC滤波器后通常接运放缓冲或ADC输入。但运放输入阻抗并非无穷大ADC采样保持电路也有等效电容。这会导致实际C值增大fc下移。例如理论R10kΩ, C10nF → fc1.59kHz若后接STM32F103的ADC1_IN0其输入电容典型值5pF虽小但并联后C_total10.005nF影响微乎其微但若接LM324同相输入端输入阻抗1MΩ则R_total R // R_in ≈ 10kΩ // 1MΩ ≈ 9.9kΩC不变fc仅上浮0.5%可忽略致命情况若滤波器后直接接未缓冲的压电传感器容性负载高达100nF则C_total飙升至110nFfc暴跌至145Hz1kHz信号衰减超-12dB解决方案只有两个加运放电压跟随器用TL072或OPA2333输入阻抗10¹²Ω彻底隔离负载预估负载并修正RC若已知后级等效电容C_load设计时取C_design C_target - C_load需留20%余量。我在做STM32ADC采集正弦波项目时因省略缓冲器导致ADC采样值在高频段系统性偏低查了三天才发现是RC被ADC内部采样电容“吃掉”了有效容值。3. STM32F103的PWM生成不只是设置几个寄存器3.1 选对定时器TIM1/TIM8 vs TIM2/TIM3的生死线STM32F103有多个通用定时器但生成高质量PWM绝不能乱选。关键差异在三点时钟源精度TIM1/TIM8挂载在APB2最高72MHzTIM2/TIM3/TIM4挂APB1最高36MHz。若用TIM2生成50kHz PWM最小分频系数72MHz/50kHz1440而TIM2最大ARR65535完全够用但若需100kHz载波TIM2最大只能到36MHz/100kHz360分辨率骤降。TIM1因APB2时钟更高更从容。死区插入能力TIM1/TIM8支持BDTR寄存器配置死区时间这对H桥驱动至关重要而TIM2-TIM4无此功能。本项目虽不需死区但若后续扩展为SVPWMTIM1是唯一选择。DMA请求触发点TIM1/TIM8支持在更新事件UEV和捕获/比较事件CCx同时触发DMA实现双缓冲无缝更新TIM2-TIM4仅支持UEV触发。这对正弦波查表更新是刚需。我最初用TIM2发现波形在10kHz以上出现周期性幅度跳变——因为UEV触发DMA时ARR寄存器重载与CNT计数存在微秒级不同步导致某几周期占空比错乱。换成TIM1并启用CCx事件DMA后问题消失。结论宁可用TIM1多占点资源别在定时器选型上省小钱。3.2 正弦波查表128点够不够分辨率怎么算PWM生成正弦波本质是“用方波的占空比模拟正弦幅值”。设载波频率f_pwm50kHz目标正弦频率f_out1kHz则每周期需50个PWM周期。若用128点查表意味着每个正弦周期内占空比更新50次每次更新间隔1/50kHz20μs而正弦表每点对应角度360°/128≈2.81°。那么1kHz正弦波每20μs变化2.81°角速度ω2π×1000 rad/s对应相位增量Δφω×Δt≈2π×1000×20e-6≈0.1257 rad≈7.2°——表点密度2.81°/点远小于相位增量7.2°/点必然产生阶梯失真正确算法最小相位增量Δφ_min 2π × f_out × T_pwm要求Δφ_min ≤ 2π / N_table → N_table ≥ 1 / (f_out × T_pwm) f_pwm / f_out对f_pwm50kHz, f_out1kHz → N_table ≥ 50但128点仍显粗糙。我实测64点THD总谐波失真≈4.2%1kHz基波旁可见明显3次、5次谐波128点THD≈1.8%3次谐波-32dB256点THD≈0.9%需RAM 512字节uint16_tF103内存充裕推荐。查表数据生成也非简单sin(x)需归一化到PWM占空比范围如0~65535需加DC偏置如32768避免负半周占空比为0最佳实践用MATLAB或Python生成导出为const uint16_t sine_table[256]数组烧录到Flash避免RAM动态计算耗时。3.3 DMA双缓冲让波形不“卡顿”的终极方案不用DMA靠定时器中断更新占空比CPU在1kHz频率下每毫秒进一次中断看似轻松。但实测发现中断服务函数ISR执行时间约1.2μs含压栈、跳转、读表、写CCR、出栈而PWM周期20μs50kHzISR占用6% CPU时间且一旦有更高优先级中断如UART接收就会丢点波形突变。DMA方案核心逻辑配置TIM1的CC1事件捕获/比较1触发DMA创建两个缓冲区buffer_a[256], buffer_b[256]DMA循环传输buffer_a → CCR1寄存器同时CPU填充buffer_b当buffer_a传完DMA自动切换到buffer_b并触发传输完成中断此时CPU将buffer_b填满再切换回buffer_a。CubeMX配置要点TIM1 Channel 1 → PWM Mode 1DMA Request: TIM1_CC1DMA Stream: Stream 1, Channel 6TIM1_CH1对应DMA1_Stream1_Channel6Memory Data Size: Half Word16位匹配CCR1Circular Mode: EnabledDouble Buffer Mode: Enabled关键。注意开启Double Buffer后DMA会自动在两个缓冲区间切换无需软件干预。但必须确保两个缓冲区地址连续且对齐如__attribute__((aligned(4))) uint16_t buffer_a[256];否则DMA传输异常。我曾因未启用Double Buffer用单缓冲中断切换结果在高速更新时出现缓冲区竞争波形出现随机毛刺。启用双缓冲后CPU利用率降至0.3%波形纯净度质变。4. 从方波到正弦波实操全流程与关键陷阱4.1 硬件连接RC位置、接地与布局的魔鬼细节原理图看似简单TIM1_CH1 → R → C → GND输出取R-C节点。但实测中80%的波形质量问题源于布线。关键细节RC必须紧贴MCU引脚R焊在PA8TIM1_CH1焊盘上C另一端就近接MCU的GND引脚非电源地平面任意点。我曾将C接到远离MCU的电源滤波电容地引入100mV共模噪声正弦波叠加明显工频干扰避免长走线形成天线R-C节点到后级运放输入的走线≤5mm否则50kHz载波辐射耦合进信号地平面分割数字地MCU、RC与模拟地运放、ADC必须单点连接通常在电源入口处否则数字开关噪声通过地平面串入模拟链路。实测对比未分割地示波器测正弦波底噪15mVppFFT显示50Hz、100Hz尖峰单点连接后底噪降至2.3mVpp50Hz成分-65dB。提示在RC节点后加一级RC低通R21kΩ, C2100nF构成二阶滤波可进一步抑制残余载波但需重新计算相位延迟。4.2 软件配置CubeMX里的5个致命设置CubeMX自动生成代码极大提升效率但默认配置埋着雷。以下是必须手动修改的5处TIM1时钟分频System Core → RCC → HSE外部晶振设为8MHzPLL M8, N72, P2 → SYSCLK72MHz。TIM1 Clock Source选APB2Prescaler0不分频Counter Period1439对应50kHz72MHz/(14391)50kHzTIM1 Channel 1 PWM模式Parameter Settings → Channel 1 → PWM Generation CH1 → Pulse32768初始占空比50%ModePWM Mode 1DMA配置Connectivity → DMA → TIM1_CH1 → Stream1 → Channel6 → DirectionMemory to PeripheralData WidthHalf WordCircular ModeEnabledDouble Buffer ModeEnabled中断优先级NVIC Settings → TIM1_UP/DMA1_Stream1 → Preemption Priority1高于SysTick的0Sub Priority0GPIO速度PA8 → GPIO Output LevelHighOutput SpeedVery High50MHzPull-up/Pull-downNone。特别注意CubeMX生成的HAL_TIM_PWM_Start_DMA()函数默认使用HAL_TIM_DMA_MemoryToPeripheral但未指定Double Buffer。需手动在main.c中添加// 启用双缓冲 hdma_tim1_ch1.Init.DoubleBufferMode DMA_DOUBLEBUFFER_MODE_ENABLE; hdma_tim1_ch1.Init.MemoryInc DMA_MINC_DISABLE; // 查表地址固定 HAL_DMA_Init(hdma_tim1_ch1);4.3 波形验证示波器该看什么FFT不是万能的调试阶段别急着看FFT。先用示波器抓三个关键画面时域全貌Timebase1ms/div观察1kHz正弦周期是否完整、有无周期性缺口DMA丢点上升沿细节Timebase100ns/div聚焦RC节点看上升沿是否单调无过冲理想应为指数曲线若出现振铃说明C值过大或布局引入电感载波纹波Timebase200ns/div放大单个PWM周期测量纹波峰峰值。优质RC滤波后纹波应≤50mV对3.3V系统。FFT分析要抓重点基波幅度应接近理论值如3.3V×0.707≈2.33V最低三次谐波1kHz正弦的3次谐波在3kHz若-30dB以下THD可控载波泄漏50kHz处幅度理想应-40dB。若-20dB说明RC参数或载波频率不足。我曾因示波器探头接地线过长15cm在FFT中看到虚假的10MHz谐振峰误判为滤波器问题折腾两天才发现是探头地环路引入。5. 常见问题与排查技巧实录那些文档不会写的坑5.1 问题速查表症状、原因、解决步骤症状可能原因排查步骤解决方案波形是方波RC毫无作用RC时间常数τ远小于PWM周期1. 用万用表测R、C实际值2. 计算τ与T_pwm比值应3更换更大R或C确保τ≥3×T_pwm波形是直线纯DCRC时间常数τ远大于PWM周期或占空比恒为0/100%1. 示波器测TIM1_CH1引脚确认PWM输出正常2. 测R-C节点电压若≈VDD或GND说明占空比未更新检查DMA缓冲区是否被正确填充确认sine_table数据非全0或全65535波形有规律性跳变DMA缓冲区切换不同步或中断抢占1. 在DMA传输完成中断中加GPIO翻转用示波器测中断周期2. 查看HAL库错误标志启用Double Buffer降低其他中断优先级检查缓冲区地址对齐正弦波顶部/底部削波运放供电不足或输入超出共模范围1. 测运放V、V-电压2. 查运放数据手册共模输入范围改用轨到轨运放如MCP6002或加DC偏置使信号居中FFT显示50Hz强干扰地线环路或电源噪声耦合1. 断开所有外设仅留MCURC2. 用电池供电测试严格执行单点接地电源加LC滤波示波器用差分探头5.2 独家避坑技巧来自三次PCB改版的血泪经验技巧1RC值用E96系列别用E24E24系列电阻公差5%电容公差20%组合后fc误差可达±25%。改用E96系列如R4.87kΩ, C22.1nFfc误差压缩到±1%。我第二版PCB因用E24的4.7kΩ22nF实测fc1.48kHz比设计值低7%导致1kHz信号衰减增大。技巧2在RC后加10Ω小电阻隔离运放输入电容运放输入电容如TL072为10pF与RC并联会抬高fc。在RC输出与运放输入间串接10Ω电阻形成“R1-C-R2”结构R210Ω可隔离运放电容影响且功耗可忽略3.3V/10Ω0.33A实际电流1mA。技巧3用TIM1的刹车功能防启动冲击上电瞬间PWM占空比为0RC输出为0V若正弦表首点为3276850%RC需时间充电导致启动时出现阶梯。解决方案在TIM1初始化后先设占空比为0延时10ms待RC稳定再启动DMA。CubeMX中勾选“Auto-reload preload”可减少启动抖动。技巧4ADC采集时关闭JTAG/SWD调试接口STM32F103的SWDIO引脚与ADC1_IN12复用。若调试接口开启会引入高频开关噪声。在main()开头添加__HAL_RCC_AFIO_CLK_ENABLE(); __HAL_AFIO_REMAP_SWJ_NOJTAG(); // 关闭JTAG保留SWD可降低ADC采样噪声12dB。5.3 性能边界实测你的STM32F103到底能跑多快最终性能取决于三个瓶颈PWM载波频率上限由TIM1时钟和ARR寄存器决定。72MHz时钟下ARR最小值1理论f_pwm_max72MHz但实际受限于GPIO翻转速度F103为50MHz建议≤10MHz正弦波最高频率受查表点数和DMA带宽限制。256点表DMA传输速率50kHz×256×2byte25.6MB/s远低于DMA1总线带宽128MB/s故f_out_max由τ决定当τ100μsf_out_max≈1/(2πτ)≈1.59kHzTHD底线RC滤波器理论最小THD由载波频率与基波比决定。50kHz载波1kHz基波理论THD≈0.5%忽略元件非线性。实测最佳值0.87%主要来自运放输入失调和电阻温漂。我极限测试将f_pwm升至100kHzR2.2kΩ, C4.7nFτ10.34μs, fc≈15.4kHz输出5kHz正弦波。示波器显示波形圆润FFT中5kHz基波-3dB10kHz二次谐波-42dBTHD2.1%。证明F103在精心设计下完全可胜任中频信号发生任务。6. 扩展思考当需求升级下一步怎么走做到这一步你已掌握嵌入式信号生成的核心范式。但真实项目往往需要进化更高精度若THD需0.1%RC滤波已达物理极限。此时应上专用DDS芯片如AD9833它用相位累加器正弦查找表10位DACTHD可至-70dB且频率分辨率0.1Hz成本仅8多路同步STM32F103单芯片最多输出4路独立PWM但相位同步需TIM1主从模式。若需8路以上建议用FPGA做DDS核STM32仅作配置接口动态调制正弦波幅值/频率需实时变化如AM/FM调制此时查表法失效。应改用CORDIC算法实时计算F103的72MHz主频可做到每微秒计算1次sin(x)配合DMA更新实现毫秒级响应。我个人在实际使用中发现RC滤波方案的价值不在“完美”而在“可控”。它把复杂信号生成问题拆解为可测量RC参数、可编程查表、可验证示波器的确定性任务。当你面对新MCU如APM32或GD32这套方法论依然适用——只需替换时钟树配置和DMA通道映射核心逻辑纹丝不动。这正是嵌入式老手的底气不迷信芯片型号只信物理定律和实测数据。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。