Horizontal_45KW_LXN06 项目修改复盘

基于 S32K144 热管理控制器源码,梳理硬件适配、双路 RS485、寄存器映射、水泵手动调速及联调方法。

这个项目是在 DFXN01 基础上适配的 45 kW 液冷热管理控制器。修改涉及传感器和 IO 映射、补液泵、变频器通信、故障处理,以及 BMS 与 HMI 的控制权切换。

复盘时最需要回答的是:外部写入的一个寄存器,经过哪些变量和条件,最终变成了执行器指令?设备返回的数据,又是怎样映射回上位机的?

本文以 index_01_Horizontal_45KW_LXN06/45KW/script/S32K144_TMS/H45KW 中的现有源码为依据,并参考项目根目录的《软件修改项.md》和《版本说明.txt》。历史记录用于说明需求背景;与当前源码有差异的地方单独标明。以下为静态分析和联调建议,尚未通过实机测试验证。

1. 项目结构与修改边界

index_01_Horizontal_45KW_LXN06/
├─ 45KW/
│  ├─ models/                       TMS_SLM.slx、TMS_DD.sldd
│  ├─ libraries/                    模型库
│  ├─ script/
│  │  ├─ CodeGenerate.m             生成代码、编译、整理发布物
│  │  └─ S32K144_TMS/H45KW/
│  │     ├─ Sources/main.c          初始化和主循环
│  │     ├─ Sources/APP/            Simulink 生成的算法代码
│  │     ├─ Sources/BSW/            调度、IO、Modbus、CAN、HMI
│  │     ├─ Sources/CCP/            CCP 标定相关代码
│  │     ├─ Generated_Code/         Processor Expert 外设配置
│  │     ├─ driver/、app/、SDK/      驱动、诊断和基础支持
│  │     └─ Debug/                  工程编译输出
│  ├─ work/                         模型代码生成中间文件
│  ├─ release/                      bin、elf、map、a2l 等发布物
│  └─ backup/                       发布归档
├─ HMI/                             屏端工程资料
├─ 配置文件/                        Modbus 调试配置
└─ docs/                            电气图、协议及器件资料
修改内容优先检查的位置
传感器接线、输入路由、执行器输出Sources/BSW/APP_IO.c、BSW_interface.c、Generated_Code/pin_mux.c
BMS 侧寄存器、Modbus 从机应答Sources/BSW/cus_modbus.c/.h
内部设备轮询及寄存器映射Sources/BSW/cus_modbus_CAN.c/.h
BMS/HMI 控制权交接Sources/BSW/hmi.c/.h、Sources/main.c
制冷、制热、状态机和故障算法models/ 及其生成的 Sources/APP/
任务周期和超时计数Sources/BSW/BSW_Task.c、Interrupt_Event.c

Sources/APP/ 是代码生成目录。CodeGenerate.m 会先删除其中的文件,再复制模型生成的 C/H 文件,因此直接修改这里的算法代码,下一次生成时会被覆盖。算法变化应同步回模型;硬件和通信适配则先从 BSW 层定位。

2. 启动流程与数据链路

初始化的主要顺序如下:

TMS_SLM_initialize()
→ 时钟、缓存、电源、内存和 GPIO
→ 看门狗、CAN、定时器和队列
→ BSW_Init():ADC、PWM、LPIT、两路 UART 等
→ APP_Initial():默认交由 BMS 控制
→ eMB_Init():BMS 侧 Modbus 从机
→ eMB_main_Init():内部设备 Modbus 主机
→ 主循环

主循环持续执行 BSW_Schedule() 和 MB_Master_Poll()。BMS 侧的 eMBPoll() 是否运行,取决于当前控制权,见后文。

周期或入口当前主要工作
每次调度的 BSW_Task0ms()CAN 接收及 CCP 后台处理
1 ms 就绪分支通信超时递减、Modbus 延时处理、g_HVWait 递减、排气计时
10 ms 任务PIN_INPUT_SCAN → Read_ADValue → Inputs → TMS_SLM_step → Outputs
100 ms 任务CAN_Rx_Tx()、MB_Master_main()、Save_Data() 等
主循环的诊断时基CAN TP 周期处理,以及 10 ms 分支中的喂狗和 UDS 处理

LPIT 中断通过 BSW_TaskTimer() 设置就绪标志,具体任务在主循环中执行。源码注释中有“在 1 ms 中断中递减”的说法,但 MB_Delay100ms_Tick() 当前实际在 BSW_Schedule() 的 1 ms 就绪分支中调用。分析时需要跟到调用位置。

BMS/上位机写入
    ↓
cus_modbus.c:解析报文、检查地址权限、写入寄存器变量
    ↓
APP_GetInfoFromBMS():转换模式、温度、高压和水泵目标
    ↓
TMS_SLM_step() 与 Outputs():算法计算及输出适配
    ↓
内部 Modbus / GPIO / PWM → 执行器
    ↓
反馈变量 → APP_SetInfoToBMS() → 上位机读取

需要结合任务顺序理解这张图:当前 APP_GetInfoFromBMS() 位于 Outputs(),在本周期 TMS_SLM_step() 之后执行。新命令对模型计算的影响通常要到后续周期体现,不能把协议写应答等同于执行器已经动作。

3. 从 DFXN01 到 45KW 的硬件适配

早期《软件修改项.md》记录了新增补液泵控制、进水压力和环境温度输入,以及压力、温度传感器更换。接手时需要对照“电气图 → 外设配置 → Inputs() 路由 → 模型变量”整条链路检查。

当前 Inputs() 中可直接确认的映射包括:

算法输入当前来源核对重点
Sens_ADOutWaterPrsADC1_SE1_PTA3已不同于早期配置注释中的 PTC6
Sens_ADOutWaterTempADC1_SE4_PTC6已不同于早期配置注释中的 PTA3
Sens_ADInWateTempADC1_SE3_PTD3当前与进水压力的早期映射发生互换
Sens_ADInWaterPrsADC1_SE0_PTA2以现板接线与实测确认
Sens_ADAmbTempADC1_SE11_PTE6环境温度输入
Sens_ADPlateExchTempADC1_SE10_PTE2当前作为压缩机排气温度输入使用

其他关键 IO:补液泵输出为 PTC9,补液按钮读取 PTC1,液位故障输入取 !GPIO_PTC14,循环水泵强启输入取 !GPIO_PTC11。补液泵和变频循环水泵是两套控制对象,排查时要分清。

历史材料中还记录了冷媒压力传感器和水路传感器的曲线适配。传感器型号相同、协议地址相同,都不足以单独证明可以直接替换;还要核对供电、量程、单位、分压电路、查表数据,以及当前模型参数。原记录里的 Typora 本机图片路径也无法作为可共享的接线依据,应回到项目中的图纸和器件资料。

4. 两路 RS485 的角色与通信时序

4.1 谁是主机,谁是从机

Generated_Code/lpuart1.c 和 lpuart2.c 当前均配置为 9600 bit/s、8 数据位、无校验、1 停止位,即 9600 / 8N1。

接口配置控制器角色对端主要实现
lpuart1Modbus 从机,站号 1外部 BMS;调试时由上位机充当主机cus_modbus.c
lpuart2Modbus 主机压缩机变频器 1、水泵变频器 2、风机 4、HMI 64cus_modbus_CAN.c

这里的编号指生成配置名。cus_modbus_CAN.c 虽然带有 CAN 字样,当前这条设备轮询链路实际调用 LPUART2。与此同时,工程仍初始化和调用 CAN、CCP、UDS 相关逻辑,不能据文件名或旧分析报告推断整机“没有 CAN”。具体 CAN 外设是否接入,需要另行核对硬件。

调试 BMS 侧时,应避免让上位机与 BMS 同时作为该总线的主机;内部设备总线则已经由控制器发起轮询。

4.2 BMS 侧有约 100 ms 的执行前延时

当前从机处理链路为:

收到完整帧 → CRC 和站号检查
→ MB_StartDelay100ms(),g_MBBusyFlag = 1
→ 1 ms 就绪任务递减计数
→ 到期后 g_MBBusyFlag = 2,投递 EV_EXECUTE
→ 执行读写并发送应答
→ 发送完成回调清除忙标志

忙期间收到的新帧会被丢弃。因此上位机应串行处理请求:收到应答或完成超时处理后,再发送下一条。建议联调起步使用 1000 ms 应答超时,再根据报文长度和实测调整;这个数值是调试建议,不是固件配置。

例如连续读取 111 个寄存器,应答长 111 × 2 + 5 = 227 字节。在当前 8N1、9600 bit/s 下,仅应答传输就约需 227 × 10 / 9600 ≈ 236 ms,还没有算请求、帧间隔、执行前延时和调度等待。不能用 100 ms 的上位机超时覆盖这类请求。

外部通信超时计数初值为 30000,由 1 ms 就绪分支递减,名义上约为 30 s。由于采用就绪标志调度,主循环阻塞可能影响实际计时;HMI 接管期间主循环还会主动复位该超时。

5. 寄存器映射:协议地址和 C 变量名分开看

5.1 两段地址空间

水冷配置下,BMS 侧定义了两个地址段:

报文中的地址,十进制数量权限对应 C 变量
1~111111只读Reg1~Reg111
201~302102读写Reg112~Reg213

APP_IO.h 通过宏把第二段转换成协议含义:

#define Reg_201 Reg112
#define Reg_202 Reg113
#define Reg_203 Reg114
#define Reg_218 Reg129

所以 Reg_218 是报文地址 218 对应的控制项,实际存储变量是 Reg129。不要根据变量尾号直接填协议地址。

这里记录的是固件实际比较的报文地址:读取第一项时地址字段就是 0x0001,201 对应 0x00C9。调试工具若采用 4xxxx 编号或自动做一基/零基换算,需要确认最终发出的字节。

从机支持 0x03、0x04 读,0x06 单写和 0x10 多写。当前 0x03 与 0x04 读取同一套映射缓冲区;只读段拒绝写入。请求必须完整落在一个地址段内,不能跨越 111 与 201 之间的空洞。

5.2 常用读取项

地址当前含义解析说明
1循环水泵实际转速百分比按 Pump_nMotoSpd × 100 / 6000 计算,并限制到 100
2~5两台压缩机、电加热、冷凝风扇状态按当前赋值条件解析
6、7、10出水、回水、环境温度int16_t 原始值除以 10;回水温度另有补偿逻辑
8、9出水、回水压力来自过滤后的水压变量;代码注释为绝压,单位应结合模型确认
11、12补液输出状态、机组高压状态分别取 GPIO_PTC9、STM_flgHVState
21外部 RS485 通信正常标志comm_fault_485 == 0 时为 1
31~38故障位图区域按 tms_process_error_code() 的逐位赋值解释
41打包的故障等级及故障码(OBD_stFaltLvl << 6) + (OBD_stErrCodeNow & 0x3F);BMS 高压状态关闭时为 0
42~45冷媒高压、冷媒低压、压缩机温度、实际转速各项比例需分别核对,不能套用统一温度或压力比例
47、48工作模式、系统状态来自 STM_stWorkMode、STM_stSatus
49排气温度原始值按有符号 16 位解析后除以 10
50~55、56六路风机反馈转速、风机故障字顺序对应 FAN_nSpd0~FAN_nSpd5
57、60~65压缩机目标转速、六路风机目标转速目标与实际反馈分开展示
67g_HVWait 剩余计数按名义 1 ms 时基递减
95、96、97水泵下发值、设备返回设定值、设备返回运行值分别为 mc_fr_set2、mc_fr_set_ro2、mc_fr_run2 原始值
98、99最终选用的泵指令百分比、自动算法泵指令百分比用于判断手动是否真正被选中
110、111软件、硬件版本寄存器当前 APP_IO.c 中均定义为 1

例如温度原始值 0xFF9C 按 int16_t 解释为 -100,再除以 10 得到 -10.0 ℃。直接按无符号整数显示会得到错误结果。

5.3 常用写入项

地址当前功能值与限制
201工作模式0 待机、1 制冷、2 制热、3 自循环、4 排气;其他值转为待机
202高压请求0 请求关闭、1 请求开启;BMS 侧关闭时有停泵流程
203手动水泵目标百分比0~100;大于 100 时手动目标按 0 处理
206制冷设定温度原始值限制在 50~350,再除以 10,即 5.0~35.0 ℃
207制热设定温度同上
216压缩机目标转速覆盖值非 0 且非 INVALID_DATA 时在 Outputs() 中覆盖目标
217风机目标覆盖值非 0 且非 INVALID_DATA 时覆盖 TMS_dcycFan1Rmp
218循环水泵控制模式0 自动、1 手动;其他值在输出选择中恢复为自动

204、205、208~215 等地址虽然处于可读写区,但当前部分业务赋值已被注释。能写入、能读回,只能证明寄存器存储成功,不能证明功能已经接入控制链路。

6. 水泵手动调速:目标、模式、输出与反馈

6.1 为什么只写 203 不够

当前实现保留自动算法 TMS_dcycPumpRmp,另用 Reg_203 保存手动目标、Reg_218 选择模式。最终由 APP_SetInfoToCompressor_slave() 选出 pump_output_duty。

203:用户希望的手动百分比
218:是否选择手动
99 :原自动算法百分比
98 :经过输出选择后的百分比
95 → 96 → 97 → 1:下发原始值 → 返回设定 → 返回运行 → 实际转速百分比

上电初始化时,203 和 218 都置为 0,保持默认自动模式。排查“写了 50%,水泵没变化”时,先检查 218,再看 98 和后续反馈,而不是重复写 203。

6.2 输出选择仍受条件约束

手动模式下,代码先把选用指令设为 0,只有同时满足以下条件才采用手动目标:

  • Reg_202 == 1,BMS 高压状态为 1,且高压请求变量为 0;
  • TMS_flgHVState 有效,系统状态在 [10, 50);
  • 故障等级为 0 或 2,水泵通信丢失标志未置位;
  • 手动目标不大于 100。

此外,原有强制启泵及其预充流程优先于手动,会清除手动模式。外部通信故障或 HMI 接管后,手动目标和模式也会清零,避免继续沿用旧指令。非法目标在手动分支中产生 0 指令,但仍需区分强启、自动回退等其他分支。

这里的 Pump_flgCANLos 虽然名称带 CAN,当前内部 Modbus 轮询会更新它;变量命名不能代替对实际赋值来源的追踪。

6.3 下发比例与实际转速分开核对

现有代码沿用以下换算:

mc_fr_set2 = duty * 100 / 6.5 * 6;
Pump_nMotoSpd = (float)mc_fr_run2 * 60.0F / (100.0F * 4.0F);

前者是选用百分比到设备下发原始值的映射,后者是运行反馈到 rpm 的映射。它们是当前项目实现,不能直接推广为其他水泵的通用公式;下发与反馈的单位、比例及设备参数仍需通过变频器资料和实测闭环确认。

6.4 BMS 侧关高压的实际判据

写 202 为 0 后,代码退出手动、清除手动目标并将工作模式设为待机。只有 TMS_dcycPumpRmp 与 pump_output_duty 都为 0,才撤销内部高压状态和请求;关高压期间还有泵指令只减不增的限制。

这段代码检查的是自动指令和选用指令为 0,没有直接等待水泵实际反馈转速归零。是否需要基于实测转速或额外超时完成停机,应结合设备要求确认。该流程也不能直接套用到 HMI 下电路径,因为 APP_HMI_control_tms() 对高压变量采用了另一套赋值逻辑。

7. HMI 接管为什么会影响上位机通信

默认控制权为 BMS。HMI 位于内部 Modbus 总线,控制器主动轮询屏端寄存器,而不是由屏端向 BMS 侧站号 1 发送相同命令。

屏端地址当前用途
0x1040 起 30 项控制器向 HMI 下发机组信息
0x105E控制器读取 HMI 的控制申请或释放值
0x105F 起 4 项控制器向 HMI 下发当前 BMS 控制参数
0x1063 起 4 项控制器读取 HMI 用户设置
0x1067控制器向 HMI 写入交接应答

当前启用分支收到 0xC05A 后准备参数、置应答 0x0CA5,进入下一状态后便切换为 HMI 控制。等待 0xC055 的判断已被注释,因此不能按旧握手图描述为“必须收到第二次确认才接管”。收到 0xC0A5 后释放控制权,并设置应答 0x5555。

主循环中的关键条件如下:

if (machineStat == MACHINE_STAT_CONTROLLED_BY_BMS) {
    eMBPoll();
} else {
    MBResetTimerTimeOut();
    Modbus_clear();
}

因此,HMI 接管后,BMS 侧 Modbus 事件处理暂停,上位机可能收不到应答。这种现象首先应与控制权状态对照分析,不能仅凭超时认定串口断线。

另一个需要核对的地方是 APP_SetInfoToHMI():它仍将 Reg12 当作故障码、Reg51 当作版本号,而当前 BMS 映射中二者分别是机组高压状态和风机反馈转速。部分旧寄存器引用也与现行 BMS 映射不同。屏端显示含义需要与当前结构体、赋值来源逐项核对。

8. 补液与排气:区分历史需求和当前实现

8.1 补液泵

早期修改记录描述的是“进水压力低于 150 kPa 启动、高于 220 kPa 停止,并增加启动确认和故障码”。当前 LiquidPump_Control() 的实际行为已有变化:

  • 使用过滤后的出水压力,低于 180 启动、达到 250 停止;
  • PTC1 低电平表示按钮按下,按钮可直接开补液泵;
  • 液位故障 OBD_flgLiqLvlDeb 有效时先关闭补液泵并返回;
  • 当前启用状态机只有 LP_IDLE、LP_RUNNING,没有执行早期记录中的启动确认和 LP_FAULT 分支。

因此不能把旧文档中的“延时 1 s 判断启动成功、上报故障码 50”写成当前已实现功能。压力单位和阈值应与模型及传感器标定一起验证。

8.2 排气模式

当前模式 4 的代码意图是:循环水泵按 50% 指令运行 2 min,停止 1 min,共计 30 次,然后回到待机,并通过 exhaust_done 阻止 BMS 持续写 4 导致重复触发。BMS 切换到其他模式后解除封锁。按设定时长计算,一轮完整流程为 90 min。

这部分有两个调用顺序问题需要实测:ExhaustMode_Tick() 根据 Reg_201 == 4 计时,输出分支却根据 BMS_stModeReq == 4 执行;同时,排气分支修改 TMS_dcycPumpRmp 的位置晚于本周期水泵指令选择,下一周期又会先运行模型。应抓取相位、计时器、算法目标、98 和 95 的变化,确认排气目标最终确实下发,不能只观察变量被赋值。

9. 几个容易影响联调结论的细节

温度上报存在补偿,而且读操作会进入计算函数

APP_IO.c 当前 REAL_TEMP 为 0。在制冷且压缩机转速大于 4000 时,回水温度上报会叠加随计数变化的补偿,补偿常量为 0.9 ℃。

APP_SetInfoToBMS() 不仅在 Outputs() 中调用,外部读取经 APP_LUART_ReadReg() 也会调用它。补偿计数位于该函数内,因此不能只按注释中的固定 10 ms 周期推算变化速度;增加读取频率也可能影响上报补偿。验证真实温差时,应同时记录滤波温度和对外寄存器值。

版本标识不止一处

main.c 中有 APP_VERSION = V0.1、ver_soft = CXS02.1001.240524、ver_soft_hex = 0x1001 和 ver_hard = V15B;APP_IO.c 中上报的软硬件版本寄存器又均为 1。这些标识不能直接当成同一个发布版本,应与 bin/elf、编译时间及发布归档一起确认。

保留的覆盖入口可能改变算法结果

216、217 会在 Outputs() 中覆盖压缩机和风机目标。排查算法输出与实际下发不一致时,应读取这两个寄存器,并确认是否有旧调试值残留。

异常路径也要覆盖忙状态释放

正常路径在发送完成回调中清除 g_MBBusyFlag。广播路径不发送应答,发送失败也可能没有正常完成回调,因此应专门验证这些情况下状态是否能够恢复。初次联调建议使用站号 1 的单播请求,确认正常链路后再测试异常路径。

10. 联调步骤与验证记录

10.1 先验证只读链路

  1. 确认烧录的固件来自当前 H45KW 工程,记录 bin/elf 和编译信息。
  2. 确认使用 BMS 侧 RS485、参数 9600 / 8N1、站号 1,并确认控制权在 BMS。
  3. 从地址 1 开始读取少量寄存器,抓取原始收发字节、CRC、响应时间和解析值。
  4. 分别读取 95~99 与 201~218;不要跨地址空洞,也不要连续并发请求。
  5. 核对负温度、无效值和目标/反馈的显示,再进行控制项测试。

例如读取地址 1 起的 12 个寄存器,请求中 CRC 之前的字节为:

01 03 00 01 00 0C
│  │  └─地址1─┘ └─数量12─┘
│  └─读保持寄存器
└─站号1

完整 RTU 帧还需追加 CRC16。寄存器地址和数值按高字节在前,当前固件 CRC 按低字节在前发送。读到 0x7FFF 时,还需结合初始化和该字段是否实际更新来判断,不能直接作为有效测量值显示。

10.2 水泵和控制权验证表

以下为待执行用例,不代表已经通过测试。

场景操作与观察重点
上电默认203、218 应为 0;记录自动目标 99 和选用目标 98
仅写手动目标218 保持 0,写 203;确认自动输出未被该目标直接覆盖
手动调速在输出条件满足时,先设置 203,再选 218=1;跟踪 98、95~97、1
手动零目标203=0、218=1;核对选用指令与实际反馈的下降过程
非法输入验证 203>100、218 非法值、201 非法模式的处理
保护与强启分别触发水泵通信故障、相关故障等级和强启条件,检查优先级
BMS 下电写 202=0,观察退出手动、指令归零、高压输出和实际停转的先后关系
外部通信中断持续到超时判定,确认手动清零及后续自动流程;不要预设为立即停泵
HMI 接管和释放检查手动清零、BMS 侧应答变化,以及释放后通信恢复情况
排气与补液核对压力阈值、按钮和故障优先级,并记录排气阶段实际下发值

建议每条记录至少包含:时间、固件标识、控制权、收发帧、模式、系统状态、故障等级、203/218、98/99、95~97、实际转速和压力。这样才能区分“写入成功”“输出被选中”“设备接受”和“机械动作完成”。

11. 历史版本记录与后续维护

根目录《版本说明.txt》保留了以下简要记录,未提供逐项验证结果和对应提交:

版本原记录中的修改方向
0.1基础版本
0.2添加补液
0.3高压下压缩机调整
0.4低温策略调整
0.5未上电时屏蔽通信故障
0.6外部 485 通信修改
0.7高压继电器刚开启时的设备超时故障处理
0.8完善设备故障处理
0.9工作中直接断开高压的相关处理
1.0制冷回差修改

这些是历史变更摘要。尤其是下电和故障策略,应与当前源码逐项对照,不能只按旧版本描述推断行为;水泵手动调速等当前实现也不据此自行编造新版本号。

后续每次修改,建议同时记录四件事:需求和触发条件、修改的模型或源文件、外部可观察到的行为、验证记录及固件归档。项目协议、电气图、屏端映射和上位机显示也应随代码一起更新,避免同一地址在不同材料中被解释成不同含义。

载入内容