单片机DIY多功能充电器:恒流恒压、OLED显示、容量估算
2026/9/1 7:59:11 网站建设 项目流程

简介:面向单片机与嵌入式初学者的多功能充电器设计资料包,以Philips 12C5410AD单片机为控制核心,面向课程设计、电子竞赛及日常DIY充电方案,重点解决电池类型自动识别、充电电压电流检测和过充欠充保护等工程问题。压缩包共11个文件,包含C语言源程序(low001.c)、Keil工程文件(uvproj/uvopt/plg)、编译中间与结果文件(obj、lst、m51、hex)以及说明txt,能够清晰呈现程序编写、编译到生成烧录文件的全过程;工程结构简单,适合快速上手。整个资源包仅66KB,内容精炼,目前已有201人学习下载。资料中单片机利用内置ADC实时采集电池电压和电流,通过判断电池初始特征区分镍氢、镍镉、锂离子等类型,并据此切换恒流、恒压或涓流充电模式,同时设定过充和欠充阈值以确保安全。源码量适中,关键逻辑注释清晰,便于读者深入理解自动识别和充电控制流程,并移植到其它型号单片机。 手头攒了一堆18650、镍氢电池,还有一块闲置的12V适配器,每次充电都得翻出不同的充电器,桌面乱成一团不说,关键有些充电器还只能充特定类型的电池。后来我干脆用单片机自己造了一台多功能充电器,支持锂电池、镍氢电池、铅酸电池三种电池类型的恒流/恒压充电,还带了OLED显示、容量估算和温度保护。这篇就把整个设计思路、硬件选型、软件架构和实测中踩过的坑完整记录下来,给想做类似项目的朋友一个可以直接参考的实战方案。

这个项目适合有一定单片机基础、又想从点灯进阶到带功率控制的开发者。整个系统不算复杂,但把采样放大、Buck降压、状态机、PID调节、多任务调度这些嵌入式常用技术都串了起来,做完之后对电源类项目的理解会明显上一个台阶。我会尽量把每个关键决策背后的理由都说清楚,让大家不只照着焊,还能明白为什么要这么做。

1. 为什么是单片机,而不是充电管理专用芯片

1.1 现成芯片方案的局限

市面上充电管理IC非常多,比如TP4056、CN3791、BQ24650这些,选型得当的话外围电路比单片机方案简单得多。但我一开始就没打算走这条路——专用芯片的充电参数是写死的,或者只能通过电阻组合选择有限的几档,想做一台"通吃"的充电器很麻烦。而且锂电池、镍氢、铅酸这三类电池的充电策略完全不同,用专用IC就得做三种独立电路,成本和体积都兜不住。

纯硬件方案还有一个问题:调试时一点都不直观。电压电流只能靠万用表点测,想看清楚整个充电过程的变化曲线非常痛苦。而单片机方案的好处是,参数改固件就能变,状态全部可以显示在屏幕上,出了问题也能通过日志定位。

1.2 单片机方案的技术底座

选择单片机做控制核心,本质上是把"模拟电源控制"变成了"数字电源控制"。充电过程的恒压、恒流、截止判断,都交给ADC采样+软件算法来处理。这样做最大的优势是灵活:想要4.25V截止就改一个宏定义,想要100mA的涓流预充就改一个状态跳变阈值,不需要动硬件。

主控我选了STC8系列,属于51内核,主频跑到24MHz没问题,内置12位ADC和硬件PWM。之所以没用STM32,一方面是这个项目需要的资源不多,STC8完全够用;另一方面51生态的资料太全了,很多刚入门的朋友也熟悉51的寄存器操作。至于有些人担心的浮点运算,在PI调节器里我全程用定点运算,跑起来毫无压力。

1.3 功能框架与整体目标

这个项目的功能规划,我列了一个清单,也建议大家在做同类型项目时先列清楚,不然一边写代码一边加需求很容易乱。

功能项实现说明
电池类型选择锂电(3.0V~4.2V)、镍氢(1.2V×N)、铅酸(12V)
充电模式预充、恒流CC、恒压CV、截止,四段式状态机
显示0.96寸OLED,显示电压、电流、容量、状态
交互单按键循环切换模式,长按进入参数设置
安全保护电池反接检测、过流保护、NTC温度保护
扩展功能放电模式,可估算电池实际容量

2. 功率电路与采样网络:硬件设计的关键决策

2.1 Buck降压拓扑与MOS驱动电路

充电器的核心功率拓扑,我选了Buck降压结构。12V输入,输出需要覆盖2V到14.6V的范围,最大电流3A,Buck是最合理的方案。主开关用一颗N沟道MOS管(IRLZ44N,逻辑电平型,Vgs阈值只有1V左右),为什么强调逻辑电平?因为驱动电压来自单片机PWM引脚,高电平才5V。如果选了普通电平的MOS,5V驱动会让管子工作在放大区,瞬间发热就能把手摸出水泡。

驱动电路上不能直接用单片机IO直驱MOS。单片机IO口驱动能力有限且驱动高边MOS时源极电位会漂移,所以中间加了一级三极管推挽驱动。Q1是低边驱动管,Q2是高边驱动管,两只三极管组成互补推挽结构,既能快速充放电栅极电容,又能保证栅极驱动电压足够。功率电感这里要注意选饱和电流大于5A的型号,否则大电流时电感量塌陷,纹波会严重到影响控制环。

2.2 采样电路的增益计算与器件选型

ADC采样的精度决定了整个充电控制的稳定性。我用0.05Ω、5W的绕线电阻做电流采样电阻,满量程3A时压降150mV,这电压太小,直接送ADC等于把噪声和信号一起采,所以必须放大。运放我选LM358搭同相放大电路,放大倍数11倍:

[ V_{out} = I \times R_{sense} \times \left(1 + \frac{R_f}{R_g}\right) ]

算一下:3A的时候 Vout = 3 × 0.05 × 11 = 1.65V,STC8的ADC参考电压是2.5V,留了约0.85V的余量,避免满量程时接近顶格导致失真。放大后的信号经一级RC低通滤波(截止频率约1.6kHz)再进ADC。

电压采样就更直接了。输出端最高14.6V,直接接ADC肯定烧引脚,用电阻分压网络1/11比例衰减,再送ADC引脚。分压电阻用1%精度金属膜,串联的均衡电阻有助于减少温漂影响。这里有个细节:分压网络的地必须和采样电阻的冷端共用同一个模拟地,不能在主功率地线上串接,否则采样结果会叠加地线压降误差。

2.3 接线保护:反接、过流、温度NTC

充电器最怕的是接反电池,一个反接可能直接烧掉采样电阻和续流二极管。我设计了一个简单有效的反接检测:电池接入后经过一个分压网络,二极管挡位分压点电压为负,利用单片机ADC检测负压(通过叠加偏置电压)即可判断是否反接。一旦判定反接,立即断开充电MOS并报警提示。

过流保护方面,除了软件在ADC里检测,我在硬件上还加了一个熔断器和一只自恢复保险丝,双保险。温度探头用10K NTC贴在电池仓旁边,接分压电路进ADC,当电池温度超过45℃就自动降低充电电流,超过55℃强制停机。这个功能做出来后用了不止一次——有次电池是劣质货,充电到一半明显发烫,NTC直接拉停了。

3. 软件架构:状态机、PID与时间片调度

3.1 三段式充电状态机转换逻辑

充电控制的软件核心是一个状态机,看起来就这么几种状态,但状态跳转条件要写得非常严谨,否则会出现充电不满或者过冲的问题。

状态进入条件退出条件控制方式
待机上电 / 充满检测到电池接入且电压>2.8V关闭PWM输出
预充电池电压<2.8V电池电压升至2.8V100mA恒流
恒流充电预充完成电池电压到达目标恒压值电流环PI,目标1A
恒压充电电压到达4.2V/7.2V/13.8V电流降至设定截止电流电压环PI,占空比微调
充满截止电流维持5分钟拔掉电池关闭PWM,显示充满

状态机的好处是逻辑清晰,任何时间点都知道系统在干什么,也方便加入异常分支,比如温度过高随时可以进入保护态。预充阶段是非常容易被忽略的:一块过放电池如果直接上大电流充电,内部可能有短路析锂风险,必须先用小电流让电压慢慢恢复。我设定了一个2.8V阈值,低于这个值一律先预充。

3.2 PID的工程简化:为什么我用改进型PI而不是标准PID

充电控制环路本质上是电压环和电流环交叠工作。标准PID有微分项,但在这个项目里,ADC采样本身有噪声,微分项会放大噪声,导致PWM占空比抖动,反而让输出电压不稳。所以我把D项砍掉,只用了PI。实际测试下来,动态响应完全够用。

具体实现是增量式PI:

[ \Delta u_k = K_p \times (e_k - e_{k-1}) + K_i \times e_k ]

其中 e_k 是当前误差,e_{k-1} 是上次误差。为什么用增量式?因为它天然带积分抗饱和能力——如果输出已经限幅,下次累加时误差累积不会无限膨胀。我在实现时还加了一组条件:输出PWM占空比限制在5%~88%之间,防止启动瞬间占空比过冲导致冲击电流。

每个控制周期输出前要做一次"环路选择":电压环算出一个占空比,电流环算出一个占空比,取两者中较小的那个作为实际输出。这个逻辑在电源控制里叫"低选门",目的是让系统在任一时刻都被更保守的环路约束,不会出现电池已经到达4.2V但电流还没降下来的危险情况。

3.3 1ms时基下的多任务调度与实时性

很多朋友用51单片机时遇到过一个问题:想同时做按键扫描、OLED刷新、ADC采样、充电控制,结果一部署就乱套。我这次用的方案是"定时器中断产生时基 + 主循环任务表调度"。

定时器0配置为1ms中断一次,中断服务函数里只做三件事:喂软件计数器、置标志位、做一次时间片计数。所有实际任务都放在主循环中根据标志位执行。任务按需要分在不同优先级:PD控制环每5ms执行一次,温度检测每200ms执行一次,OLED刷新每100ms执行一次,按键扫描20ms一次。

任务表的核心是把实时性要求高的充电控制放在高频执行,把显示这类低频任务放在较低频。即使某一帧显示因为耗时掉了几毫秒,充电环路也不会被拖慢。这个架构不止适合这个项目,后续做其他带多个外设的单片机项目同样可以直接复用。

4. OLED显示、按键交互与参数标定

4.1 显示界面:用一块OLED讲清楚充电状态

显示部分我选的0.96寸OLED,SSD1306驱动,I2C接口,只占两根IO口。界面分三屏,按顺序排布:第一屏为充电主界面,实时显示电压、电流、充电模式和已充入的估算容量;第二屏为模式设置界面,显示当前选择的电池类型;第三屏为系统信息界面,显示温度、PID参数校准系数等。

关键数据刷新策略是:电压电流每100ms刷新一次,容量数据1秒刷新一次。OLED刷新频率太高会闪烁,太低了让人觉得卡顿,100ms这个频率模拟下来观感最自然。I2C驱动这里要注意总线速率设为400kbps更流畅,SSD1306本身支持这个速率。

4.2 单按键交互:短按切换,长按设置

界面交互只有一个按键,这其实比一堆按键更考验逻辑设计。短按在不同显示页面间切换,长按2秒进入参数设置。进入设置后,短按调整参数值(加一档),每500ms自动保存到EEPROM,长按退出设置。

实际操作体验下来,设置电池类型最多需要6次短按加1次长按,基本10秒内能完成操作。按键抖动处理用的是20ms延时+连续确认法,没有用外部中断,节省引脚。

4.3 校准方法:没有高精度设备怎么标定

ADC转换结果和真实物理量之间一定存在偏差,主要来源于采样电阻容差、分压电阻偏差和运放失调电压。如果不对这些偏差做校正,显示电压可能偏差0.1V,恒压截止点偏差更明显。我的做法是双点标定:

第一步,用一个万用表(哪怕是几十块钱的)测出充电器空载时的实际输出电压,记下 ADC 读数;第二步,接一个可调电阻负载,调整到另一个电压点,记录第二组数据。然后软件里建立线性映射:

[ V_{real} = V_{adc} \times K + B ]

K 和 B 就是标定系数,通过两组数据反推出来。得到系数后烧录进EEPROM,之后每次开机自动读取。值得注意的是,这个校准参数必须在整机老化30分钟后再做,因为LM358热漂移会让初始阶段的读数偏移几个毫伏。

5. 实测与排坑:从炸管到稳定运行的完整过程

5.1 纹波导致的ADC抖动:差点让我怀疑运放坏了

第一版硬件实测时发现一个问题:充电电流纹波非常大,OLED上显示的电流值在0.8A到1.4A之间快速跳动,用示波器测采样点波形,上面叠加了很大幅度的开关噪声。

排查过程:先怀疑是运放的问题,换了一颗LM358还是无解。后来仔细看波形才发现,噪声不是来自运放,而是来自采样点到运放输入这段走线。因为这段线比较长,而且旁边就是功率电感,开关节点的高频噪声直接耦合进来了。解决方式:把采样走线改成紧贴地线的屏蔽结构(在PCB上做包地处理),同时在运放输入端加了一个1K+104的RC低通滤波。改了之后纹波从±300mV降到了±30mV以内,ADC跳动基本收敛到1个数字量。

5.2 MOS驱动不足的发热:逻辑电平MOS也救不了所有问题

第二版测试时用小电流0.5A充电,MOS管居然烫手。一开始以为是管子质量问题,后来量了栅极波形才发现:驱动电阻太大了,我最初选了100Ω栅极电阻,栅极电容充放电时间常数过大,导致MOS开关边沿非常缓。开关损耗在100kHz开关频率下直接转化为热量。

解决方法是把栅极电阻降到10Ω,同时增加了一个三极管推挽驱动级的输出能力,把栅极充放电时间从2微秒压到200纳秒。实测满载3A充电一小时,散热片温度稳定在60℃左右,完全可接受。

5.3 电池热插拔导致的反向冲击

真正让我吃了一次教训的是电池接入瞬间的问题。第一版程序里,充电MOS在待机状态下是关闭的,这没问题。但当电池被接入的时候,电池电压会反向经过续流电感回路倒灌到Buck的输出电容上,瞬间电流把板载电源引脚干短路了一次。后来我加了一个防倒灌二极管在输出回路中,同时把单片机上电初始化时的GPIO状态配置为输入模式(不输出高电平),确保充电MOS默认关闭,硬件上和软件上双重防止了热插拔反向冲击。

另外一个容易被忽略的细节是:MOS管控制充电通路时,下管栅极放电如果速度太慢,会导致关断瞬间Vds尖峰过高,这时候在DS两端并联一个RC吸收电路(100pF+10Ω),实测尖峰从40V压到了22V以下。

5.4 延伸玩法:放电测容量模式

硬件做稳定后我又加了一个"放电测容量"模式:把充电器输出端接一个固定功率电阻,用PWM调节放电电流,实时记录放电电流和放电时间,用安时积分法估算电池真实容量。虽然精度比不上专业电池测试仪,但相对误差能做到5%以内,对判断18650是否老化非常有参考价值。

5.5 稳定性验证结果

整套系统调到最终状态后,我做了一轮完整的参数测试:

测试项设计指标实测结果
锂电池恒压精度±1%4.19V~4.21V之间,满足
恒流精度±5%0.96A~1.03A之间,满足
镍氢充满检测-ΔV或最高温升用最高电压1.45V截止,实测正常
铅酸浮充电压13.8V13.79V~13.82V之间,满足
充满截止电流设定50mA48mA~52mA之间,满足

我个人在实际操作中最大的感受是,这类带功率的项目,软件只占了四成功夫,六成的精力都要花在硬件调试和排查上。尤其是采样、地线、驱动这三块,任何一个环节偷懒,最后都会在测试阶段找上门。如果大家也想复刻这个项目,建议一定先把采样和地线处理好,再开始写PID,否则你会同时面对多个变量,根本无法定位问题根源。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询