bms.h
bms.h:20-59)2.2 枚举类型2.3 位域联合体(电池状态码)2.4 结构体2.5 编译期断言3. 函数清单4. 核心逻辑解析4.1 内存布局:SDRAM 绝对定位 + 1 字节打包4.2 三类数据的生命周期划分4.3 位域布局与「最大 64 个 bit」约束4.4 电池产品号 → 平台/容量/DoD/型号 的映射关系4.5 CAN_SEND_QUEUE_T 队列深度与 BATTERY_MAX_NUM 的边界约定4.6 与 uCOS-II 的配合5. 对外接口5.1 本文件导出的内容5.2 本文件依赖的外部内容6. 依赖关系7. 备注与风险点源文件路径:
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)保证所有字段无填充,这有两个直接后果:
BATTERY_CONFIG_TAB_T与BATTERY_EXTEND_CONFIG_TAB_T可以按固定字节偏移整块写入 Flash 扇区,STATIC_ASSERT进一步确认尺寸整除扇区;- 联合体的
byteData[8]与 64 个位域严格重叠,CAN 帧按字节写入即可用位名读取,不需要手工移位。
4.2 三类数据的生命周期划分
| 容器 | 字段 | 落盘 | 通信丢失时 |
|---|---|---|---|
BATTERY_CONFIG_TAB_T | t_config_data | 变化时 save_job_post(BATTERY_CONFIG_PAGE) 写 Flash | 保留(是配置,不是实时值) |
BATTERY_EXTEND_CONFIG_TAB_T | t_extend_config_data | 变化时 save_job_post(BATTERY_EXTEND_CONFIG_PAGE) | 保留 |
BMS_RUN_TABLE_T | t_run_info | 不落盘 | bms_lost_handle() 整体 memset 清零(仅保留 u8_type) |
BMS_STATIC_TABLE_T | t_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 开始排布。这意味着:
- 新增故障位只能追加到已使用字节之后,或者填进已有的
bitNN占位符(如bit21~bit23),不能插到中间,否则所有已发布固件与云平台协议的解释都会错位; BMS_SELF_LOCK_FAULT_U额外提供了word.u16_word1..word4的字视图,word.u16_word4被bat_self_lock_handle()当作「自锁故障类型」使用,而bit.self_lock_enable_flag(bit7,即word.u16_word1的高字节首位)是自锁使能的同步标志位。两种视图叠在同一个 64 位空间里,是这份头文件里最容易误用的一处。
4.4 电池产品号 → 平台/容量/DoD/型号 的映射关系
bms.h 只定义常量,映射逻辑在 bms.c 里,但它们构成了本模块的核心数据契约:
bms_get_store_type()返回t_config_data.u8_type,是所有映射的输入;handle_battery_model()把产品号翻译成s_type_splice[31]型号字符串(OEM 号翻译成客户专用字符串);handle_battery_cell_capacity()把产品号翻译成u16_cell_rate_capacity(0.1Ah 单位,直接写成154*32、96*105这类算式);handle_battery_dod()把产品号翻译成u8_dod(80/90/95/96/100);get_bms_hardware_platform()把产品号翻译成BMS_48V/BMS_HV,default分支用u16_cell_rate_volt > 6000(即 > 60V)反推平台;bms_read_hard_version()只对ALPHA_SMILE_G3_BAT_7_6P_ID返回V1.00,其余返回V1.02。
因为映射用 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 的边界约定
CAN_SEND_QUEUE_T.t_frames[6]:单次最多下发 6 帧自定义 CAN 报文,can_send_queue_add()用u8_count >= 6做满判;u8_a_cluster_id[6]/u8_b_cluster_id[6]:每簇最多 6 台电池,读取接口用index >= 6挡越界;BATTERY_MAX_NUM= 12:单系统最多 12 台电池,但注意t_run_info里 5 组位域数组的长度是BATTERY_MAX_NUM + 1= 13(多出的一格用于「汇总/全部」),而u_bms_self_info[BATTERY_MAX_NUM]、u16_single_soc[BATTERY_MAX_NUM]等是 12。bms_read_protection_code()等合并函数手工或运算了 0~12 共 13 个元素。BATTERY_EXTEND_CONFIG_TAB_T.battery_basic_info[18]:扩展配置区预留 18 格,比运行区的 12 格多,是为将来扩容留的余量;bms_get_store_sn(index)与bms_get_platform(id)不做 18/12 的边界检查,直接下标访问。
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.h | UCOSII/uCOS-CONFIG/includes.h | u8/u16/u32/u64/s8/s16/s32、TRUE/FALSE、uCOS-II 类型 |
debug.h | midware/debug/debug.h | STATIC_ASSERT 宏、ASSERT_FLASH_SECTOR_SIZE |
g_t_bat_info 的存储地址宏 | hardware/sdram/sdram.h | 仅 bms.c 使用,bms.h 不引用 |
6. 依赖关系
依赖(本文件 include / 使用)
UCOSII/uCOS-CONFIG/includes.hmidware/debug/debug.h
被依赖(哪些文件 include bms.h 或声明 g_t_bat_info)
- 本模块:
midware/bms/bms.c、midware/bms/alpha/battery_comm.c、midware/bms/alpha/battery_upgrade.c - 数据层:
data/data.c、data/fault_warn_log/fault_warn_log.h/.c、data/system_config/system_config.c、data/resume_data/flash/flash_data_store.c - 逻辑层:
logic/logic.c、logic/dispatch.c、logic/dc_control.c、logic/self_test.c - 网络层:
net/ems.c、net/server.c - HMI:
hmi/key.c、hmi/led.c、hmi/led/app_led.c、hmi/ui/ui_main.c、hmi/ui/ui_status_bat.c、hmi/ui/ui_status_comm.c、hmi/ui/ui_Information.c、hmi/ui/ui_setting_user_func_battery.c、hmi/ui/ui_setting_admin_debug_battery.c、hmi/ui/ui_setting_admin_debug_power.c - 中间件:
midware/interface/modbus/modbus.c、midware/interface/modbus/sunspec_business.c、midware/interface/modbus/sunspec_modbus.c、midware/interface/interface.c、midware/interface/dry_node/dry_node.c、midware/inverter/inverter.c、midware/inverter/pvcharger.c、midware/inverter/parallel.c、midware/inverter/alphaess/、midware/inverter/goodwe/、midware/inverter/ginlong/、midware/inverter/kelong/、midware/inverter/inovance/、midware/inverter/set/、midware/meter/backupbox.c、midware/auxiliary/system_aux.c
7. 备注与风险点
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)目前传入的是受控索引,但接口本身没有防护,属隐患。
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循环遍历单台数组,会越界一格。
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没有。同一份头文件里两种风格并存,调用方不能依赖统一的行为。
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等含义明确的位名。这类叠加语义没有注释说明解包规则,属于典型的版本演进遗留。
BATTERY_STATUS_E的枚举值跳跃(0、1、256、257、512、513)。这是刻意让「高字节=充电权限、次高字节=放电权限」,BATTERY_STATUS_MAX因此等于 514 而非 6,若有人拿它当数组长度会分配出无意义的大数组。
ALPHA_BAT_HEAT_MAX_VOLTAGE_ERR_RANGE是「每台」的误差量。bms.c:1783使用时写成ALPHA_BAT_HEAT_MAX_VOLTAGE_ERR_RANGE * u8_num,即误差阈值随电池台数线性放大。台数越多,判定越宽松,极端情况下(12 台)阈值达到 1200(对应 12V),可能漏判真实加热电压异常。
u16_soc_display_minimum/u16_soc_display_maximum声明为s16(bms.h:932-935),字段前缀u16与类型s16不一致,虽然赋值语义是 0~1000 无符号区间,不会实际产生负值,但命名容易误导。
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内部调用,因此不会编译报错;但它们缺少声明意味着编译器不会对潜在的隐式声明/签名不匹配告警,也让「模块私有的处理函数」与「真正的对外接口」在代码上无法区分。
暂无其它可疑写法。