
简介本资源是一份面向高校电力电子方向本科生的毕业设计与课程设计实践资料聚焦STM32微控制器在DCM断续导通模式下对BUCK降压变换器的闭环控制实现解决开关电源中非连续工作状态下的电压稳定、效率优化与电磁干扰抑制等工程问题。压缩包共272个文件涵盖55个C源码、60个头文件.h、18张原理图与PCB截图.png、13张实物/波形测试图.jpg、5份PDF技术文档及Keil工程配置文件.uvprojx/.uvoptx、调试日志.log和README说明等完整呈现从硬件选型、电路设计、PCB布局到PWM时序控制、ADC采样、PID调节算法及系统联调的全流程包体大小为32.68MB。已有72人学习下载内容包含可直接编译运行的STM32F10x标准外设库工程含timers.c、adc.c、rcc.c等核心驱动、DCM模式识别逻辑与占空比动态调整策略以及典型故障现象分析与抗干扰布线建议是深入理解电力电子控制与嵌入式系统协同开发的高价值实践参考。 做电源设计的人都知道BUCK变换器是绕不开的基础功。但大多数入门教程讲的是模拟控制、CCM连续模式很少有一篇把“STM32数字控制 DCM断续模式”串起来的实战记录。这篇文章把我做的一款基于STM32的DCM模式BUCK变换器完整拆开给你看12V输入转5V/1A输出开关频率100kHz控制芯片用STM32F103C8T6核心是把DCM原理、参数计算、功率电路、采样电路、数字PI控制这几个环节一次讲透。适合正在做电力电子课程设计的学生、想入门数字电源的嵌入式工程师以及想搞清楚电感选型和环路补偿的爱好者。1. 项目整体方案与设计思路1.1 这个项目到底要解决什么问题先把这个项目说人话输入端给一个不稳定的12V直流电输出端要得到一个稳定的5V最大带载1A并且用单片机来闭环控制而不是用传统的TL494、SG3525这类模拟电源芯片。STM32在这里扮演的角色是“大脑”它负责产生PWM波去驱动开关管同时用ADC实时采集输出电压然后跑一个数字PI控制器动态调整PWM占空比让输出电压稳在5V。为什么要用单片机做电源三个理由第一参数调整灵活改环路参数不用换电阻电容改代码就行第二可以很方便地加保护、显示、通信功能比如OLED显示电压电流、串口把数据发到电脑上第三这是目前数字电源方向的基础功学会了之后再去做PFC、LLC、数字同步整流这些复杂拓扑思路是相通的。我这块的输入源用的是实验室可调DC电源额定输入12V实际测试时把输入从10V拉到14V输出电压都能稳在5V±1%以内负载从空载到1A切换时动态跌落控制在200mV以内。对一个10W级别的小功率变换器来说这个指标够用了。1.2 为什么选用DCM模式而不是CCM这是很多人第一次接触时最容易懵的地方。BUCK变换器按照电感电流是否连续分为CCM连续导电模式和DCM断续导电模式。CCM下开关周期内电感电流始终大于零DCM下电感电流每周期都会跌到零并且保持一段时间的零电流状态等下一个周期开始再重新上升。我选DCM不是拍脑袋是基于这个项目的功率等级和应用定位一是电感体积小。DCM允许使用更小的电感。我这个设计里10µH的电感就够了而同样条件下如果硬要做CCM临界电感算下来接近15µH为了保证全负载范围都在CCM还得加余量用22µH甚至27µH。体积和成本直接上去了。二是小功率轻载效率有优势。CCM在轻载时开关管每周期都切换电流却很小开关损耗占比高DCM在轻载时峰值电流低、能量传递效率更好所以很多小功率适配器在轻载时都故意进入DCM。三是环路补偿简单。CCM的BUCK在传递函数里有一个右半平面零点补偿起来比较麻烦稍不注意就震荡DCM下这个零点消失了用一个普通的数字PI控制器就能稳定对STM32这种做定点运算也不是负担。当然DCM也有代价输出纹波大、峰值电流高、电感电流不连续导致EMI差一些。这些在后面实测部分都会提到通过增大输出电容、加后级滤波等手段可以压下去。1.3 STM32在这个项目里的分工STM32F103C8T6在这块板子上的任务清单是这样规划的TIM1高级定时器产生100kHz的PWM驱动功率MOSFETADC1采集两路信号一路是输出电压分压后的反馈值一路是输出电流采样放大后的值定时器TIM3产生10kHz的更新中断作为控制循环的心跳每次中断里跑一遍数字PI软件上做了软启动、过流保护和占空比限幅防止上电瞬间炸管子和输出过冲UART1作为调试口用printf把实测电压、电流、占空比打到串口助手方便调参。有人可能会问为什么控制频率只做10kHz而不是跟开关频率一样100kHz我的实测经验是10kHz的环路对于这个功率等级完全够用而且10kHz意味着MCU每隔100µs才需要算一次PI剩下的大量时间可以干别的。如果你想把动态响应做得很激进可以把控制频率提到50kHz但这时要注意PI运算量和ADC采样的延迟对环路稳定性的影响。2. 主功率参数计算与器件选型2.1 临界电感计算与DCM实现条件DCM不是靠运气出来的是电感取值取出来的。BUCK在CCM和DCM的边界上有一个临界电感公式Lc Vout × (Vin − Vout) / (2 × f × Iout × Vin)把这个设计的目标参数带进去Vin12VVout5Vf100kHzIout1A。Lc 5 × (12 − 5) / (2 × 100000 × 1 × 12) ≈ 14.6µH这个结果的意思是当电感取14.6µH时满载1A刚好处于临界状态只有取比14.6µH更小的电感满载时才会进入DCM并且从空载到满载整个区间都维持DCM。所以我选了10µH留出足够的DCM裕量。这里有个很容易犯的错误有人为了做DCM把电感选得特别小比如2.2µH结果峰值电流飙到七八安培MOS管和电感都扛不住。电感不是越小越好而是要在保证DCM的前提下尽量降低峰值电流。10µH这个值是我算完后实测验证过的满载时峰值电流约2.4A器件应力和纹波都在可以接受的范围。2.2 开关频率与工作波形的确定开关频率选100kHz是综合了几方面考虑的结果。频率越高电感和电容可以做得越小但MOS管的开关损耗和驱动损耗会线性上升频率太低磁性元件体积变大输出纹波也变差。100kHz是中小功率BUCK很常用的一个折中值。还有一个工程细节是PWM分辨率。STM32F103的定时器时钟是72MHz做100kHz的PWM时自动重载值ARR 72000000 / 100000 − 1 719占空比分辨率就是1/720大约0.14%。对5V输出来说每一步占空比调节对应约7mV的变化量配合PI控制器的积分作用稳压精度足够。DCM下一个完整开关周期可以分成三段开关管导通阶段电感电流线性上升开关管关断、续流二极管导通阶段电感电流线性下降电感电流归零后的死区阶段输出完全靠电容撑。这三个阶段对应到电感电流波形上就是一个三角形这也是DCM最直观的判断方法——拿示波器电流探头看电感电流波形拖到零并且平一段时间就是DCM如果是一个连续的锯齿波那就是CCM。2.3 MOSFET、续流二极管、输出电容的选型选型这块我直接给结论和理由器件参数都按满载1A、峰值电流2.4A来定并且留了1.5倍以上的余量。器件型号/规格选型理由控制MCUSTM32F103C8T672MHz主频TIM1高级定时器12位ADC价格便宜、资料多功率MOSFETIRLML6344逻辑电平驱动Vgs(th)约1VSTM32的3.3V IO可以直接推Rds(on)约29mΩ续流二极管SS34肖特基3A/40V反向恢复时间短续流损耗小功率电感10µH/饱和电流3.5A以上小于临界电感14.6µH保证全负载范围DCM输出电容47µF陶瓷X7R 22µF电解并联压低输出纹波兼顾ESR和容量输入电容100µF电解 0.1µF陶瓷滤掉输入侧开关噪声稳定母线电压MOSFET选逻辑电平驱动型是个关键点。有些老师给的电路图里用IRF540这种工业管需要10V栅极电压才能完全导通STM32的GPIO只有3.3V直接推会出现管子没完全导通、导通损耗剧增、发热严重的问题。要么换低门槛的管子要么加一级栅极驱动芯片。为了项目简洁我直接用IO推逻辑电平MOS实测驱动上升沿大概100ns出头100kHz下没有任何问题。二极管这里我多说一句DCM下确实不存在CCM那种二极管反向恢复问题但用普通快恢复管和用肖特基效率差得不是一点半点。SS34的正向压降在1A时大约0.5V而普通1N4007压降1.1V续流损耗会翻倍发热也明显。小功率DCM也坚决用肖特基。3. 硬件电路实现细节3.1 功率回路与栅极驱动这个BUCK用的是异步降压拓扑功率回路由上管MOSFET、续流二极管、电感和输出电容组成。12V从输入端子进来先经过输入电容再到MOSFET的漏极MOSFET的源极接电感和二极管负极的公共节点SW二极管的阳极接地电感另一端接输出电容和负载。STM32的PA8输出PWM经过一个10Ω的栅极电阻直接接到MOSFET栅极。这个栅极电阻有三层作用抑制MOSFET米勒平台引起的振铃、限制栅极充电电流保护IO口、减小开关噪声对单片机的干扰。有条件的可以在栅极加一个10k的下拉电阻防止单片机复位瞬间PWM引脚悬空导致MOS误导通。这里必须提醒一个新手常踩的坑MOSFET的源极接SW节点在开关过程中这个点的电压会在0V和12V之间高速跳变所以千万不要用ST-Link的探头直接去勾SW点普通示波器探头的地线夹子会引入很大干扰看到的全是振铃。测这个点要用差分探头或者至少用短地弹簧把探头地线缩短。3.2 电压电流采样电路输出5V不能直接进STM32的ADCADC的输入范围是0到3.3V。我在输出端做了个电阻分压10kΩ串20kΩ5V分压后得到约3.33V刚好在ADC量程内。分压电阻一定要用1%精度普通的5%电阻温度漂移大会导致设定电压随温度漂移。分压点的后面我又并联了一个100nF的电容和分压电阻天然组成一个低通滤波器把高频开关噪声滤掉。这里有个细节STM32的ADC是开关电容型如果信号源阻抗太高采样瞬间电荷会被拉走导致读数偏低。10k和20k分压后的等效阻抗约6.7kΩ配合100nF电容和足够长的采样时间实测读数很稳。电流采样用INA180这类电流检测放大器50mΩ采样电阻放在输出回路的高侧增益选50倍1A负载时输出2.5V刚好在ADC范围内。这路电流信号不参与闭环控制只用来做欠载、过流保护和串口显示。如果嫌搭运放麻烦直接用INA219模块走I2C也能读电流但注意它的更新率大约1kHz都不到做监测够用做电源的快速保护环就嫌慢了。3.3 PCB布局与接地处理电源PCB的布局核心就一句话让大电流环路面积尽量小。功率回路由输入电容、MOSFET、二极管、电感组成这个环路的面积决定了开关噪声和EMI水平。我的做法是把输入电容尽可能地贴近MOSFET漏极和二极管阳极SW节点铜皮做成一块小SMD焊盘而不是一根细长走线避免天线效应。反馈分压电阻和ADC采样线要远离SW节点和栅极驱动走线。我在第一版里把采样线铺在SW节点的正下方结果输出电压纹波里全是振铃后来把采样线挪到板边、包了一圈地才解决。这类高频干扰靠加大滤波电容只能压一部分根源还是布局。接地处理上我把功率地和小信号地分开铺铜然后在输入电容的负极附近单点连接。ADC的地和STM32的地同属模拟区域避免大电流地回流经过ADC参考地。如果你手头只有一块万用板做不到完整铺铜至少保证主功率回路用粗短线跳线采样点尽量从输出电容两端直接取。4. STM32软件框架与控制算法4.1 定时器PWM配置软件部分我用的HAL库CubeMX配置成本最低。TIM1选PWM Generation Channel 1PA8输出预分频PSC0自动重载ARR719初始比较值Pulse设一个100左右的中间值避免上电瞬间占空比突变。配置完调用一次HAL_TIM_PWM_Start输出就出来了。PWM频率校验很重要推荐在初始化后加一段代码用定时器输入捕获测一下PA8的实际频率。网上经常有人问“为什么我配了100kHz示波器测出来是96kHz”多半是时钟树没配好HSE频率写错或者PLL倍频不对。我习惯在项目初始化时把SystemCoreClock这个变量打印出来确认主频确实是72MHz再谈PWM频率。PWM占空比的更新用__HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, duty)这个宏。注意F103的TIM1 PWM使能了预装载寄存器修改比较值后会在下一个PWM周期开头生效不会出现半周期跳变这是好事正好避免占空比突变带来的电压毛刺。4.2 ADC多通道与DMA采样ADC我配置成两通道扫描连续转换DMA循环模式。PA0接电压反馈PA1接电流反馈。DMA缓冲区长度设64也就是每通道32个样本在控制循环里对这32个样本求平均相当于一个滑动均值滤波器。#define ADC_BUF_SIZE 64 uint16_t adc_buf[ADC_BUF_SIZE]; float get_vout(void) { uint32_t sum 0; for (int i 0; i ADC_BUF_SIZE; i 2) { sum adc_buf[i]; } float adc_avg (float)sum / 32.0f; float vfb adc_avg * 3.3f / 4095.0f; return vfb * 3.0f; // 10k20k分压, 分压比3:1 }这里有个经验DMA写缓冲区是持续循环覆盖的控制循环读取和DMA写入之间会有竞争。好在读的是均值偶尔读到半程数据影响不大真要做到严格同步可以用HAL的ADC半传输完成中断在标志位里切换读区。但实测下来均值法已经足够稳我就没加双缓冲。采样时机上我强烈建议让ADC采集避开MOSFET开关沿。最简单的办法是控制循环定时和PWM错开或者直接用定时器的触发信号去触发ADC注入组采样。我这个项目里因为用了32次均值开关噪声本身就被平均掉了所以没做复杂触发。但对纹波要求高的场景用TIM1的TRGO信号去触发ADC在电感电流过零后的死区时间采样效果会好很多。4.3 数字PI控制与软启动实现控制循环跑在TIM3的10kHz更新中断里每次中断读一次滤波后的电压算一次PI更新一次占空比。PI控制器我写成独立模块方便以后挪到别的项目复用。p a hrefhttps://download.csdn.net/download/2401_89793006/90976635 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p