1. 前言
谁在决定系统什么时候算初始化完成? 谁在决定什么时候开始预充? 谁在发现错误后决定延时断开还是立刻断开?
SYS 状态机:负责 ECU 级别的启动、测量首轮闭环、各功能模块初始化联动。 BMS 状态机:负责电池系统级业务状态,包括待机、预充、运行、开断接触器和错误退出。

SYS 和 BMS 都在同一条周期控制路径里,但SYS 负责把 BMS 拉出未初始化态。 外部请求和 fatal diagnosis 都不会直接去动接触器,而是分别通过数据库读取和诊断聚合进入 BMS 的决策链。
2. SYS 状态机
2.1 先看状态变量本身
currentState / currentSubstate nextState / nextSubstate previousState / previousSubstate timer stateRequest illegalRequestsCounter initializationTimeout triggerEntry
2.2 顶层状态并不复杂,但每个状态下面的子流程很长
UNINITIALIZED INITIALIZATION PRE_RUNNING RUNNING ERROR
2.3 INITIALIZATION 阶段:先确认系统有没有历史问题
FRAM_ReadData(FRAM_BLOCK_ID_DEEP_DISCHARGE_FLAG);2.4 然后才是 SBC、CAN、RTC、自检和 Boot Message
请求 SBC 初始化并等待它进入 SBC_STATEMACHINE_RUNNING 初始化 CAN 等 RTC 模块准备好 执行启动期 BIST:
SYS_GeneralMacroBist() DATA_ExecuteDataBist()
SBC 初始化失败是直接可导致 SYS 进入 ERROR 的。这说明硬件安全基础设施在系统级启动中优先级极高。 数据库自检在这里完成。这进一步印证了前一篇的结论:Database 不只是工具模块,而是系统级依赖。
3.PRE_RUNNING:系统拉起流程的地方
3.1 先初始化 Interlock,再初始化 Balancing
ILCK_SetStateRequest(ILCK_STATE_INITIALIZATION_REQUEST) BAL_SetStateRequest(BAL_STATE_INIT_REQUEST) 等待 BAL_GetInitializationState() == STD_OK 根据 BS_BALANCING_DEFAULT_INACTIVE 决定全局使能还是全局禁用均衡
3.2 首轮测量是一个真正的系统门槛
MEAS_StartMeasurement();...if (MEAS_IsFirstMeasurementCycleFinished() == true) {ALGO_UnlockInitialization();...}
SYS 不会默认测量模块总能很快给出第一批有效数据。 算法模块初始化是被锁住的,必须等第一轮测量完成才解锁。
3.3 电流传感器
CAN_EnablePeriodic(true) 进入当前传感器存在性检查流程 对每个 string 检查:
CAN_IsCurrentSensorPresent(s) CAN_IsCurrentSensorCcPresent(s) CAN_IsCurrentSensorEcPresent(s)
SE_InitializeSoc(true/false, s) SE_InitializeSoe(true/false, s) SE_InitializeSoh(s)
3.4 最后才请求 BMS 状态机初始化
BMS_SetStateRequest(BMS_STATE_INIT_REQUEST);Interlock ready Balancing ready 第一轮测量完成 电流传感器存在性确认 SOF 初始化完成 IMD 初始化请求成功
3.5 SYS 状态
SYS_FSM_STATE_UNINITIALIZED | SYS_SetStateRequest(SYS_STATE_INITIALIZATION_REQUEST) 合法后由 SYS_Trigger() 消费 | INITIALIZATION | |
SYS_FSM_STATE_INITIALIZATION | UNINITIALIZED | PRE_RUNNING;SBC 超时等情况转入 ERROR | |
SYS_FSM_STATE_PRE_RUNNING | INITIALIZATION | BMS_GetInitializationState() == STD_OKRUNNING;任一初始化超时则转入 ERROR | |
SYS_FSM_STATE_RUNNING | PRE_RUNNING | ERROR | |
SYS_FSM_STATE_ERROR |
SYS_FSM_SUBSTATE_INITIALIZE_INTERLOCK | PRE_RUNNING | ILCK_STATE_INITIALIZATION_REQUEST | |
SYS_FSM_SUBSTATE_START_INITIALIZATION_BALWAIT_INITIALIZATION_BAL | BAL_STATE_INIT_REQUEST 并轮询 BAL_GetInitializationState() | STD_OK | |
SYS_FSM_SUBSTATE_WAIT_INITIALIZATION_BAL_GLOBAL_ENABLE | BS_BALANCING_DEFAULT_INACTIVE 发送全局 disable 或 enable 请求 | ||
SYS_FSM_SUBSTATE_START_FIRST_MEASUREMENT_CYCLEWAIT_FIRST_MEASUREMENT_CYCLE | MEAS_StartMeasurement()MEAS_IsFirstMeasurementCycleFinished() | ALGO_UnlockInitialization(),再进入电流传感器检查或 misc 初始化 | |
SYS_FSM_SUBSTATE_START_CURRENT_SENSOR_PRESENCE_CHECKWAIT_CURRENT_SENSOR_PRESENCE_CHECK | BS_CURRENT_SENSOR_PRESENT == true | CAN_EnablePeriodic(true)SE_InitializeSoc/Soe/Soh | SOF_Init() 并进入 misc 初始化;超时转错误态 |
SYS_FSM_SUBSTATE_INITIALIZATION_MISC | SE_InitializeSoc(false) / SE_InitializeSoe(false) | ||
SYS_FSM_SUBSTATE_INITIALIZATION_IMD | IMD_RequestInitialization() | ||
SYS_FSM_SUBSTATE_START_INITIALIZATION_BMSWAIT_INITIALIZATION_BMS | BMS_STATE_INIT_REQUEST 并轮询 BMS_GetInitializationState() | STD_OKRUNNING |
4. BMS 状态机
4.1 BMS 状态变量里最值得看的辅助状态
prechargeTryCounter powerPath closedStrings[] closedPrechargeContactors[] numberOfClosedStrings firstClosedString stringOpenTimeout stringCloseTimeout nextState restTimer_10ms currentFlowState remainingDelay_ms minimumActiveDelay_ms transitionToErrorState
4.2 外部请求是走数据库
从数据库读取 DATA_BLOCK_STATE_REQUEST 查看 stateRequestViaCan 映射为 BMS_REQ_ID_STANDBY / NORMAL / CHARGE / NOREQ
4.3 从 CAN 请求到预充执行,是这样串起来的

5. 预充流程:源码比先负后正复杂得多
5.1 进入预充前,先决定要从哪一串开始
充电: BMS_GetLowestString(BMS_TAKE_PRECHARGE_INTO_ACCOUNT, &bms_tablePackValues)放电: BMS_GetHighestString(BMS_TAKE_PRECHARGE_INTO_ACCOUNT, &bms_tablePackValues)
充电时先从电压最低的 string 开始更合理。 放电时先从电压最高的 string 开始更合理。
5.2 第一步先合负极
CONT_CloseContactor(firstClosedString, CONT_MINUS)stringCloseTimeout = BMS_STRING_CLOSE_TIMEOUT timer = BMS_WAIT_TIME_AFTER_CLOSING_STRING_CONTACTOR substate = BMS_PRECHARGE_CLOSE_PRECHARGE
5.3 第二步才是闭合预充接触器
CONT_ClosePrecharge(firstClosedString)OscillationTimeout = BMS_OSCILLATION_TIMEOUT closedPrechargeContactors[string] = 1
5.4 真正的预充判据不是等一会儿,而是电压差和电流双判据
cont_prechargeVoltDiff_mV = abs(stringVoltage - highVoltageBusVoltage)current_mA = abs(stringCurrent)
cont_prechargeVoltDiff_mV < BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV current_mA < BMS_PRECHARGE_CURRENT_THRESHOLD_mA
压差太大,说明母线电容还没充起来。 电流太大,说明存在异常浪涌或负载问题。
DIAG_ID_PRECHARGE_ABORT_REASON_VOLTAGE DIAG_ID_PRECHARGE_ABORT_REASON_CURRENT
5.5 预充失败允许有限重试
先尝试打开预充接触器 检查 prechargeTryCounter < (BMS_PRECHARGE_TRIES - 1u) 若还没到上限,则:
清除 closedPrechargeContactors[string]等待 BMS_TIME_WAIT_AFTER_PRECHARGE_FAIL再回到 BMS_PRECHARGE_CLOSE_PRECHARGE
5.6 成功预充后,还要确认正极接触器闭合
CONT_CloseContactor(firstClosedString, CONT_PLUS)5.7 预充关键子状态
BMS_ENTRY | STANDBYNORMAL 或 CHARGE 请求后进入 BMS_STATEMACH_PRECHARGE | firstClosedString;先闭合负极接触器 | BMS_PRECHARGE_CLOSE_PRECHARGE;无可用 string 或命令非法则走开断错误路径 |
BMS_PRECHARGE_CLOSE_PRECHARGE | OscillationTimeout 并闭合预充接触器 | BMS_CHECK_ERROR_FLAGS_CLOSING_PRECHARGE;超时或命令失败则走错误路径 | |
BMS_CHECK_ERROR_FLAGS_CLOSING_PRECHARGE | BMS_CHECK_STATE_REQUESTS;有错误则开断进入错误路径 | ||
BMS_CHECK_STATE_REQUESTS | STANDBY 退回请求 | STANDBY 则转 OPEN_CONTACTORS;否则转 BMS_PRECHARGE_CHECK_VOLTAGES | |
BMS_PRECHARGE_CHECK_VOLTAGES | BMS_CheckPrecharge() 做压差+电流双判据;成功后闭合正极 | BMS_CHECK_CLOSE_SECOND_STRING_CONTACTOR_PRECHARGE_STATE;失败则打开预充接触器,并在未超重试上限时等待后重试,否则进错误路径 | |
BMS_CHECK_CLOSE_SECOND_STRING_CONTACTOR_PRECHARGE_STATE | BMS_CHECK_ERROR_FLAGS_PRECHARGE_CLOSING_STRINGS;超时则走错误路径 | ||
BMS_CHECK_ERROR_FLAGS_PRECHARGE_CLOSING_STRINGS | BMS_PRECHARGE_OPEN_PRECHARGE | ||
BMS_PRECHARGE_OPEN_PRECHARGEBMS_PRECHARGE_CHECK_OPEN_PRECHARGE | BMS_STATEMACH_NORMAL;否则错误退出 |
6. 错误处理:BMS 并不是看到故障就立刻跳ERROR
6.1 BMS 会先扫描所有 fatal error,并选最短延时
DIAG_GetDiagnosisEntryState(...)DIAG_GetDelay(...)
6.2 remainingDelay_ms 让错误切断变成了可控策略
如果已经进入错误过渡态,就根据距离上次调用过去的时间递减 remainingDelay_ms如果新发现了更短延时的 fatal error,就把剩余延时压缩到更短值 只有当 remainingDelay_ms == 0时,才真正返回STD_NOT_OK
有些错误立刻切断 有些错误允许一个很短的受控延时
7. SYS 和 BMS 之间真正的关系
main() 只负责把硬件和调度器拉起来。 SYS 负责把 Interlock、Balancing、首轮测量、传感器存在性检查、IMD、BMS 初始化全部串起来。 BMS 在自己的 10ms 节拍里消费外部请求和诊断结果,决定接触器如何动作。
SYS 是系统级编排者 BMS 是高压业务执行者
小结
SYS 的重点是把系统按正确顺序拉到可运行状态。 BMS 的重点是把接触器控制、预充重试、反馈确认、错误延时这些细节都纳入了状态机。 外部请求和错误都是通过数据库和诊断模块进入状态机。
推荐阅读顺序
先读 SYS_Trigger(),建立 SYS 状态机的顶层入口。再看 SYS_ProcessInitializationState()和SYS_ProcessPreRunningState(),把系统拉起顺序理清楚。接着跳到 BMS_Trigger(),并补读CANRX_BmsStateRequest()与BMS_CheckCanRequests(),把外部请求如何进入 BMS 决策链串起来。然后读 BMS_CheckPrecharge()与BMS_STATEMACH_PRECHARGE分支,把预充执行主链串起来。最后读 BMS_IsBatterySystemStateOkay()、接触器动作函数和配置头文件,看错误延时、执行动作与阈值定义如何一起收口。
夜雨聆风