EMS 知识库
首页 / knowledge/代码解析/midware/bms

bms.h

源文件路径:midware/bms/bms.h 所属模块:midware / bms(BMS 电池管理中间层) 代码行数:1255

1. 文件职责

本文件是 EMS 主控固件中「电池(BMS)数据汇聚层」的公共头文件,定义电池信息的唯一全局运行时容器 BATTERY_TABLE_T(实例 g_t_bat_info)、断电保存用的配置表、以及全部 BMS 相关故障/保护/告警位域联合体。

它把两类数据区分开:BATTERY_CONFIG_TAB_T(需掉电保存,落 Flash)与 BMS_RUN_TABLE_T(运行时实时数据,掉电不保存、断通信要清零)。上层逻辑(logic/)、HMI(hmi/)、网络(net/)、Modbus(midware/interface/)、逆变器中间件(midware/inverter/)都通过 bms.h 声明的 bms_read_* / bms_get_* / bms_set_* 接口访问电池数据,而真正的数据填充由 bms.c 的 task_bms 驱动 midware/bms/alpha/battery_comm.c 解析 CAN 帧完成。

本文件不含任何函数实现,只有宏、类型定义、extern 全局变量声明与对外函数原型;所有结构体都在 #pragma pack(1) 下按 1 字节对齐,以保证 Flash 读写与 CAN 报文的字节布局一致。

2. 关键数据结构与宏

2.1 电池产品号宏(bms.h:20-59)

名称类型说明
BATTERY_MAX_NUM宏12,单系统最大并联电池台数,是所有 [BATTERY_MAX_NUM] 数组的上界
ALPHA_M4850_BATTERY_ID … ALPHA_SMILE_M_BAT_13_9P_HC_ID宏ALPHAESS 自有电池产品号:M4850=1、M4860=2、M48100=3、M48112=13、SMILE5=16、M4856-P=24、SMILE10.3=27、SMILE10.1=30、SMILE5.8=33、SMILE5-JP=34、SMILE13.3=35、SEEDS4.1P=60、SEEDS8.2P=61、SMILE-BAT-5P=74、8.2PH=75、8.2PHO=76、8.2PHA=77、5PH=84、G3-10.1P=91、8.2PH-P=98、G3-3.8S=106、G3-4.8S=116、GY-8.2PH=118、M-BAT-5P=142、G3-7.6P=143、M-BAT-13.9P=144、G3-9.3S=146、M-BAT-13.9P-HC=311
ALPHA_FACTORY_BAT_INT_ID宏255,工厂测试用电池产品号
OEM_ALPHA_SMILE_BAT_5PH_ID(89) / OEM_ALPHA_SMILE_BAT_8_2PHO_ID(90) / OEM_ALPHA_SMILE_BAT_8_2PH_SMART_ID(96) / OEM_ALPHA_SMILE_BAT_8_2PH_ROCKET_ID(97) / OEM_ALPHA_HEB8200_25_0EP_ID(100) / OEM_SUNPOWER_BAT_1_DC_10_1_INT_ID(108)宏OEM 贴牌电池产品号,容量/型号映射时与 ALPHA 号分开处理
ALPHA_BAT_HEAT_MAX_CURRENT_ERR_RANGE宏200,电池加热时逆变器侧电流与 BMS 上报加热电流的最大允许偏差(对应 u16_heat_current 的 0.01A 单位 → 2A)
ALPHA_BAT_HEAT_MAX_VOLTAGE_ERR_RANGE宏100,电池加热电压最大允许偏差(0.1V/bit,实际使用时再乘以电池台数)
VERSION_BMS_HARD / VERSION_BMS_HARD_2宏字符串 "V1.00" / "V1.02",bms_read_hard_version() 的返回值,按是否 G3-7.6P 区分
TYPE_BAT_* / TYPE_SMILE_* / TYPE_OEM_*宏各产品号对应的平台上报型号字符串(如 "M4850"、"SMILE-BAT-8.2PH"、"OTHER_BAT" 等),写入 s_type_splice[31] 后随 s_type_splice 上报云平台
ZOE_OEM_TYPE_* / SMART_OEM_TYPE_* / ROCKET_OEM_TYPE_*宏OEM 客户专用型号字符串("ZSPA BM48032"、"ZSPA BM80032"、"Smart Battery"、"Rocket Battery")
DEBUG_BMS宏0,bms.c 中大量 printf 调试输出的总开关

2.2 枚举类型

名称类型说明
BATTERY_STATUS_E枚举电池充放电使能状态机:FORBID_CHG_DISCHG_E=0、FORBID_CHG_ALLOW_DISCHG_E=1、ALLOW_CHG_FORBID_DISCHG_E=256、ALLOW_CHG_ALLOW_DISCHG_E=257、FORCE_CHG_FORBID_DISCHG_E=512、FORCE_CHG_ALLOW_DISCHG_E=513。值刻意做成「高 2 位=充电权限、次 2 位=放电权限」,供 u16_status_flag 直接比对
BATTERY_MOS_STATUS_E枚举充/放电 MOS 四态组合:双开、充开放闭、充闭放开、双闭
BMS_ID_E枚举电池编号 0~18,0 为「全部」,BMS_ID_MAX_E 为哨兵
BMS_SERIES_PARA_STATE_E枚举串并联状态:BMS_NULL_E=0、BMS_PARA_E=1(并联)、BMS_SERIES_E=2(串联)
BMS_PLATFORM枚举电池 BMS 主控平台:TYPE_NXP=1、TYPE_GD32=2、MAX_TYEP=3(未知)
BMS_HARDWARE_PLATFORM枚举硬件平台分类:BMS_48V=0、BMS_HV=1(150V/300V 高压),BMS_MAX_TYEP 为哨兵
BMS_SET_SN_STATUS_E枚举并机 SN 配置状态机:NONE→IDLE→SRC_SEND_E→DEST_SEND_E→WATTING_E→FINISH_E
BMS_SELF_LOCK_STATUS_E枚举电池自锁处理状态机:BMS_SELF_LOCK_NONE/CONFIG_SYNC/IDLE/WAIT_SEND_CLEAR/WAIT_CLEAR/UPLOAD_FAULT_CLEAR;另定义发送子命令 BMS_SELF_LOCK_SEND_CONFIG_COMMAND(0)/BMS_SELF_LOCK_SEND_CLEAR_COMMAND(1)
BMS_HEAT_STATE枚举加热主状态机:BMS_NORMAL_FSM、BMS_INV_HEAT_FSM(逆变器加热中)、BMS_INV_HEAT_FAULT_FSM(加热故障)、BMS_INV_HEAT_MAX
BMS_FSM_SUBSTATE枚举状态机子步骤:BMS_ENTER_SUB→BMS_EXECUTE_SUB→BMS_EXIT_SUB,用于自加热状态机的一次性进入/退出动作
BMS_FAULT_E枚举64 位故障位定义:温度传感器故障、MOS 故障、断路器断开、拨码不一致、从机通信丢失、SN 缺失、主机通信丢失、固件版本不一致、多主机错误、MOS 高温、绝缘故障、总压异常、MOS 反馈失败、预充失败、17823/17841 通信失败、MOS 温度传感器故障、线束抖动故障、09AFE 配置错误、AFE 高压电路错误、加热板无效告警;BMS_FAULT_CURRENT_ERROR=32 单独跳号
BMS_PROTECTION_E枚举保护位定义:温度不均衡、过温、放电低温、充电低温、放电过流、充电过流、单体过压、单体欠压、短路保护
BMS_WARNING_E枚举告警位定义:温度不均衡、过温、放电低温、充电低温、放电过流、充电过流、单体过压、单体欠压、软件版本不一致、MOS 温度传感器故障、SOC 不一致、BMS SCI 丢失、BMS 风扇故障
BmsInfoValueType枚举SELF_INFO_U8/SELF_INFO_U16/SELF_INFO_U32,用于按类型访问 BMS_SELF_INFO_TABLE_T 的字段

2.3 位域联合体(电池状态码)

名称类型说明
BMS_FAULT_U联合体u64_all / byteData[8] / 64 个 1 位标志(按 BYTE0~BYTE7 排列),承载电池故障码。位名与 BMS_FAULT_E 一一对应,未使用位命名 bit21~bit63
BMS_PROTECTION_U联合体同上结构,承载电池保护码,BYTE0 对应 BMS_PROTECTION_E 前 8 位
BMS_PROTECTION_EXTEND1_U联合体DCDC / 高压模块扩展保护码:母线电压异常、母线过压、DCDC 过温欠温、母线短路、DCDC 放电过载、DCDC 软起失败、谐振腔过流、电芯侧过流、功率线/采样线未接、维护模式、电芯异常、并机参数不一致、电芯节数不匹配、内部通信异常、加热膜异常、地址重复
BMS_PROTECTION_EXTEND2_U联合体u16_all + 位域,仅定义 u8_power_line_over_temperature(功率线过温)
BMS_WARN_U联合体64 位告警码,位名与 BMS_WARNING_E 对应,含 u8_socket_high_temperature_alarm(插座高温告警)
BMS_SINGLE_SN_U联合体u64_sn 与 8 个 byte1..byte8,用于把 BMS 上报的 SN 逐字节拼接
BMS_SELF_LOCK_FAULT_U联合体电池自锁故障联合体:既有 word.u16_word1..u16_word4(字视图)也有 64 位位视图。bit.self_lock_enable_flag(bit7)为自锁使能同步标志,word.u16_word4 为自锁故障类型;BYTE6/BYTE7 复用了温度传感器故障、短路保护、MOS 故障、单体欠压/过压、过温、充/放电低温、温度不均衡、充/放电过流等位

2.4 结构体

名称类型说明
BATTERY_INFO_TAB_T结构体单台电池的持久化基础信息:s_single_sn_splice[32]、u16_single_soft_ver、u8_single_platform_type、u8_reserved[21]。落在扩展配置区,掉电保存
BMS_ACTIVATION_TIME_TABLE_T结构体电池激活时间(u16_bat_activation_years/u8_bat_activation_months/u8_bat_activation_days)。年份 > 2000 视为「已有激活时间」,是 handle_bat_activate_time_info() 的判定依据
BMS_STATIC_TABLE_T结构体断电不保存、断通信要保持的加热相关中间状态:加热主状态机 e_bms_heat_FSM、加热膜故障标志、加热展示状态、加热方式、进入/退出/异常退出步骤、四个时间戳(u32_heat_tick/u32_drop_out_heat_tick/u32_fault_drop_out_tick/u32_heat_fault_tick)、故障恢复次数(最多 3 次)、预存的加热请求/SOC 低标志/自加热能力、必须外部加热标志、SOC 阈值 u8_set_bat_heat_soc(20)、升温阈值 u8_set_bat_increase_temp(2)
BMS_SELF_INFO_TABLE_T结构体电池自评估(SOH/SOC 算法)统计量:容量/能量吞吐量、剩余容量与往返效率、欧姆内阻、初始/当前/演化自放电率、等效循环、深度放电/充电次数、超上下限运行与充电时间、生产日期、装机日期及 u32_service_date_unix、u8_service_date_sync 同步标记、u32BmsCommTick 最后通信时间戳
AnyValue联合体u8/u16/u32 三态容器,配合 BmsInfoValueType 做统一取值
BMS_RUN_TABLE_T结构体本文件最核心的结构体,全部实时电池运行数据(约 200 个字段):连接状态与单台软件版本、硬/软件版本、型号字符串、SN 拼接数组、主 SN、DoD、额定单体电压/容量、状态标志、工作状态、电池台数;5 组按电池索引的位域数组(故障/保护/扩展保护1/扩展保护2/告警,长度 BATTERY_MAX_NUM+1);MOS 控制标志(u8_bms_mos_set_flag/u8_bms_mos_enable/u8_bms_mos_open_set_flag/u8_bms_mos_open_enable/u8_bms_self_lock_clear_flag);ATE 允许放电标志;重启/清能量/关机指令标志;充放电截止电压与最大倍率电流;允许充放电标志、最大充/放电功率、关机状态、继电器状态;总 SOC/总压/总流;SOC 显示最小最大值;最低/最高单体电压及其模块号与串号;低温/高温与功率线低温/高温样本点;单台 SOC/SOH/循环/运行小时/电流/温度/单体电压数组;s8_temp 温度;串并联状态;能量使能、能量同步标志、充/放电电量、u16_real_time_energy_rating、u16_energy_rating;自锁位域 u_self_lock_status;激活时间相关数组;单体温度/电压采样缓存 s16_single_cell_temper_sample[12][16]、u16_single_cell_volt_sample[12][32];校时标志;加热相关字段(加热电压/电流设定、加热状态、请求加热、加热功能、加热继电器、自加热功能、加热台数、必须外部加热、停功率标志、加热继电器指令、逆变器加热指令 u8_inv_heat_cmd、BMS 加热指令 u8_bms_heat_cmd 0xAA/0x55、单体 AH、加热电压/电流实测、加热初始温度);平台查询日志字段;u16_charge_pro_cur_step_1/u16_discharge_pro_cur_step_1/u16_bat_rate_volt_instant;剩余可用电量与系统最大存储能力;u_bms_self_info[12];格式化标志;混装相关(u8_bat_mixed_installation_flag、u8_bat_MIX_info_flag、s_type_splice_MIX[12][31]、u8_MIX_dod、u16_MIX_cell_rate_volt/AH/type/capacity、u8_brand、u8_origin);需求 1 u32_max_capacity[12];需求 2 u64_fault_code_raw/u64_warning_code_raw/u8_fault_code_valid/u8_warning_code_valid;需求 5 串并联 u8_a_cluster_id[6]/u8_a_cluster_status[6]/u8_b_cluster_id[6]/u8_b_cluster_status[6]/u8_a_cluster_mode/u8_b_cluster_mode/u8_a_cluster_valid/u8_b_cluster_valid
BATTERY_CONFIG_TAB_T结构体需掉电保存的电池配置:u16_head 头、使能 u8_ready、类型、台数、软件版本、DoD、额定单体电压/容量、串并联状态、型号字符串、自锁使能与自锁故障类型、预留、硬件版本、充放电截止电压、加热使能 u8_heat_en、充/放电倍率电流 step1、额定电压瞬时值、u8_reserved[57]、u8_reserved_flag、u16_crc_code
BATTERY_EXTEND_CONFIG_TAB_T结构体扩展配置区:u16_head + BATTERY_INFO_TAB_T battery_basic_info[18](注意长度是 18 而非 12)+ u8_reserved[12] + u16_crc_code
BATTERY_SET_SN_TABLE_T结构体并机 SN 改写任务表(6 个槽位):u8_status、u8_send_sequence_number、源/目标 SN 字符串各 32 字节
BATTERY_TABLE_T结构体顶层聚合结构:t_config_data + t_extend_config_data + t_run_info + t_activate_time_info[BATTERY_MAX_NUM] + t_static_data。全局实例 g_t_bat_info 按绝对地址放在 SDRAM
CAN_SEND_FRAME_T结构体需求 3 自定义 CAN 帧:u32_can_id、u8_data[8]、u8_frame_type(0 标准帧 / 1 扩展帧)
CAN_SEND_QUEUE_T结构体需求 3 发送队列:u8_count、u8_send_index、u32_last_send_tick、u8_status(0 空闲 / 1 发送中)、t_frames[6]

2.5 编译期断言

名称类型说明
STATIC_ASSERT(ASSERT_FLASH_SECTOR_SIZE % sizeof(BATTERY_CONFIG_TAB_T) == 0)宏调用bms.h:1103,保证配置表大小能整除 Flash 扇区,便于按扇区整块读写
STATIC_ASSERT(ASSERT_FLASH_SECTOR_SIZE % sizeof(BATTERY_EXTEND_CONFIG_TAB_T) == 0)宏调用bms.h:1114,同上,针对扩展配置表

3. 函数清单

本文件不定义任何函数,只声明对外接口(bms.h:1156-1252)。下表列出全部声明,供调用方核对。

函数名作用域说明
task_bms全局电池数据采集主任务入口(uCOS-II 任务,user/main.c:200 用 OSTaskCreateExt 创建)
bms_get_connect_state全局读取电池是否在线
bms_reset全局请求重启电池
bms_clear_energy全局清空并同步电池充放电电量
bat_low_soc_detect全局SOC 低事件上报检测
bms_set_shutdown全局请求电池关机
bms_set_mos_enable全局设置充/放电 MOS 开合
bms_set_mos_open_enable全局设置主 MOS 断开/闭合(干接点联动)
bms_set_ready_enable / bms_get_ready_enable全局读写「电池使能」配置位
bms_get_store_type全局读取电池产品号(t_config_data.u8_type)
bms_get_store_MIX_type全局读取混装场景下第 mun 台电池的产品号
get_bms_hardware_platform全局按产品号/额定电压判定 48V 还是高压平台
bms_get_store_num全局读取电池台数
bms_get_store_ver全局返回软件版本字符串(id=0 整机版本,1~num 单台版本)
bms_get_platform全局返回单台电池平台字符串("NXP" / "GD " / " ")
bms_get_store_sn全局返回第 index 台电池 SN 字符串指针
bms_set_self_lock_enable / bms_get_self_lock_enable / bms_set_self_lock_clear全局读写电池自锁使能与清除请求
bms_read_chg_cut_rate_volt全局充电截止电压(取自配置表)
bms_read_chg_max_rate_cur全局最大充电倍率电流(由最大充电功率 / 总压换算)
bms_read_dischg_cut_rate_volt全局放电截止电压
bms_read_dischg_max_rate_cur全局最大放电倍率电流
bms_read_max_charge_power全局最大充电功率(升级中/混装异常时返回 0)
bms_read_max_dischg_power全局最大放电功率(UPS + ATE 允许放电时兜底 1000W)
bms_read_work_status全局电池工作状态
bms_read_relay_status全局电池继电器状态
bms_read_num全局电池台数(运行值)
bms_read_shut_down全局电池关机标志
bms_read_single_soh全局单台电池 SOH
bms_read_temp全局电池温度
bms_read_total_soc / bms_read_total_volt / bms_read_total_cur全局电池组总 SOC / 总压 / 总电流
bms_read_single_single_cycle / bms_read_single_single_runhrs全局单台循环次数 / 运行小时
bms_read_status_flag全局充放电使能状态字(BATTERY_STATUS_E)
bms_read_total_power全局电池组总功率(总压 × 总流 / 10000)
bms_read_single_soc / bms_read_single_cur全局单台 SOC / 电流
bms_read_protection_code全局13 台电池保护码按位或合并
bms_read_protection_extend2_code全局13 台扩展保护码 2 按位或合并
bms_read_fault_code全局13 台电池故障码按位或合并
bms_read_cell_min_volt_info / bms_read_cell_max_volt_info全局单体最低/最高电压打包值(模块号<<24 \串号<<16 \电压)
bms_read_low_temper_info / bms_read_high_temper_info全局最低/最高温度打包值
bms_read_pwrline_low_temper_info / bms_read_pwrline_high_temper_info全局功率线最低/最高温度打包值
bms_read_single_low_temper_info / bms_read_single_high_temper_info全局单台电池温度打包值(样本点<<16 \温度)
bms_read_hard_version全局BMS 硬件版本字符串
bms_read_battery_model全局电池型号字符串(配置值)
bms_read_battery_cell_model全局混装场景下单台电池型号
bms_read_battery_cell_dod全局混装场景下单台 DoD
bms_read_battery_MIX_capacity全局混装场景下单台容量
bms_read_battery_capacity全局系统总容量(同型号 = 单台容量 × 台数;混装 = 逐台累加)
bms_read_battery_series_para_state全局串并联状态
bms_cell_rated_vot全局额定单体电压(0.01V → V)
bms_read_rated_vot_instant全局额定电压瞬时值
bms_read_charge_pro_cur_step_1 / bms_read_discharge_pro_cur_step_1全局充/放电倍率电流 step1
bms_read_battery_available_capacity全局可用容量(即配置 DoD)
handle_bat_set_activation_time全局云平台下发的电池激活时间写入处理(唯一带结构体指针入参的公开接口)
get_bat_heat_forbid_power_flag全局加热期间是否停电池功率
get_bms_cell_data_support全局该电池型号是否支持云 BMS 分钟级数据(仅 G3-3.8S)
bms_read_current_actual_remaining_available_electricity全局当前实际剩余可用电量
bms_read_max_system_storage_capacity全局系统最大存储能力
bms_get_energy_rating / bms_get_real_time_energy_rating全局系统额定能量 / 实时电池能量总数
handle_bat_heat_prestore_info全局按 CAN 帧 ID 预存加热相关 BMS 状态
handle_bat_heat_soc_info全局按各单台 SOC 判定加热模式(SOC 低标志)
bms_read_mixed_installation_flag全局混装标志(0 老电池/新老混装,1 新电池)
bms_MIX_battery全局电池混搭信息有效标志
bms_read_single_max_capacity全局需求 1:单台 SOC 算法最大容量值(Ah)
bms_read_fault_code_by_id / bms_read_warning_code_by_id全局需求 2:指定电池 ID 的原始故障码/告警码
bms_is_fault_code_valid / bms_is_warning_code_valid全局需求 2:指定电池 ID 的故障/告警码有效标志
can_send_queue_clear / can_send_queue_add / can_send_queue_start / can_send_task全局需求 3:自定义 CAN 帧下发队列的清除/入队/启动/循环发送
bms_read_a_cluster_mode / bms_read_a_cluster_id / bms_read_a_cluster_status全局需求 5:A 簇运行模式、指定位置电池 ID、旁路状态
bms_read_b_cluster_mode / bms_read_b_cluster_id / bms_read_b_cluster_status全局需求 5:B 簇运行模式、指定位置电池 ID、旁路状态
bms_is_a_cluster_valid / bms_is_b_cluster_valid全局需求 5:A/B 簇数据有效标志

4. 核心逻辑解析

4.1 内存布局:SDRAM 绝对定位 + 1 字节打包

g_t_bat_info 的类型是 BATTERY_TABLE_T,实际定义在 bms.c:39:

BATTERY_TABLE_T g_t_bat_info __attribute__((at(SDRAM_BAT_INFO_ADDR)));

SDRAM_BAT_INFO_ADDR(hardware/sdram/sdram.h:65)由 SDRAM_WS2812_DATA_ADDR + SDRAM_16K 计算得来,注释标注长度 7KB。也就是说这块结构体不是普通 .bss,而是被链接器钉死在外部 SDRAM 的固定地址上——因为 BMS_RUN_TABLE_T 内含 s16_single_cell_temper_sample[12][16]、u16_single_cell_volt_sample[12][32] 等大数组,加上 5 组 13 元素的 64 位位域数组,整个结构体体积远超 MCU 内部 SRAM 能承受的规模。

#pragma pack(1)(bms.h:217 ~ bms.h:1149)保证所有字段无填充,这有两个直接后果:

  1. BATTERY_CONFIG_TAB_T 与 BATTERY_EXTEND_CONFIG_TAB_T 可以按固定字节偏移整块写入 Flash 扇区,STATIC_ASSERT 进一步确认尺寸整除扇区;
  2. 联合体的 byteData[8] 与 64 个位域严格重叠,CAN 帧按字节写入即可用位名读取,不需要手工移位。

4.2 三类数据的生命周期划分

容器字段落盘通信丢失时
BATTERY_CONFIG_TAB_Tt_config_data变化时 save_job_post(BATTERY_CONFIG_PAGE) 写 Flash保留(是配置,不是实时值)
BATTERY_EXTEND_CONFIG_TAB_Tt_extend_config_data变化时 save_job_post(BATTERY_EXTEND_CONFIG_PAGE)保留
BMS_RUN_TABLE_Tt_run_info不落盘bms_lost_handle() 整体 memset 清零(仅保留 u8_type)
BMS_STATIC_TABLE_Tt_static_data不落盘刻意保留:加热过程状态、加热故障恢复次数、预存的加热请求等,避免断通信后重复进入加热流程

BMS_STATIC_TABLE_T 头部的注释「断电不用保存,断通信又要保持的数据」正是这一层设计的意图说明。t_run_info 与 t_static_data 之间的同步由 handle_bat_heat_prestore_info()(bms.c:4094)在每帧 BMS 数据到达时完成,而不是周期性地无条件拷贝——只有在 bat_bat_connet_check() == 0(在线且未丢失)时才刷新,防止把已失效的旧值覆盖到静态区。

4.3 位域布局与「最大 64 个 bit」约束

BMS_FAULT_U、BMS_PROTECTION_U、BMS_WARN_U 都是 64 位,注释明确写着「最多 64 个 bit」。位域以 u8 xxx:1 逐位声明,在 #pragma pack(1) 下按声明顺序从字节 0 的 bit0 开始排布。这意味着:

4.4 电池产品号 → 平台/容量/DoD/型号 的映射关系

bms.h 只定义常量,映射逻辑在 bms.c 里,但它们构成了本模块的核心数据契约:

因为映射用 switch 硬编码,新增产品号必须同时改这 5 处,否则会落到 default 分支——handle_battery_cell_capacity()、handle_battery_dod()、handle_bat_chg_cut_rate_volt()、handle_bat_dischg_cut_rate_volt() 的 default 都是「自赋值」(x = x),等于保持上一次的值不变,静默失效。

4.5 CAN_SEND_QUEUE_T 队列深度与 BATTERY_MAX_NUM 的边界约定

4.6 与 uCOS-II 的配合

bms.h 不涉及 RTOS 原语,但它声明的 task_bms 是 user/main.c:200 创建的静态任务,优先级 TASK_BMS_PRIO = 11(UCOSII/uCOS-CONFIG/app_cfg.h:62,注释「任务间隔 100ms」),栈 TASK_BMS_STK_SIZE = 256(app_cfg.h:89,单位 OS_STK)。任务内部主循环末尾 OSTimeDlyHMSM(0, 0, 0, 100) 即 100ms 周期。所有 bms_read_* / bms_get_* 接口都是无锁直接读全局结构体,因此跨任务读取看到的是「最近一次 task_bms 更新后的快照」,不存在读写原子性保护。

5. 对外接口

5.1 本文件导出的内容

导出项类型使用者
g_t_bat_info全局变量几乎所有模块,跨模块直接读写(extern 声明在 bms.h:1151)
g_t_bat_set_sn_info[6]全局变量net/server.c:1632-1639(云平台下发并机 SN 改写任务)
g_t_can_send_queue全局变量net/server.c:7193-7196(自定义 CAN 帧队列状态查询)
bms_read_* / bms_get_* / bms_set_* 约 80 个函数函数见第 3 节;主要消费者为 net/ems.c、net/server.c、midware/interface/modbus/、midware/inverter/pvcharger.c、logic/logic.c、hmi/ui/
全部枚举/结构体/宏类型配置保存(data/system_config/、data/resume_data/flash/flash_data_store.c)、故障日志(data/fault_warn_log/)、HMI 显示

5.2 本文件依赖的外部内容

依赖来源用途
includes.hUCOSII/uCOS-CONFIG/includes.hu8/u16/u32/u64/s8/s16/s32、TRUE/FALSE、uCOS-II 类型
debug.hmidware/debug/debug.hSTATIC_ASSERT 宏、ASSERT_FLASH_SECTOR_SIZE
g_t_bat_info 的存储地址宏hardware/sdram/sdram.h仅 bms.c 使用,bms.h 不引用

6. 依赖关系

依赖(本文件 include / 使用)

被依赖(哪些文件 include bms.h 或声明 g_t_bat_info)

7. 备注与风险点

  1. bms_get_store_sn(index) / bms_get_platform(id) 无边界检查(bms.c:3178、bms.c:3162)。前者直接取 battery_basic_info[index],后者直接取 battery_basic_info[id].u8_single_platform_type,id 若 ≥ 18 会越界读 SDRAM 中的相邻字段。调用方(net/ems.c)目前传入的是受控索引,但接口本身没有防护,属隐患。
  1. BMS_RUN_TABLE_T 与 5 组位域数组的长度约定不统一。故障/保护/扩展保护 1/2/告警数组长度是 BATTERY_MAX_NUM + 1(13),但 u16_single_soc、u8_single_soh、u16_single_cell_volt_sample[BATTERY_MAX_NUM][32] 等是 12。读写函数中 bms_read_protection_code() 手工或了 0~12,而 bms_read_single_soh(index) 之类完全不做检查。新增代码时若按 BATTERY_MAX_NUM+1 循环遍历单台数组,会越界一格。
  1. bms_read_single_max_capacity / bms_read_fault_code_by_id / bms_is_*_valid 做了 index < BATTERY_MAX_NUM 检查,而同类的 bms_read_single_soc / bms_read_single_cur / bms_read_single_soh / bms_read_battery_cell_dod / bms_read_battery_MIX_capacity 没有。同一份头文件里两种风格并存,调用方不能依赖统一的行为。
  1. BMS_SELF_LOCK_FAULT_U 的位视图与字视图语义重叠。bit.bit0..bit6 被声明但从未命名赋值,word.u16_word1 的高字节对应 bit.self_lock_enable_flag;word.u16_word4 被解释为「自锁故障类型」,同一 64 位空间中 BYTE6/BYTE7 又复用了 u8_mos_temperature_sensor_error、u8_cell_low_voltage 等含义明确的位名。这类叠加语义没有注释说明解包规则,属于典型的版本演进遗留。
  1. BATTERY_STATUS_E 的枚举值跳跃(0、1、256、257、512、513)。这是刻意让「高字节=充电权限、次高字节=放电权限」,BATTERY_STATUS_MAX 因此等于 514 而非 6,若有人拿它当数组长度会分配出无意义的大数组。
  1. ALPHA_BAT_HEAT_MAX_VOLTAGE_ERR_RANGE 是「每台」的误差量。bms.c:1783 使用时写成 ALPHA_BAT_HEAT_MAX_VOLTAGE_ERR_RANGE * u8_num,即误差阈值随电池台数线性放大。台数越多,判定越宽松,极端情况下(12 台)阈值达到 1200(对应 12V),可能漏判真实加热电压异常。
  1. u16_soc_display_minimum / u16_soc_display_maximum 声明为 s16(bms.h:932-935),字段前缀 u16 与类型 s16 不一致,虽然赋值语义是 0~1000 无符号区间,不会实际产生负值,但命名容易误导。
  1. bms.h 中大量函数原型未声明。bms.h 只导出了第 3 节列出的接口,但 bms.c 里还有约 20 个非 static 全局函数(handle_bat_status_flag、handle_bat_chg_cut_rate_volt、handle_battery_model、bat_mos_control、force_bat_shutdown_handle、bat_heat_handle 等)没有在头文件中声明。经全工程搜索,这些函数目前只被 bms.c 内部调用,因此不会编译报错;但它们缺少声明意味着编译器不会对潜在的隐式声明/签名不匹配告警,也让「模块私有的处理函数」与「真正的对外接口」在代码上无法区分。

暂无其它可疑写法。