简介这是基于STM32的DCM模式BUCK开关变换器毕业设计实战资料面向电子、自动化等专业学生在毕业设计或课程设计阶段完成电源变换器项目也可作为工作中开关电源开发的参考资料。包内含完整工程源码、原理图与PCB设计文件、调试日志、说明文档及演示图片共227个文件核心代码以C语言源文件和头文件为主同时包含STM32标准外设库文件、Keil工程配置、Hex固件、Altium Designer原理图/PCB设计文件、PDF设计报告以及实物与仿真截图压缩包整体约32.62MB目录结构清晰便于分模块查阅。内容覆盖STM32定时器与ADC采样配置、BUCK拓扑参数计算、DCM工作模式下的占空比控制策略以及软硬件联调时常见问题的排查思路适合需要完成同类课题的学生快速上手也适合希望深入掌握数字电源控制的工程师参考。已有110人学习作为真实毕业设计成果方案完整、文档详细能提供从原理分析、参数设计到软硬件实现的全程支撑。1. 用STM32做DCM的BUCK轻载效率和失稳边界的权衡DCM模式在BUCK电路里常被误认为效率低、性能差但在轻载场景下结论恰恰相反。电感电流断续后开关管零电流开通、二极管自然关断开关损耗被大幅压低轻载效率反而优于连续模式。这个特性让DCM特别适合做小功率辅助电源、电池供电设备以及课程设计里对硬件参数容错要求较高的场景。配合STM32的定时器PWM和ADC采样不需要昂贵的专用电源芯片就能实现闭环调节。这篇内容围绕STM32F103 DCM BUCK展开从临界电感计算、AOT控制时序、ADC触发采样到闭环参数整定把能直接抄进工程的部分拆开讲。2. DCM边界计算与定时器PWM的恒定导通时间实现2.1 临界电感先算清理清楚再动硬件BUCK变换器工作在哪个模式取决于开关周期内电感电流是否归零。定义电感电流纹波峰峰值Delta I_L (Vin - Vo) * Ton / L当 2 * Iout_min Delta I_L 时电流会跌到零进入DCM。由伏秒平衡可推得临界电感L_c (Vin - Vo) * D * Ts / (2 * Iout_min)其中 D Vo / Vin 是稳态占空比Ts 是开关周期。设计时如果负载下限是0.2A输出5V、输入12V、开关频率100kHz代入得到 L_c 大约在126uH。选择小于 L_c 的电感才能保证规定负载范围内始终处于DCM这也是和CCM设计最大的区别CCM追求大电感压低纹波DCM则在满足纹波要求的前提下尽量把电感选小。参数DCMCCMBCM电感电流周期内归零始终大于零临界点恰好归零二极管反向恢复无有无轻载效率高低高输出电压纹波较大较小中等控制环复杂度较低较高高选择DCM的另一个理由是控制简化CCM下BUCK的传递函数存在右半平面零点补偿网络设计要费不少功夫DCM相当于一阶系统PI参数粗调就能稳定。工程里常见做法是先按最低负载电流算出临界电感然后取0.7倍左右作为实际电感值留出器件误差和温漂余量。2.1.1 DCM电压增益与Ton的关系DCM下输出电压不再只由占空比决定还和负载相关。每周期电感存储能量E 0.5 * L * Ipk^2Ipk (Vin - Vo) * Ton / L输出功率 Pout E * fsw整理后得到Vo Vin - sqrt(2 * L * Pout / (Ton^2 * fsw))这个公式说明一个关键现象在DCM下如果保持导通时间 Ton 不变负载加重时输出电压会下降必须通过闭环增加 Ton 来稳压。反过来固定频率调占空比也能稳压但动态响应不如恒定导通时间AOT控制。原因是AOT模式下 Ton 直接反映控制量电压环输出和 Ton 之间是线性关系而固定频率模式还需要经过调制器转换。2.2 AOT控制的定时器配置方式AOT控制的核心是开关管导通时间由电压环输出决定导通结束后等待电感电流归零再开始下一个导通区间。实现上不需要连续PWM计数而是用定时器的输出比较功能配合一个外部同步信号或者软件判断。ST官方例程里常用定时器单脉冲模式One Pulse Mode配合触发输入这里给出裸机实现方案。2.2.1 TIM3单脉冲模式配置用STM32F103的TIM3作为AOT定时器CH1输出高电平使能MOSFET比较寄存器决定 Ton更新事件后输出拉低。核心配置代码如下void TIM3_AOT_Init(uint16_t ton_us) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Prescaler 72 - 1; // 72MHz/72 1MHz TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period 0xFFFF; TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode TIM_OCMode_Toggle; // 比较匹配时翻转输出 TIM_OCInitStructure.TIM_Channel TIM_Channel_1; TIM_OCInitStructure.TIM_Pulse ton_us * 1000 - 1; // 1MHz计数ton_us对应计数值 TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OCInit(TIM3, TIM_OCInitStructure); TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single); // 单脉冲模式 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 更新中断等待电感电流复位 TIM_Cmd(TIM3, ENABLE); }代码逻辑说明定时器时钟72MHz预分频72分频后计数频率1MHz计一个数就是1us。TIM_Pulse 设为 ton_us*1000 减1是为了让比较匹配发生在 Ton 结束时输出电平翻转关闭MOSFET同时更新中断触发通知MCU当前周期结束。单脉冲模式下计数器在更新事件后停止下一次通过软件重新设置计数初值并启动TIM_Cmd进入新周期。参数说明里最重要的两个点一是预分频系数决定时间分辨率72分频下最大Ton可达65ms覆盖绝大多数BUCK的应用范围二是TIM_OCMode_Toggle配合单脉冲模式实现导通-等待-再导通的AOT时序。此时开关频率不是固定值而是由Ton和电流复位时间共同决定因此ADC采样不能按固定频率触发必须同步到PWM周期的特定时间点。3. ADC采样触发、过压保护与闭环参数3.1 采样时机三种同步方式对比BUCK输出电压在开关管导通和关断期间存在周期性纹波在任意时刻采样会引入严重的开关噪声。工程上常见的采样时机有三种采样方式实现复杂度抗噪能力动态响应定时器软件触发最简单差一般利用TIM更新事件触发ADC中等较好较好外部比较器同步触发复杂最好最好最简单也最常用的是把ADC触发源设为定时器更新事件。在AOT控制下定时器更新事件正好发生在MOSFET关断瞬间此时开关管和续流二极管处于电流换流末端电压噪声已衰减大部分。若想在电感电流完全复位后再采样可在更新中断里延时几十微秒再启动ADC软件转换牺牲一点实时性换取更干净的采样值。3.1.1 ADC采样代码用DMA省掉主循环等待STM32F103的ADC规则组支持定时器触发外部启动配合DMA自动搬运转换结果。初始化代码如下void ADC1_Init(void) { ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_DMA1, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)adc_value; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize 1; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_Init(DMA1_Channel1, DMA_InitStructure); ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; ADC_InitStructure.ADC_ContinuousConvMode DISABLE; ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_T3_TRGO; ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_ExternalTrigConvCmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); }代码说明DMA设置为循环模式ADC每次转换完成自动把结果写入 adc_value 变量主循环里直接读该变量即可不用等待转换标志。ADC1外部触发源配置为T3_TRGO即TIM3的TRGO事件需要把TIM3的触发输出配置为更新事件。ADC_SampleTime_239Cycles5 是最大采样时间目的是降低ADC输入阻抗对高内阻分压网络的影响。参数调整要点如果发现采样值跳变剧烈首先检查采样时间是否太短常见做法是固定用239.5周期其次在ADC引脚并联一个0.1uF电容构成一阶RC抗混叠滤波。STM32的ADC引脚输入阻抗约50k欧分压电阻选择在10k量级比较合适。3.2 过压保护和主循环里跑的控制任务过压保护最好放在定时器更新中断里做而不是丢给主循环。因为AOT模式下如果Ton控制异常输出电压可能快速升高主循环几十微秒的延迟都可能让MOSFET承受过应力。中断服务函数里判断 adc_value 是否超过阈值超过则直接关闭PWM输出。void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); if (adc_value OVP_THRESHOLD) { TIM_Cmd(TIM3, DISABLE); GPIO_SetBits(GPIOA, GPIO_Pin_8); // 关断信号灯 } else { ton_target PID_Regulate(TARGET_VOLTAGE, adc_value); TIM_SetCompare1(TIM3, ton_target); TIM_SetCounter(TIM3, 0); TIM_Cmd(TIM3, ENABLE); } } }这里的中断服务函数承担了三件事更新使能时重新计算Ton、把最新的Ton写入比较寄存器、从零启动下一次定时。OVP_THRESHOLD 根据分压电阻比例换算比如输出额定12V、保护点14V分压比1:4则阈值对应ADC读数约3.5V/3.3V*40954342。PID_Regulate 是电压环函数输出限制在允许的Ton最小值与最大值之间防止积分饱和导致恢复时间过长。4. PID参数整定、数字滤波和tasks.c工程框架的衔接4.1 DCM模式的PID参数为什么好调DCM下BUCK的电流是断续的电感不参与连续储能从控制角度看负载更接近一个受控电流源并联电容。所以系统的开环传递函数近似为单极点系统PID里根本不需要微分项PI就足够。微分项在DCM下反而容易放大开关噪声导致Ton抖动。位置式PI实现如下int16_t PID_Regulate(uint16_t setpoint, uint16_t feedback) { static int32_t integral 0; int32_t error setpoint - feedback; int16_t output; integral error; if (integral INTEGRAL_LIMIT) integral INTEGRAL_LIMIT; if (integral -INTEGRAL_LIMIT) integral -INTEGRAL_LIMIT; output KP * error KI * integral; if (output TON_MAX) output TON_MAX; if (output TON_MIN) output TON_MIN; return output; }积分限幅INTEGRAL_LIMIT取TON_MAX的60%左右防止负载突变时积分积累过大。KP决定响应速度KI决定稳态精度。DCM下典型调法先置KI为0KP从小往大调直到输出电压出现小幅震荡然后KP减半再缓慢增加KI直到稳态误差消失。这个流程在BUCK输出电容100uF、开关频率100kHz的条件下通常KP取50~200、KI取5~30。4.1.1 采样值数字滤波ADC每次转换结果直接用于PID会让Ton周期级抖动。常见做法是一阶低通滤波static float filtered_value 0; float LowPass_Filter(float new_sample, float alpha) { filtered_value alpha * new_sample (1.0f - alpha) * filtered_value; return filtered_value; }alpha 取0.2到0.4之间对应截止频率约等于开关频率的1/10到1/20。如果开关频率是100kHz希望截止频率10kHz采样频率100kHzalpha约0.2。需要注意滤波引入的相位滞后在DCM下影响不大因为系统带宽本就低于5kHz。4.2 tasks.c和现有工程怎么拼装资源里的tasks.c是典型的RTOS风格任务骨架在没有操作系统的情况下也可以拆成函数在while循环里分时调用。工程中常见划分方式是把ADC滤波、PID计算、按键扫描、OLED刷新拆成不同任务void tasks_init(void) { TIM3_AOT_Init(20); ADC1_Init(); tasks_fsm TASK_RUN_NORMAL; } void task_control(void) { float vout_filtered LowPass_Filter(adc_value, 0.25f); ton_target PID_Regulate(vout_setpoint, (uint16_t)vout_filtered); TIM_SetCompare1(TIM3, ton_target); } void task_display(void) { OLED_ShowNum(0, 0, vout_setpoint, 4); OLED_ShowNum(0, 2, adc_value / 4, 4); }主循环按固定周期调用这些任务比如用SysTick每200us调用一次task_control每50ms调用一次task_display。这样做的好处是控制频率稳定和中断里调PID相比主循环方式更容易调试PWM的Ton更新延迟最多200us对100kHz开关频率影响可控。注意stm32f10x_tim.c和stm32f10x_adc.c是标准外设库的固件实现初始化顺序必须是先RCC使能时钟再配置外设否则写寄存器不生效。工程里若编译报错优先检查是否漏了stm32f10x_conf.h里的外设头文件包含。4.3 同步整流和异步整流的实测对比设计和文档里如果使用了二极管续流属于异步BUCK。异步BUCK的好处是电路简单、反向恢复问题几乎不存在DCM下效率表现也不差。若改用MOSFET做同步整流DCM下要增加反向电感电流检测电路防止电流倒灌复杂度上升明显。实际对比结论输出功率10W以下、负载电流小于1A时异步DCM BUCK的满载效率通常在85%左右同步整流BUCK约92%差距主要来自续流二极管0.3~0.5V的正向压降。负载降到100mA时异步方案效率反而可能反超因为同步整流的驱动损耗和死区时间管理在轻载下成了主要开销。课程设计和毕业设计推荐先用异步方案跑通功能再用同步整流优化效率。5. 轻载调试时的几个隐蔽坑与最后验证方法5.1 电感量温漂和频率上限的余量取舍DCM下电感量直接决定电流峰值大小铁硅铝磁环电感温度升高后电感量会下降15%到25%导致Ipk增大、Ton减小输出电压纹波恶化。选电感时按实测值常温留出30%余量。另一个常被忽视的是定时器分辨率72MHz主频下1MHz计数频率开关频率超过200kHz时一个开关周期的计数值低于500Ton调节步进过大输出电压会出现可见的台阶。常见做法是把开关频率控制在100kHz附近既保证分辨率又避开音频噪声。5.2 检查DCM边界示波器定位电感电流零点验证是否真正工作在DCM不能用万用表量电压就算完成。需要用示波器电流探头测电感电流波形或者用电阻采样配合差分探头观察。DCM的判据是电感电流在开关周期内有一段恒为零的时间对应电感两端电压为零、输出由电容单独供电。实测时让负载从满载缓慢减小观察电流波形底部出现平底的那一点对比理论算出的临界负载电流偏差应控制在20%以内。如果偏差过大说明电感实际值和标称值差异较大需要重新测量。另外检查续流二极管电压波形DCM下二极管关断时没有反向恢复尖峰电压波形平滑若看到高频振荡说明进入了CCM或者PCB寄生参数过大。配合输出纹波测量在轻载1%负载时纹波峰峰值应小于50mV超过这个数值优先检查采样地和功率地的单点连接。5.3 最后落地的验证流程按照闭环设计完成后推荐的验证顺序是空载启动看输出电压是否过冲用电子负载按25%、50%、75%、100%步进加载记录电压跌落和恢复时间再用示波器全程监视电感电流波形确认未脱离DCM。电压环带宽可以通过扫频或者时域阶跃响应估算DCM下恢复时间小于1ms即为合格。整套参数确认后把PID参数固化到stm32f10x_flash.c对应的Flash存储区实现上电自动加载避免每次硬编码改参数重新烧录。这样一套DCM BUCK从计算、控制到验证就算闭环了后续换电感或改输出电压只需要重算临界电感和Ton范围不需要改动控制算法。本文还有配套的精品资源点击获取