简介基于STM32的恒流源设计完整方案包含原理图、PCB、固件源码与仿真验证材料适合电子工程师与电源控制学习者参考。方案采用意法半导体STM32微控制器通过MOS管配合ADC与DAC输出实现1至300毫安可调恒流并融入PID算法提升稳定性覆盖硬件电路到软件控制的完整链路。资源共507个文件压缩后约29.38MB主要包含C语言源码、Keil工程文件、Altium Designer设计文档及编译辅助文件可按需提取核心内容。已有4008人学习下载验证了参考价值借助其中的电路图纸、程序框架和PCB布局可快速理解恒流源的设计要点并据此搭建或改进自己的系统。整套内容从电路原理到程序实现形成闭环有助于掌握精密电流调节方法。1. 恒流源设计课题为什么用STM32做数字恒流而不是传统运放恒流某高校电子类课程设计经常遇到这样一个题目设计一个输出01A可调的恒流源要求电流稳定、能显示、能设定。按照传统做法一个运放加一个精密电位器就能完成恒流但电位器调电流靠人手温度一变电流就飘想加个按键设定和数码管显示还得再搭一套逻辑电路调试过程几乎靠手感。改用STM32做主控后恒流的基准电压由PWM/DAC产生实际电流由ADC采样回来参与闭环设定值、显示值、校准值全部变成代码里的变量温漂和器件误差还能通过软件校准压下去。这篇设计就沿着需求、方案、实现、验收四个环节把整条链路铺开适合正在做恒流源课设或毕设的学生也适合需要快速做一个可编程恒流源模块的工程师参考。2. 总体方案设计线性恒流拓扑与STM32系统结构拆解2.1 控制拓扑选择线性恒流为主开关恒流不做主方案恒流源的核心是把负载电流稳定在设定值放大拓扑上主要有两类一类是运放加MOS管构成的线性恒流MOS管工作在放大区靠消耗压差来吸收电流波动另一类是Buck/Boost开关恒流通过电感储能和高频开关稳压。做课设和一般仪器级恒流源我一般先排线性方案理由很直接线性方案无电感、障碍少运放反馈环一闭合电流就稳纹波天然小开关方案效率高但多出来电感选型、续流二极管、环路补偿PCB布局稍微不好就会出现辐射干扰和电流尖峰时间紧的情况下特别容易翻车。线性方案的代价集中在功耗上。假设输入电压12V负载电压3V输出电流1AMOS管上的压降就是9V消耗9W功率需要做散热处理如果把输入直接接到24V功耗会到20W以上这时候就要认真考虑加散热片甚至改用开关拓扑。做设计选型时先算这一个数P等于输入电压减去负载电压再乘以输出电流超过2W就要给MOS管加面积足够的铜箔超过5W要加散热器这也是答辩时老师最常追问的点。决定用线性方案后整体的控制思路就清晰了STM32输出一个可调参考电压运放把采样电阻上的电压死死盯住这个参考值MCU再通过ADC把采样值读回来做修正。这个闭环分两层下面把每一层拆开说明。2.2 系统架构与模块划分整个系统按功能可分成五个模块主控模块、设定模块、恒流驱动模块、电流采样模块和人机交互模块。主控模块就是STM32最小系统负责生成PWM、采集ADC、运行校准和PID算法设定模块用定时器PWM加两级RC滤波输出一个平滑的直流参考电压恒流驱动模块由运放和MOS管构成是恒流的执行核心电流采样模块用采样电阻加ADC完成人机交互模块用OLED显示设定电流和实测电流配合按键修改数值。信号流向是整个方案的灵魂画框图时按这条路走PWM占空比 → RC滤波 → 参考电压Vref → 运放负反馈环 → MOS管栅极 → 负载电流 → 采样电阻电压Vs → ADC采样 → STM32计算误差 → 修正PWM占空比。注意这里有两层反馈第一层是运放硬反馈速度快保证电流跟随Vref第二层是MCU数字闭环速度慢负责修正电阻温漂和系统误差。两层环各干各的活这也是设计报告里最值得写清楚的创新点。模块划分如下表器件选型时对照着看模块主要器件关键参数职责主控STM32F103系列72MHz主频、12位ADC产生PWM、采样、校准、显示设定TIM1 PWM 两级RCPWM频率1kHz20kHz把数字占空比变成模拟Vref恒流驱动运放 N-MOS轨到轨运放、逻辑电平MOS用负反馈稳定负载电流采样精密采样电阻0.5Ω/0.1%精度把电流转换成电压供ADC读取人机OLED 按键I2C接口显示设定值与实测值2.3 核心器件选型与关键参数估算采样电阻放在整个电路的地回路里取值需要综合权衡。按目标01A计算采样电阻取0.5Ω时满量程压降0.5V这个电压刚好在单片机ADC的合理输入范围内又不至于把运放的共模范围顶到上限如果取0.05Ω满量程只有50mV运放失调和地噪声会把这个信号淹没精度就靠不住了。取值偏大也不行0.5Ω在1A下功耗0.5W功率选型要选1W以上的合金电阻否则温度升高后阻值漂移直接反映成电流误差。运放选型上LM358这类低带宽单电源运放通常够用但要注意它输出能不能摆到接近电源轨。Vref最高可能到3.3V运放输出要能驱动MOS管完全开启普通LM358在3.3V供电下高电平输出只能到供电的2.8V左右这时候最好选轨到轨输出的运放或者把运放供电单独提升到5V。MOS管选逻辑电平N-MOS栅极阈值电压要低于运放最低输出电压导通电阻Rds(on)要小在1A电流下管压降越低发热越轻。PWM设定通路的参数计算是另一个关键位置。PWM分辨率和滤波后的纹波是一对矛盾定时器计数周期1000占空比步进就是0.1%对应电流步进约1mA两级RC滤波的截止频率越低纹波越小但设定值响应越慢。通常的做法是PWM频率取1kHz到20kHz之间RC参数按截止频率为PWM频率的1/10左右设计第3章会给出具体数值。最后电源部分也要注意用线性稳压芯片给模拟部分供电数字地和模拟地在采样电阻附近单点连接不然ADC读出来的数会飘得厉害。3. 关键模块实现从恒流电路到STM32闭环控制代码3.1 恒流驱动电路低端采样电阻加运放负反馈电路实现采用低端采样方案负载的高端接电源正负载低端接MOS管漏极MOS管源极接采样电阻后入地。运放的反相输入端接PWM滤波后的参考电压Vref同相输入端接采样电阻电压Vs输出直接驱动MOS管栅极。这个接法的闭环逻辑是电流增大 → Vs升高 → 运放输出降低 → MOS管关小 → 电流回落整个过程在微秒级完成不需要MCU干预。关键公式是Vref等于Iset乘以Rs。设定电流1A、Rs取值0.5Ω时Vref需要0.5V也就是PWM滤波后的平均电压要为0.5V。运放的失调电压在2mV以内时等效电流误差约4mA对1%精度要求影响不大但如果采样电阻精度只有5%这个误差会被放大成几十毫安所以采样电阻精度至少要0.1%。低端采样的好处是Vs对地电位很低单电源运放就能直接处理不用差分电路代价是负载不直接接地产品化时要特别注意和外部设备的共地问题做课设演示时这个问题不明显但答辩老师可能会问。3.2 用PWM加RC滤波实现可调参考电压第一次做这个项目的人最容易纠结的问题是STM32到底用内置DAC还是用PWM滤波。我的习惯是先看手头的芯片资源STM32F103内置DAC只有12位两个输出通道共用一个基准电压走线要占用两个引脚PWM加RC滤波方案不挑芯片所有定时器都能输出电路上只多两个电阻两个电容。DAC方案胜在纹波低、响应快PWM方案胜在通用和便宜课设场景下PWM完全够用交作业的成本也更低。RC滤波参数按照PWM频率1kHz设计第一级R10kΩ、C1uF第二级R10kΩ、C1uF两级都接地。单级截止频率约16Hz两级叠加后对1kHz方波基波的衰减超过60dB理论上纹波在毫伏级别。需要说明的是截止频率低会导致参考电压建立时间变慢设定值改变后要等几个周期才能稳定PID响应也要适当放慢否则两者抢时间会出现振荡。下面这段代码是初始化定时器产生PWM的核心逻辑// 使用TIM1_CH1输出PWMPA8复用为PWM引脚 void PWM_Init(void) { GPIO_InitTypeDef gpio {0}; TIM_OC_InitTypeDef oc {0}; __HAL_RCC_TIM1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // PA8配置为复用推挽输出驱动RC滤波器 gpio.Pin GPIO_PIN_8; gpio.Mode GPIO_MODE_AF_PP; gpio.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, gpio); htim1.Instance TIM1; htim1.Init.Prescaler 71; // 72MHz/72 1MHz计数频率 htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 999; // 计数到999溢出PWM频率1kHz HAL_TIM_PWM_Init(htim1); oc.OCMode TIM_OCMODE_PWM1; oc.Pulse 0; // 初始占空比0避免上电误触发 oc.OCPolarity TIM_OCPOLARITY_HIGH; HAL_TIM_PWM_ConfigChannel(htim1, oc, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); }预分频器设为71是把72MHz时钟分频成1MHz计数周期设为999后PWM频率正好是1kHz。如果想提高PWM频率到10kHz只需要把Period改成99同时把RC滤波的电容缩小例如两级各取0.1uF补偿频率升高带来的纹波下降。占空比和电流的换算关系是Pulse值等于Iset乘以Rs除以3.3V再乘以10000.5V参考电压对应Pulse约为152。3.3 ADC采样电路与两点校准方法采样电阻上的电压通过PA1引脚进入ADC1。ADC的参考电压和单片机的Vref绑定如果板子上用3.3V稳压默认满量程就是3.3V所以采样电阻电压0.5V换算成ADC原始值约为620。直接拿这个值算电流会引入两类误差一是采样电阻的实际阻值和标称值有偏差二是运放和ADC存在零偏。用两点校准可以同时消掉这两类误差。校准的具体做法是第一步PWM设0读一次ADC原始值记为offset第二步用万用表实测一个已知电流例如用恒定电阻负载把电流稳定在0.5A附近读取ADC原始值记为raw则增益gain等于raw减去offset再除以实测电流值这一步把采样电阻和分压网络的比例都吸进了一个系数里。之后计算电流的公式就是ADC原始值减offset再除以gain每次上电先执行一次不依赖硬件修改。// 单次ADC采样取平均值减少随机噪声 uint32_t ADC_ReadAverage(void) { uint32_t sum 0; for (int i 0; i 16; i) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); sum HAL_ADC_GetValue(hadc1); } return sum / 16; }一定把ADC采样时间拉长到最大档位片段里只写了循环取平均值实际初始化时采样时间也要配置成最长档位能明显减少参考电压毛刺和时钟噪声的混叠。校准系数建议存到备份寄存器或外部Flash每次开机先读不要让用户每次都重校准。3.4 数字闭环开环校准与PID修正两层实现拿到ADC回读的实际电流后控制层有两种实现路径。最简单的是开环校准前期把占空比和实测电流的关系做成一张表运行时查表输出适合负载固定、温漂不明显的场景代码量小答辩时不至于被追问复杂算法。另一种是闭合PID环把设定电流和实测电流的误差喂给PID输出量叠加到PWM占空比上这样做的好处是MOS管温度变化导致电流漂移时环会自动拉回来稳流效果更接近仪器级。// PID控制器位置式输出带积分限幅 float PID_Process(PID_t *pid, float set, float cur) { float err set - cur; pid-integral err; // 积分限幅防止积分饱和造成电流上冲 if (pid-integral 30.0f) pid-integral 30.0f; if (pid-integral -30.0f) pid-integral -30.0f; // 微分项默认关闭ADC噪声会被放大成毛刺 // float d pid-kd * (err - pid-lastErr); // pid-lastErr err; return pid-kp * err pid-ki * pid-integral; }P参数和I参数的初值按先P后I的流程调P从0.02开始观察电流阶跃响应过冲了减半响应太慢就加倍等到稳态误差还消不掉再加II从0.01开始。注意运放的硬反馈环已经把大部分电流控制做完了MCU的PID只负责慢速修正P和I的数值通常比纯软件控制小一个数量级调参时如果发现电流振荡先怀疑RC滤波截止频率太低带来相位滞后再怀疑PID参数过大不要一上来就改代码里的参数。写到这里把两层环的关系再说透运放环恒的是“采样电阻电压等于参考电压”MCU环恒的是“实测电流等于设定电流”前者快后者慢。如果把运放环做到完美MCU环可以很轻如果运放环有温漂MCU环就把它补回来。设计报告里如果能画出两条环路的带宽关系基本就能让评阅老师相信你理解了控制结构。4. 常见问题与排查恒流源调试最容易翻车的五个点4.1 设定电流和万用表实测电流永远对不上现象写代码让输出500mA万用表测到只有460mA左右而且不同量程档位偏差不一致。这是第一次看到恒流源实测数据对不上时最容易被卡住的问题。原因有两类。一类是采样电阻实际阻值不是标称的0.5Ω贴片电阻标称精度5%的就很明显另一类是运放失调电压叠加在Vs上Vref等于Vs时实际电流等于Vs除以Rs但Vs里混了运放的2mV到5mV失调折合到1A满量程就是1%量级的误差。解决换0.1%精度的合金采样电阻同时做两点校准。校准先把PWM设到0读offset再输出一个已知电流标定gain。做完校准后偏差基本上能压到0.2%以内这是成本最低的精度提升手段比换更高精度运放划算多了。4.2 电流不是稳定的直流而是低频振荡甚至啸叫现象输出端接示波器电流波形出现几百赫兹到几千赫兹的正弦振荡或者负载切换瞬间有明显的过冲和回摆现场听起来还有嘶嘶声。原因MCU闭环和运放闭环在抢带宽。RC滤波截止频率设计得太低时Vref从设定新值到稳定要几百毫秒PID却在这段时间里继续输出纠正量两者叠加成相位滞后就表现为振荡。另一个常见原因是积分项没有限幅误差持续累计导致过冲。解决先用排除法确定是哪个环在振荡。把PID的积分项清零只用纯P看振荡是否消失如果消失就是积分饱和加上限幅。如果仍然是低频振荡把RC滤波的一级电容加大一倍或者PID的P值先减半每次只改一个变量至少留出十分钟观察稳定时间。4.3 PWM滤波后的参考电压纹波大电流波形上有毛刺现象电流恒定后示波器能看到1kHz的锯齿纹波幅度有几毫伏到几十毫伏对精度要求高的测量直接不合格。原因两级RC的滤波效果没有发挥出来通常是布局问题RC地线离采样电阻地太远地回路的压降被耦合进Vref也可能PWM频率本身太低1kHz基波能量太大16Hz截止频率虽然能把基波衰减掉但方波的谐波含量不小。解决把RC滤波部分的接地点单独连到电源地不要和采样电阻的地共用同一段走线。同时可以把PWM频率从1kHz提高到10kHz占空比分辨率从1/1000变成1/100如果压低频率又想要原来的分辨率就把计数周期改成9999并改用100kHz附近的RC截止频率这个方向通常能同时改善纹波和分辨率。4.4 上电瞬间电流直接冲到满量程容易打坏负载现象电源和主控同时上电的瞬间OLED还没亮起来负载上已经通过了接近满量程的电流。原因STM32的GPIO在上电期间是高阻态PWM引脚默认电平不确定运放在MCU初始化完成之前已经开始工作如果Vref被什么信号抬高了MOS管立即全开。这是硬件方案里最容易坑人的地方上电顺序决定了“先有鸡还是先有蛋”运放先上电而参考电压的控制权还在复位中的MCU手里。解决GPIO初始化成下拉输入PWM通道启动前把Pulse设置为0再开启定时器输出使能复杂一点的做法是加一个使能三极管或模拟开关串联在运放输出和MOS栅极之间由MCU的一个普通GPIO控制MCU初始化完成后再放开栅极信号。做这一条能避免绝大多数负载损坏事故。4.5 ADC读数跳变OLED显示电流值最后一位不停闪现象设定值不变硬件也很稳但显示电流值几百毫秒就跳几个字看着不稳定。原因ADC采样时间太短采样电容没有充分充电获得精确电压或者参考电压Vref本身有高频纹波把噪声直接量化出来了。STM32的ADC是逐次逼近型输入源阻抗高的时候采样时间不足会直接引起跳码。解决采样时间选最长档位信号链路上对地加一个10nF电容滤高频软件上再做一次递推平均或者一阶低通滤波。一阶低通一行搞定last等于last加上new减last除以16每次新采样以16分之一的权重更新显示值稳定性提升非常明显。要注意滤波带来的延迟闭环PID计算用的是滤波前的原始值不要用滤波后的值去当反馈否则相当于又增加一拍延时。5. 验收与答辩用数据证明恒流源真的合格5.1 验收测试流程与数据表验收不要只看能不能亮灯要按正式指标逐项测。我一般按三步走先做安全性检测空载状态上电用示波器看电流波形有没有过冲再做精度测试分别设0.2A、0.5A、1A三档用四位半以上万用表串联进负载回路读取实测值最后做负载调整率测试把负载电阻在2Ω到10Ω之间切换记录电流变化量。负载调整率公式是最大电流减最小电流除以满量程电流再乘100%恒流源仪器标准一般要求小于0.5%课设做到1%以内就算及格能给出三档测试数据表答辩就有底气。测试项测试条件合格标准实测电流精度设定0.2/0.5/1.0A误差≤1%负载调整率负载2Ω→10Ω变化≤0.5%动态过冲负载突变过冲≤5%纹波电流1A满载≤10mV5.2 答辩要点与常见提问应对答辩重点是讲清楚“两个环”运放硬反馈环保证响应速度MCU数字环消除系统误差。老师通常用“为什么不用DAC”“MOS管功耗怎么算”“采样电阻放在低端有什么问题”三个问题试探是不是真做过回答时直接说“用了PWM加两级RC低成本代替DAC代价是响应变慢但恒流源本身不需要毫秒级响应”就把这颗雷排掉了。功耗问题把公式和数据摆出来12V、1A、负载3V时管子功耗9W加25平方厘米散热铜箔稳定温升不超过40℃这个数字一报老师就知道这是实测过的。每次做完验收我都固化一个习惯先测最危险的上电过冲再测精度最后才测纹波顺序反了哪怕指标全过也会在答辩演示时被上电烧负载一击致命。这套从电路到代码再到验收的流程希望能帮到你把你自己的恒流源方案稳稳落地成一份有实物、有数据、能讲清原理的完整设计。本文还有配套的精品资源点击获取