简介:本资源是一套基于中颖SH367309电池管理芯片与STM32F030单片机开发的1–17串锂电池保护板(BMS)完整工程,面向嵌入式硬件工程师、BMS初学者及电池系统开发者,解决多串锂电(三元/磷酸铁锂)实时监测、多重保护与通信集成等核心设计难题。压缩包含196个文件,涵盖47个C语言源码 (.c)、41个头文件(.h)、27个编译中间文件(.o/.d)及调试配置、链接脚本、可执行镜像(.axf)等,完整呈现从底层外设驱动(如TIM、RTC、USART、ADC、I2C)到BMS逻辑层(SOC估算、RS485通讯、温度/电压/电流保护策略)的全栈实现。已有405人学习下载,配套开发板支持过压/欠压/过流/短路/温度保护,并集成光敏检测、扩展IO及上位机调试软件,便于快速验证功能、理解BMS软硬件协同架构与典型故障响应机制。 手里有一块自己画、自己调、自己写的1-17串BMS保护板,是一件挺有成就感的事。这年头凡是带锂电的东西,从两轮车、储能柜到便携电源,都离不开电池管理系统。我这次用中颖SH367309做了一版支持1-17串的锂电池保护板,原理图、PCB和固件全部走开源路线,本文把核心设计思路、关键参数计算和源码框架一次性讲透,新手能跟着画板,老手可以直接拿去改需求。
SH367309这颗料是国产AFE 里性价比非常能打的一颗,它把前端采样、保护逻辑、均衡控制和通信接口全部集成在一个芯片里,外围电路比分离元件方案干净得多。我实测下来,静态功耗、采样精度和MOSFET驱动能力都够用,用来做16串磷酸铁锂或者17串三元锂的BMS完全没问题。这篇文章适合三类人:打算从零搞BMS硬件的工程师、想给现有电池组加保护功能的DIY玩家,以及正在做储能或两轮车项目选型的开发者。
1. 我为什么选中颖SH367309:从选型到芯片能力拆解
1.1 国产AFE里的高性价比选择
BMS的核心是一颗AFE(模拟前端),它负责把所有电芯电压、温度和回路电流采集回来,再通过逻辑判断决定要不要切断充电或放电回路。以前这个位置几乎是TI bq769x0系列和ADI的天下,但近几年国产芯片进步很快,中颖SH367309就是很典型的代表。
我选它的原因很直接:第一,支持1-17串,覆盖范围广,意味着同一块板子只要改元件和配置,就能适配不同串数的电池组,打样一次能复用多个项目。第二,内置充电和放电MOSFET驱动,不需要额外加驱动芯片,外围特别精简。第三,带I2C从机接口,可以和MCU直连,既能读数据也能配置保护阈值,开发灵活度高。第四,价格相对进口芯片有明显优势,小批量打样也不心疼。
当然,选型没有完美的芯片,SH367309也有它的限制,比如均衡电流是外置MOS 方案,均衡能力取决于外部电路设计,不像某些芯片自带大电流均衡。但这个“缺点”在我的项目里反而变成了优点,因为均衡电流可以按电池容量灵活调整,不受芯片内部限制。
1.2 芯片内部结构与工作流程
想用好SH367309,得先弄清楚它的内部结构。它的核心是一个多通道 ADC,轮流采集每一串电芯的正负极差分电压,同时还有一个独立的电流检测通道和多个温度检测通道。这些模拟量经过内部逻辑和比较器处理之后,会决定芯片的过充、过放、过流、短路保护动作。
芯片内部有寄存器组,所有保护阈值、延迟时间、恢复条件都可以通过I2C配置。这里有一个关键点:芯片默认有出厂配置,但实际项目里必须根据电池化学体系(三元锂还是磷酸铁锂)修改过充过放阈值,不能拿默认值直接上电,否则可能保护电压和电池实际要求不匹配。
工作流程也很清晰:上电后芯片先完成自检和ADC校准,然后持续采样电芯电压、温度和回路电流,一旦某个参数超过配置的保护阈值并持续达到延迟时间,芯片就会关断对应的MOSFET,同时把故障状态写到寄存器里,MCU可以通过I2C读出来做进一步处理。这就是一个完整的“采集-判断-执行-上报”闭环。
2. 原理图设计要点:1-17串灵活配置下最容易踩坑的5个细节
2.1 前端采样电路:RC滤波是命根子
电芯电压采样是BMS最重要的一环,SH367309的VC0到VC17引脚通过采样电阻直接接电芯串联节点。每一个采样点都要加RC滤波,这个不能省,因为电芯连接线上会耦合电机、充电机带来的高频干扰,如果不滤波,ADC读数会跳动,严重的会导致误保护。
我在每个VC引脚前面串联一个100Ω电阻,再接一个0.1uF电容到地,构成一阶低通滤波。这个组合的截止频率大概是16kHz,既能滤掉高频噪声,又不会让电压采样响应太慢。
滤波电阻选择有个细节:电阻阻值不能太大,否则和芯片内部的输入漏电流叠加,会造成采样误差。SH367309的输入漏电流在微安级别,用100Ω的电阻产生的误差在微伏量级,完全可以忽略。但如果你为了省成本把电阻省掉了,后面调试时发现电压跳变,别怪我没提醒。
2.2 电芯连接器与走线布局
多串BMS的采样线都是细线,但电流路径是粗线,这里非常讲究开尔文接法。也就是说,采样线必须独立从电芯端子引出,绝对不能共用电流走线,否则大电流流过时,走线电阻上的压降会直接叠加到采样电压上,造成严重的采样误差。
我在板子上专门留了一个电池连接器,每串电芯的正负极端子都有独立的采样焊盘,采样走线从焊盘直接连到VC引脚,中间不经过任何电流路径。布线的宽度可以细一点,但长度要尽量短,而且采样线之间要保持距离,避免串扰。
还有一个很多人忽略的点:电芯串联节点和芯片的GND参考点。SH367309的GND引脚要接到电池组的总负极,同时模拟地和功率地要单点连接,防止大电流在PCB地线上产生压降,干扰芯片参考电位。
2.3 MOSFET驱动电路:充放分离更安全
SH367309的CHG和DSG引脚分别驱动充电MOSFET和放电MOSFET。我采用的是充放电分离的双N-MOS背靠背结构,充电回路和放电回路各用一组管子,故障时两组管子独立关断,安全性比单管方案好很多。
驱动电路里要加栅极电阻,一般10Ω到100Ω,作用是限制栅极充放电电流,防止驱动波形产生过冲和振铃。栅极和源极之间还要加一个10kΩ到100kΩ的下拉电阻,确保上电瞬间MOSFET处于关闭状态,不会出现“一上电就导通”的危险情况。
MOSFET选型要看最大持续电流和耐压。我做的是30A持续电流的平台,选了耐压60V的管子,留了足够裕量。管子导通电阻要尽量低,否则大电流下发热严重,我用的是Rds(on)在5mΩ左右的管子,满载30A时单管损耗大概4.5W,配合散热焊盘勉强能压住。
2.4 温度检测与电流采样
SH367309支持多个NTC温度检测通道,我把NTC放在电芯表面和MOSFET附近。NTC的接法很简单,一端接芯片的检测引脚,另一端通过上拉电阻接基准电压,温度变化引起电阻变化,芯片内部通过ADC测量分压值换算出温度。
NTC的型号我用的10kΩ B值3950,这是市面上最常见的规格,采购容易,换料方便。上拉电阻我选了10kΩ,这样在25℃时输出电压是基准电压的一半,ADC的动态范围利用得最充分。
电流采样是用低阻值采样电阻串联在放电回路上,通过测量采样电阻两端的压差计算电流。这里的核心是采样电阻的功率和温漂。我用的5mΩ采样电阻,持续30A时的压差是150mV,发热功率是4.5W,选的是3W额定功率的合金电阻,还留了散热过孔。温漂控制在50ppm以内,否则大电流下阻值漂移会导致过流保护阈值不准。
2.5 通信接口与MCU选型
SH367309的I2C接口支持标准模式和快速模式,我用的是100kHz标准模式,稳定可靠。I2C的SDA和SCL需要上拉电阻,我选了4.7kΩ上拉,这个是常见配置,在100kHz下时序完全没问题。
MCU我选了STM32G030,性价比高、货源充足,而且有足够的I2C外设和Flash空间。MCU和SH367309之间用I2C连接,MCU负责读取芯片的状态寄存器、电压电流温度数据,同时把处理后的数据通过UART上报给上位机或显示屏。这里要注意I2C的电平匹配,SH367309的工作电压是3.3V,MCU如果工作在5V,需要加电平转换,不能直接连,我统一用的3.3V系统,省去了转换电路。
注意:做BMS的I2C通信时,建议加一个通信超时处理。如果MCU和AFE之间的I2C被干扰卡死,要有重试机制,否则MCU会一直阻塞在读取函数里,导致整个保护逻辑失效。
3. 关键保护参数计算:过充、过放、过流阈值怎么定才靠谱
3.1 过充和过放保护电压的计算逻辑
过充和过放保护电压是BMS的“安全底线”,这两个值直接决定了电池会不会过充起火或者过放损坏。对于三元锂电池,单串过充保护电压我通常设在4.25V,过放保护电压设在2.7V;对于磷酸铁锂电池,过充保护电压设在3.65V,过放保护电压设在2.5V。
SH367309的过充和过放阈值是通过寄存器配置的,以毫伏为单位写入。比如要设置4.25V的过充保护,就直接往过充保护阈值寄存器写入4250。这里有个细节要注意:芯片测到的电压是实际电芯电压,还是经过分压之后的电压,SH367309是直接测量VC引脚之间的差分电压,所以写入的阈值就是实际电芯电压值,不需要额外换算。
另外,过充保护还分一级和二级,一级保护是预警,二级保护是强制断开。我习惯把一级保护设在4.20V,二级保护设在4.25V,这样一级保护先动作让充电器停止,如果一级保护失效,二级保护还能兜底。
3.2 过流保护与短路保护的参数整定
过流保护阈值需要根据电池组的最大持续放电电流来设。以30A持续放电为例,充电过流保护我设在35A,放电过流保护设在40A。这里要注意,过流保护的响应有延迟,延迟时间要设得比电机瞬态电流的持续时间长,否则电机一启动,BMS就误保护了。
我用的是5mΩ采样电阻,40A过流时采样电阻上的压降是200mV,芯片检测到这个电压后就触发保护。延迟时间我设的是16ms,这个值既能过滤掉正常的瞬态电流尖峰,又能在真正的过流故障发展成灾难之前切断回路。
短路保护的阈值要比过流保护高一截,响应时间要更快。我在代码里把短路保护阈值设为100A对应的压降,延迟时间设为0.5ms以内。短路保护的动作就是直接把放电MOSFET关断,保护电池和回路上的其他器件。
延迟时间是BMS参数整定里最让人头疼的部分:设大了,故障电流持续太久会烧管子;设小了,正常设备的浪涌电流就会误触发保护。我建议先看一下电池组负载的特性,如果是电机类负载,启动瞬间往往是额定电流的2-3倍,持续几十毫秒,那过流延迟就要设在50ms以上,短路延迟保持快响应即可。
3.3 均衡开启电压与均衡策略
电芯一致性是电池组的“慢性病”,均衡是解决这个问题的关键手段。SH367309支持被动均衡,也就是通过外部均衡MOSFET把高电压电芯的能量通过电阻放掉。我设计的均衡开启电压是3.5V(三元锂)/3.4V(铁锂),均衡电流设定在40mA到100mA之间。
被动均衡电流的计算很简单:均衡电流等于电芯电压除以均衡电阻值。我用了50Ω均衡电阻,在3.6V电芯电压下均衡电流约72mA,这个量级对常见的50Ah以上电池组来说足够在充放电周期内修正几十毫伏的不一致。
实际设计中要注意均衡电阻的功率损耗。72mA通过50Ω电阻时,电阻耗散功率约0.26W,我选了0805封装但额定功率0.25W会偏紧,所以最终用了1206封装0.5W的电阻,稳妥得多。均衡时MOSFET会发热,PCB布局时要把均衡MOSFET分散布置,避免热量集中。
3.4 温度保护阈值的设定
温度保护分为充电温度保护、放电温度保护和MOSFET过温保护。我设置的参数如下表:
这些参数是基于常见电芯规格书推荐的温度范围来的,具体项目要根据电池厂家的规格书调整,不要照抄我的值。温度采样有个滞后恢复设计,温度到阈值后先触发保护,等温度降下来5℃才恢复,避免温度在阈值附近震荡导致MOSFET频繁开关。
4. 源码架构与核心模块实现:从寄存器配置到保护状态机
4.1 初始化 流程:上电后的第一步
固件初始化是整个BMS软件的基石,顺序错了后面全乱。我先把代码框架列出来:
void bms_init(void)
{
mcu_clock_init(); // 配置MCU时钟
i2c_init(); // 初始化I2C外设
gpio_init(); // 初始化LED、蜂鸣器、继电器驱动引脚
sh367309_soft_reset(); // 复位SH367309
delay_ms(10); // 等芯片稳定
sh367309_check_id(); // 读芯片ID,确认通信正常
sh367309_set_protection_params(); // 配置保护阈值
sh367309_enable_afe(); // 使能AFE
bms_state = BMS_STATE_NORMAL; // 进入正常运行状态
}
初始化的时候有个值得注意的点:sh367309_check_id()这一步不能省,读芯片ID是验证I2C通信是否正确的最快方法。如果ID读出来不对,后面所有寄存器配置都是徒劳。我调试的时候经常遇到I2C地址配错导致读写无响应的情况,读ID能第一时间暴露问题。
配置保护参数的set函数里,把所有过充、过放、过流、温度阈值和延迟时间全部写进去。这里有个经验:全部配置完之后,再回读一遍寄存器,确认写进去了。因为I2C在恶劣环境下可能丢数据,尤其是在电机开关瞬间,总线受到干扰很容易写失败。
4.2 ADC采样与数据滤波算法
SH367309的ADC数据读取是整个系统最频繁的操作。我通过I2C读取每个电芯电压、总电压、电流、温度寄存器,然后做软件滤波。
#define ADC_SAMPLE_COUNT 8
uint16_t adc_filter(uint16_t new_value)
{
static uint16_t buffer[ADC_SAMPLE_COUNT];
static uint8_t index = 0;
static uint32_t sum = 0;
static uint8_t count = 0;
if (count < ADC_SAMPLE_COUNT) {
count++;
} else {
sum -= buffer[index];
}
buffer[index] = new_value;
sum += new_value;
index = (index + 1) % ADC_SAMPLE_COUNT;
return (uint16_t)(sum / count);
}
这是一个典型的滑动平均滤波,每次采到新值就替换掉最老的值,求平均。用8次采样取平均,既能有效抑制电压波动,又不至于让响应变得太慢。
我踩过的一个坑是:滤波窗口太大导致保护响应变慢。刚开始我用了32次采样做平均,结果过充保护触发延迟达到了几百毫秒,差点把电芯充到4.4V以上。后来我把滤波窗口缩小到8次,保护延迟才回到可接受的范围。ADC滤波和保护响应是一对矛盾,必须在软件层面平衡好。
4.3 保护判断与状态机实现
BMS的核心逻辑是一个状态机,状态切换直接决定MOSFET的通断。我的状态机很简单,只有三个主状态:正常、充电保护、放电保护。
void bms_state_machine(void)
{
switch (bms_state) {
case BMS_STATE_NORMAL:
if (cell_voltage_max >= OVP_THRESHOLD) {
bms_state = BMS_STATE_CHG_OVP;
mosfet_chg_off();
}
if (cell_voltage_min <= UVP_THRESHOLD) {
bms_state = BMS_STATE_DSG_UVP;
mosfet_dsg_off();
}
break;
case BMS_STATE_CHG_OVP:
if (cell_voltage_max <= OVP_RELEASE) {
bms_state = BMS_STATE_NORMAL;
mosfet_chg_on();
}
break;
case BMS_STATE_DSG_UVP:
if (cell_voltage_min >= UVP_RELEASE) {
bms_state = BMS_STATE_NORMAL;
mosfet_dsg_on();
}
break;
}
}
这个状态机的设计思路是:保护动作由芯片硬件完成,MCU的状态机只是做备份和上报。也就是说,即使MCU死机了,SH367309芯片本身依然能独立完成保护动作,MCU只是在决策层面做更精细的控制和数据上报。这种“硬件兜底+软件增强”的架构是工业级BMS的标准做法,安全性和可靠性都有保障。
状态切换中的恢复条件比保护条件更重要,代码里OVP_RELEASE和UVP_RELEASE都要设置迟滞值,防止电芯电压在阈值附近抖动导致保护频繁开关。
4.4 均衡控制算法与实现
均衡策略我采用的是“充电末尾均衡”:当任意电芯电压超过均衡开启电压,并且最高电压和最低电压的差值超过30mV时,开启最高电压电芯的均衡。这样在充电接近满电时,把电压高的电芯能量放掉,让所有电芯同步到达满电。
void balance_control(void)
{
uint16_t vmax = get_max_cell_voltage();
uint16_t vmin = get_min_cell_voltage();
uint8_t max_index = get_max_cell_index();
if (vmax >= BALANCE_START_VOLTAGE && (vmax - vmin) >= 30) {
balance_on(max_index);
} else {
balance_off_all();
}
}
实际运行中这个策略效果不错,16串磷酸铁锂电池经过几个充放电循环后,压差可以从80mV收敛到20mV以内。但如果电池组本身一致性很差,压差超过200mV,均衡会一直开启,导致均衡电阻持续发热,这时候软件里要加均衡超时限制,比如连续均衡4小时后强制进入休息状态,防止长时间过热。
4.5 通信协议与数据上报
通信模块我做了两个功能:通过I2C读取SH367309的数据,再通过UART把数据发送出去。UART的数据帧格式很简单,帧头、数据区、CRC校验、帧尾,上位机根据这个协议解析显示电压、电流、温度、SOC和故障状态。
void send_bms_data(void)
{
uint8_t buf[20];
uint8_t index = 0;
uint16_t crc;
buf[index++] = 0xAA; // 帧头
buf[index++] = 0x55;
buf[index++] = bms_state;
buf[index++] = (uint8_t)(cell_voltage_max / 100); // 最高电压高字节
buf[index++] = (uint8_t)(cell_voltage_max % 100); // 最高电压低字节
buf[index++] = (uint8_t)(cell_voltage_min / 100);
buf[index++] = (uint8_t)(cell_voltage_min % 100);
buf[index++] = (uint8_t)(total_current / 10);
crc = calc_crc(buf, index);
buf[index++] = (uint8_t)(crc >> 8);
buf[index++] = (uint8_t)(crc & 0xFF);
buf[index++] = 0x0D; // 帧尾
uart_send(buf, index);
}
这里强调了协议的健壮性,帧头、长度、校验、帧尾四个要素缺一不可。很多新手做通信只发原始数据,接收端一旦出现一个字节错位,后面全是乱码。加上帧头和CRC校验之后,接收端能及时丢弃错误帧,不会影响数据解析。
5. 打板调试实录:常见问题排查与实测建议
5.1 上电前的检查清单
BMS打板回来之后,千万不能直接上电池包,我吃了好几次亏。先做“桌面四步检查”:
第一步,用万用表量一下电池总正和总负之间有没有短路,如果MOSFET方向装反或者贴错元件,上电瞬间就可能冒烟。第二步,先不上电芯,只给MCU供电,检查I2C能不能正常读到SH367309的ID和寄存器内容。第三步,断开所有MOSFET的驱动信号,用假电池组或稳压电源模拟电芯电压,检查芯片的ADC采样读数是否正确,误差应该在±10mV以内。第四步,全部正常后再接真实电池组,用可调限流电源做首次充电测试,电流要从0.1A慢慢往上涨,观察保护动作是否按预期触发。
这四步看着简单,实际上能过滤掉80%的硬件问题。我见过不少同行直接上电池,结果MOSFET栅极接反直接炸管,板子报废不说,还容易伤到电池。
5.2 常见问题速查表
这些坑我都踩过,尤其是最后一项“上电后MOSFET直接导通”。我最早一版PCB设计时漏了栅极下拉电阻,结果每次接上电池,放电MOSFET就立刻导通,电芯瞬间短路,电流巨大,保护板直接报废。加上10kΩ下拉电阻后再测试,问题彻底消失。所以栅极下拉不是可选件,是必选项。
5.3 实测数据分享:充电保护全流程记录
我用16串磷酸铁锂电池做了一次完整的充电保护测试。电池组起始总电压50.4V,单串电压平均3.15V,充电电流设定20A。当最高单体电压爬到3.65V时,芯片触发过充保护,充电MOSFET关断,充电电流从20A瞬间降到0A。
从示波器波形看,从最高串电压达到3.65V到MOSFET完全关断,动作时间大约2ms,这个速度完全符合预期。关断瞬间,电芯电压从3.65V回落到3.60V左右,这是因为电流消失后电芯内阻上的压降消失,电压自然回落。这个现象是正常的,不是保护电路出了问题。
放电过流保护我也实测了,用电子负载从30A突然拉到60A,放电MOSFET在十几毫秒内关断,保护动作可靠。恢复条件是电流消失后需要手动或者自动解除,我在代码里设的是自动恢复,条件满足后延时5秒重新开启放电MOSFET,这个功能在电动工具里很实用,避免工具被临时卡住就锁死。
5.4 关于“1-17串”扩展能力的思考
SH367309支持1-17串的特性,让同一套PCB设计可以覆盖多种电池方案。我的板子上预留了配置跳线和电阻位,通过改变采样电阻的接法,可以在4串、10串、13串、16串、17串之间切换,只需要修改固件里的串数配置和保护阈值即可。
例如做4串便携电源时,我把芯片配置成只启用前4个VC通道,其余通道悬空并做屏蔽处理。做17串时就把所有通道全部启用,同时把均衡MOSFET的数量增加,保证高串数下均衡能力不缩水。这种平台化设计思路大大降低了多项目并行开发的工作量。
我建议如果你也想做这种可配置的BMS板,原理图阶段就把所有串数的采样点都画出来,用0Ω电阻或者跳线选择通路,不要在PCB阶段才想着加跳线,那样走线会非常痛苦。
5.5 后续可扩展的方向
这套BMS平台后续要扩展,还有几个方向可以走。一个是增加SOC估算功能,通过实时电流积分和开路电压矫正,推算出剩余电量,我现在用的简易SOC算法精度在10%以内,够显示用,但如果拿去做储能系统,精度要求会更高,得用卡尔曼滤波或者查表矫正。另一个是增加蓝牙模块,把BMS数据传到手机上查看,市面上很多BMS产品就是通过这个卖点做差异化。再一个就是多从机级联方案,用两片SH367309级联做更大串数的电池包,虽然芯片本身支持到17串,但加上级联能力就能扩展到30串以上,这个对有大型储能需求的项目会非常有用。
我在实际调这块板子的过程中,最大的体会是:BMS开发最考验人的不是某一项技术,而是细节的积累。一个采样电阻的选型、一段滤波代码的窗口大小、一个栅极下拉电阻的有无,都能决定整个系统稳不稳定。很多问题看起来像是玄学,最后查出来都是很基础的硬件或者逻辑错误。这块SH367309的板子从原理图到固件前后迭代了三版,每次改版都离“可靠”两个字更近一点。如果你也在做类似项目,先把参数算清楚,再动手画板写代码,后面调试会省很多事。
————————————————
版权声明:本文为CSDN博主「ChanKinYi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_29163857/article/details/164216640
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
×
|