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

modbus.h

源文件路径:midware/interface/modbus/modbus.h 所属模块:midware/interface/modbus(Modbus 通信接口层) 代码行数:1512

1. 文件职责

本文件是 EMS 主控对外 Modbus 通信的接口与寄存器映射定义头文件,它定义了整个系统的 Modbus 寄存器地址表(REG_MODBUS_E 枚举)、Modbus 功能码、协议错误码、固件升级相关枚举,以及 RTU/TCP 共用的请求结构体和配置存储结构体。它处在数据流的"外部世界 → EMS 内部变量"边界上:RTU(UART3/RS485)与 TCP(W5500 Socket3,端口 502)两条物理通道都复用同一套寄存器号,由 modbus.c 中的读写分派函数把寄存器号翻译成 g_t_logic_info、g_t_ems_info、g_t_bat_info、meter_*、bms_*、inverter_* 等模块的变量。上层(hmi 菜单、net/server.c 云端、sunspec_modbus.c)通过 g_t_modbus_config、g_t_config_save_flag 等导出变量与它交互。它本身不含任何可执行逻辑,只提供类型契约和常量契约。

2. 关键数据结构与宏

名称类型说明
DEBUG_MODBUS宏默认 0,Modbus 模块串口调试打印总开关
ADDR_MODBUS宏默认 Modbus 从站地址 0x55,由 system_config.c:741 做初值
ADDR_SUNSPEC_MODBUS宏Sunspec 协议默认从站地址 0x01
PVCHARGR_BROADCAST_ADDR宏值为 0,PV 充电机(主机角色)广播地址
LEN_RECV_MODBUS宏RTU 收发缓冲区长度 256 字节
FUNC_READ_REGISTER宏功能码 0x03,读保持寄存器
FUNC_WRITE_SINGLE_REGISTER宏功能码 0x06,写单个寄存器
FUNC_WRITE_REGISTER宏功能码 0x10,写多个寄存器
FUNC_QUERRY_UPGRADE_REGISTER宏功能码 0x18,查询升级前置信息(返回 JSON)
FUNC_CHECK_UPGRADE_REGISTER宏功能码 0x19,校验升级文件信息
FUNC_UPDATE_SYSTEM_REGISTER宏功能码 0x20,下发升级系统配置(30 字节 PDU)
FUNC_WRITE_FIRMWARE_CONTENT_REGISTER宏功能码 0x21,写入固件内容分片
FUNC_QUERY_UPGRADE_PROGRESS_REGISTER宏功能码 0x22,查询升级进度百分比
MODBUS_TCP_PDU_ADDR宏值 7,TCP 报文中 PDU(单元标识符)起始下标,全文件硬编码偏移的基准
TCP_PDU_CONFIG_LENGTH宏值 0x1E(30),升级配置 PDU 的固定长度
MD5_MAX_BYTE宏值 16,固件 MD5 原始长度(转 ASCII 后 32 字符)
STRING_ZERO宏字符串 "00000000",用于判定 MD5 是否为全零(即未填)
UPOBJECT / FIRM_VERSION / FACTORY_MODEL宏升级 JSON 校验用的三个键名:"Upgrade object"、"Firmware Version"、"Factory model"
MAX_ONES_PER_BIT宏值 4,同一星期位(周一~周日)最多允许的充/放电时间段数
GENERATE_ENUM(ID, BYTE_FIELD)宏X-Macro 辅助宏,把 ID 与字节域拼成寄存器名 REG_BATTERY_SN{ID}_BYTE_{BYTE_FIELD}_E
BATTERY_SN_REGISTERS(ID, ADDR)宏单个电池 SN 的 16 个寄存器(每寄存器 2 字节,共 32 字节 SN)批量生成;并机系统最多支持 12 个电池(第 13~18 个电池的定义被注释掉)
E_MODBUS_Recv_Meter_State枚举Modbus RTU 接收状态机状态:ADDR_M、FUNC_M、REGISTER_BITS_8_15、REGISTER_BITS_0_7、REGISTER_NUM_8_15、REGISTER_NUM_0_7、LEN_8_15、LEN_0_7、DATA_RECVD、CRC_Bits_8_15、CRC_Bits_0_7、EXCEPTION_E
REG_SUNSPEC_MODBUS_E枚举Sunspec 协议寄存器窗口:REG_SUNSPEC_START = 0x9C40、REG_SUNSPEC_END = 0xA052、REG_MAX_SUNSPEC_MODBUS
REG_MODBUS_E枚举本文件体量最大的定义(第 93~1317 行),包含全部 Modbus 寄存器地址常量,约 1340 个具名量(其中 BATTERY_SN_REGISTERS 宏 12 次调用各展开 16 个)。按地址段分区见 §4.1
REG_MOSBUS_ERR_E枚举内部合法性判定返回码:REG_TREU_E(合法)、REG_ILLEGAL_FUNCTION_E、REG_ILLEGAL_DATA_ADDRESS_E、REG_ILLEGAL_DATA_VALUE_E、REG_SLAVE_DEVICE_FAILURE_E、REG_CONFIRM_E、REG_DEVICE_IS_BUSY_E、REG_STORAGE_PARITY_ERROR_E、REG_UNAVAILABLE_GETEWAY_PATH_E
MODBUS_EX_CODE_E枚举协议层异常码:MODBUS_EX_NONE_E = 0x00 起,含 MODBUS_EX_ILLEGAL_FUNCTION_E、MODBUS_EX_ILLEGAL_DATA_ADDRESS_E、MODBUS_EX_ILLEGAL_DATA_VALUE_E、MODBUS_EX_SLAVE_OR_SERVER_FAILURE_E、MODBUS_EX_ACKNOWLEDGE_E、MODBUS_EX_SLAVE_OR_SERVER_BUSY_E、MODBUS_EX_MEMORY_PARITY_E、MODBUS_EX_GATEWAY_PATH_E、MODBUS_EX_GATEWAY_TARGET_E(标准 Modbus 异常码 0x01~0x0B,缺 0x07/0x08 被注释掉)
UPGRADE_FLAG_E枚举STOP_UPGRADE_E / START_UPGRADE_E,升级启动标志
MODBUS_UPGRADE_OBJECT_E枚举升级目标对象:UPGRADE_OBJECT_NONE_E、UPGRADE_OBJECT_EMS_E、UPGRADE_OBJECT_BMU_E、UPGRADE_OBJECT_LMU_E、UPGRADE_OBJECT_ISO_E、UPGRADE_OBJECT_APP2_E、UPGRADE_OBJECT_INV_MASTER_E、UPGRADE_OBJECT_INV_SLAVE_E、UPGRADE_OBJECT_INV_ARM_E、UPGRADE_OBJECT_BMS_E(枚举值即 TCP 报文中的对象编码,从 1 起)
UPGRADE_CONFIG_ERR_E枚举升级配置校验错误码,共 11 个:CONFIG_NONE_ERR_E、CONFIG_UPGRADE_FLAG_ERR_E、CONGIF_FACTORY_CODE_ERR_E、CONFIG_EMS_HARD_VERSION_ERR_E、CONFIG_BMU_MODEL_ERR_E、CONFIG_LMU_MODEL_ERR_E、CONFIG_ISO_MODEL_ERR_E、CONFIG_UPGRADE_OBJECT_ERR_E、CONGIF_MD5_NULL_ERR_E、CONFIG_FILE_LENGTH_NULL_ERR_E、CONFIG_PDU_LENGTH_ERR_E(注意后 6 个值被用作 check_upgrade_infomation 的返回位图,含义与枚举名不完全对应,见 §4.5)
MODBUS_BAUD_RATE_E枚举BAUD_RATE_9600 = 0、BAUD_RATE_115200、BAUD_RATE_256000
MODBUS_REQ_T结构体#pragma pack(1) 紧凑结构:u8_local_addr、func_code、addr_register_start、num_reg,RTU/TCP 解析结果统一存放于 modbus_rtu_info / modbus_tcp_info.t_reg
MODBUS_TCP_TABLE结构体Modbus TCP 头部 + 寄存器请求:u16_transaction_id、u16_protocol_id、u16_data_len、t_reg(MODBUS_REQ_T)
MODBUS_TCP_UPGRADE_T结构体TCP 升级会话上下文:u8_update_flag、u8_update_object、u8_update_type
CONFIG_SAVE_FLAG_T结构体13 个"配置需落盘"标志位,每类参数一个:u8_set_sys_base_para_flag、u8_set_time_flag、u8_set_ui_config_flag、u8_set_logic_config_flag、u8_set_logic_config_flag2、u8_set_logic_config_flag3、u8_set_meter_config_flag、u8_set_battery_config_flag、u8_set_inverter_config_flag、u8_set_net_para_flag、u8_set_modbus_config_flag、u8_set_ct_config_flag、u8_set_system_custom_info_flag
DISPLAY_LED_LAMP_PANE_CTROL_U联合体u16_all 与位域结构体 bit 的联合,位域含 u8_led_red、u8_led_db2、u8_led_db1、u8_led_db3、u8_led_db0、u8_led_db7、u8_led_db6、u8_led_db5、u8_led_db4、u8_led_blue 及 bit10 ~ bit15(LED 面板控制字,ATE 测试用)
ATE_CTROL_T结构体ATE 测试控制:u8_link_access_status、u8_set_sys_led_flag、led_lamp_pane_ctrol(上者)、u8_set_passthrough_can_test_flag
MODBUS_CONFIG_INFO_T结构体Modbus 配置的 Flash 存储镜像:u16_head、u8_address_modbus、u8_modbus_baud_rate、u8_sunspec_en、u16_sunspec_addr、u16_sunspec_Ver、u8_reserved[117]、u16_crc_code,共 128 字节,配套 STATIC_ASSERT(ASSERT_FLASH_SECTOR_SIZE % sizeof(MODBUS_CONFIG_INFO_T) == 0) 保证扇区整除

3. 函数清单

本文件为纯头文件,只包含函数声明(原型),无函数定义。全部 19 个声明如下:

函数名作用域说明
get_para_from_reg_addr全局(声明)按寄存器地址从系统变量读取 16 位值,供 RTU/TCP 读命令组帧
modbus_send_data全局(声明)清 UART3 接收缓冲后经 UART3(RS485)发送帧
modbus_data_is_recv_async全局(声明)查询 UART3 是否有异步待取字节
modbus_get_data_byte全局(声明)从 UART3 异步缓冲取 1 字节
handle_modbus_ret_recv_data全局(声明)RTU 从站主接收状态机(应答式解析 + 执行 + 回复)
ems_to_modbus_tcp全局(声明)Modbus TCP Socket3 状态机(建立/收包/发送采样曲线/关闭/重开)
set_flag_modbus_force_update全局(声明)设置"Modbus 正在强制升级"标志
get_flag_modbus_force_update全局(声明)读取"Modbus 正在强制升级"标志
is_time_period_overlap全局(声明)判断两个 [start, end] 时间段是否重叠
is_timeperiod_charge_insert全局(声明)判断新充电时间段能否插入(不与已存段冲突)
is_timeperiod_discharge_insert全局(声明)判断新放电时间段能否插入
count_chargebits_inposition全局(声明)统计某星期位已使能的充电时间段总数
count_dischargebits_inposition全局(声明)统计某星期位已使能的放电时间段总数
chargebit_over_check全局(声明)校验加入新段后每天充电段数是否超过 MAX_ONES_PER_BIT
dischargebit_over_check全局(声明)校验加入新段后每天放电段数是否超过 MAX_ONES_PER_BIT
time_charge_discharge_save_check全局(声明)周期性充放电时间表变更时做合法性校验并置落盘标志
modbus_sunspec_en_set全局(声明)单独设置 Sunspec 协议使能位并置落盘标志
modbus_sunspec_addr_set全局(声明)单独设置 Sunspec 从站地址(禁 0 且禁与主地址相同)
modbus_sunspec_en_addr_set全局(声明)由 16 位复合值(高字节使能、低字节地址)同时设置 Sunspec 使能与地址,并触发数据重初始化

注:modbus.c 中另有 9 个非 static 且未被本头文件声明的函数(handle_Modbus_response、handle_modbus_write_single_response、Handle_Modbus_Write_Response、Handle_Modbus_Exception、check_upgrade_infomation_for_cmd、check_upgrade_infomation、set_update_system_config、write_firmware_content、handle_modbus_tcp_recv_data),它们具备外部链接但缺少头文件原型,属于"隐式导出",详见 modbus.c.md 的风险点。

4. 核心逻辑解析

4.1 寄存器地址空间分区(REG_MODBUS_E)

枚举按"设备/功能块"划分连续地址段,段内以 ..._START_E 与 ..._MAX_E 成对定界,段内偏移靠隐式递增(省略 = 值 的枚举项在上一项基础上 +1)。各主段如下(十六进制):

地址段起始结束哨兵内容
电网电表0x0000REG_MAX_METER_ECT 使能/倍率、总买/卖电量、三相电压电流频率、有功/无功/视在功率、功率因数,含 A/B/C 相分相买电量与卖电量(0x37~0x3C)
PV 电表0x0080同上与电网电表同结构,整体偏移 0x80
户用电池(BMS)0x0100REG_HOUSEHOLD_BATTERY_MAX电压/电流/SOC/状态/继电器、单体最高最低电压与温度、充放截止、BMU/LMU/ISO 版本、容量类型 SOH、6 组 Warning 与 6 组 Fault、充放电量、MOS 控制、SOC 校准
充电桩 EV0x0200REG_EV_MAX_E4 台 EV 各 20 个寄存器(0x0200、0x0228、0x0250、0x0278),含放电模式、模式、标志、功率设定、三相电压电流、充电电量、故障码
电池 SN / 混用类型0x02E0REG_BATTERY_SN_MAX = 0x03AC12 组电池 SN(每组 16 寄存器 = 32 字节),紧接 12 个 REG_BATTERY{n}_MIX_TYPE_E
逆变器实时量0x0400REG_HOUSEHOLD_INVERTER_MAX_E三相电压电流功率、备电侧量、PV1~PV6、温度、2 组 Warning/2 组 Fault、PV 总发电量、工作模式、电池侧量、无功/视在、4 组扩展故障
ALPHAESS 扩展量0x0500REG_MAX_ALPHAESS_TAB_E额定电网参数、逆变输出/输入电量、电池输出/输入电量、运行时间、工作模式、各路温度、母线电压、PV 与组串电流、Buck/Boost 电流功率、RST 相电压电流、孤岛备电量、4 组 Warning/4 组 Fault、EMS 设定 AC/充/放电功率、强制充电标志、三相不平衡模式
逆变器信息(只读标识)0x0640REG_INVETER_INFO_MAX_E主/从/ARM 软件版本各 5 寄存器、SN 10 寄存器、机型 16 寄存器
HHE 定制段0x06FBREG_EMS_INFO_MAX_HHE_E电池容量、SOC 显示上下限、MOS 控制、馈网百分比、故障字、时间、EMS SN、DO/DI、高/中/低版本
系统信息/设置0x0740REG_SYS_MAX_E系统时间、EMS SN(16)、EMS 高低中版本与后缀、WiFi SN、Sunspec 设置 0x07F0;0x0800 起为馈网百分比、PV 容量、系统模式、电表 CT 选择、BAT Ready、网络参数(IP/掩码/网关)、Modbus 地址 0x080F 与波特率 0x0810、三相不平衡使能 0x0811、意大利防逆流 0x0815;0x084F 起为时间段控制(小时/分钟各 8 项);0x0862 起为周期性时间段读写组;0x0880 起为功率调度 8 参数、0x088F 起为频率调度 10 参数、0x08A0 起为南澳(SA)调度 7 参数、0x08B0/0x08C0 为 DO/DI、0x08D0 为 PV 与系统故障
Safety Test0x0FF0、0x1000REG_SAFETY_MAX_E安规版本、电网规约、安规测试使能、安全模式、PF/P-V/Q-V/S-PF 曲线、OVP/UVP/OFP/UFP 多级保护阈值与时间、恢复值、P-F 降载参数、保护限值与重合闸延时
ATE 测试0x1100REG_MAX_ATE_TAB_E复位模式、EMS SN/MAC/服务器指向、语言、逆变器类型、单板测试、OEM 标志、ATE 模式、DSP 软复位、N-N 短接、逆变器硬复位、下载使能、临时开关机、LED 控制、CAN 透传测试
EMS 指令寄存器组(CT 校准)0x1150REG_EMS_GET_MAX_E校准模式/复位、RST 电压电流、PV 电表 RST 电流、充放电功率校准点 0/1、清除指令 0x116D、设置值 0x1170~0x1173(写)、读回值 0x1174~0x1177(读)
CT 校准表0x11B7REG_MAX_CALIBRATION_TAB_E采样曲线使能、电网频率/电压、电网与 PV CT 电流/功率、电压 2 点、电网电流 5 点、电网功率 5 点、PV 电流 5 点、PV 功率 5 点的 point/coef/offset
DEBUG0x1200REG_DEBUG_MAX23 组 32 位调试量(REG_DEBUG1_H_E~REG_DEBUG23_L_E)
SOC 校准0x1900REG_SYS_SOC_CALIBRATION_MAX使能、周期设置/周期、天数、年/月/日/分钟 定点时刻
系统自定义(OEM)0x2000REG_SYS_CUSTOM_MAX复位、显示使能/类型、逆变器机型 16 组、登录公司名 16 组、登录密码 16 组、以太网使能/加密使能、服务器 64 组、端口 1/2、加密端口 1/2
AUX 干接点0x2200REG_AUX_CONFIG_MAX_E2 个通道各 17 项:使能、控制模式、两组起止时间、日期使能、充电 SOC、充电模式、UPS 使能、开关机功率、延时、持续时间、暂停
油机 GC0x2250REG_GC_CONFIG_MAX_E油机使能、模式、SOC 起止、时间起止、输出模式、充电功率、额定功率、速率百分比、ATS 使能、控制器使能
PV 充电机0x2300(配置)/0x2340(运行)REG_PV_CHARGER_CONFIG_MAX_E配置段为广播地址 0 专用;运行段含电池状态、SOC、电压/电流/功率、最大充放功率、充放截止电压电流、类型、额定电压

Sunspec 使用完全独立的高地址窗口 0x9C40 ~ 0xA052(REG_SUNSPEC_MODBUS_E),与主表不重叠。

4.2 请求结构与 TCP 头布局

MODBUS_REQ_T 使用 #pragma pack(1) 紧凑排列,恰好 6 字节:u8_local_addr(1) + func_code(1) + addr_register_start(2) + num_reg(2),与 Modbus RTU 帧中"地址 + 功能码 + 起始地址 + 数量"字段一一对应,因此对 RTU 缓冲可以直接按字段拼装。

MODBUS_TCP_TABLE 前 6 字节对应 MBAP 头(事务标识 2 + 协议标识 2 + 长度 2),第 7 字节(下标 6)为单元标识符即 u8_local_addr——这正是 MODBUS_TCP_PDU_ADDR = 7 的含义:PDU 的功能码位于报文下标 7。全文件所有 TCP 偏移都基于此常量书写(如 buff_Recv_modbus_tcp[MODBUS_TCP_PDU_ADDR + 1] 即 PDU 第 1 字节)。

4.3 配置存储契约

MODBUS_CONFIG_INFO_T 是 Modbus 配置在 Flash 扇区中的镜像,被 #pragma pack(1) 包裹并配 STATIC_ASSERT(ASSERT_FLASH_SECTOR_SIZE % sizeof(MODBUS_CONFIG_INFO_T) == 0):这要求结构体 sizeof 必须整除 Flash 扇区大小,从而允许"扇区中平铺多个配置块"。结构共 128 字节(1+... 逐字段:head 2 + address 1 + baud 1 + sunspec_en 1 + sunspec_addr 2 + sunspec_Ver 2 + reserved 117 + crc 2 = 128),u8_reserved[117] 是为对齐预留的填充,u16_crc_code 为整块 CRC。

4.4 升级相关枚举的取值耦合

MODBUS_UPGRADE_OBJECT_E 的枚举值不是内部标识,而是直接作为 TCP 报文 PDU 中的对象编码下发(check_upgrade_infomation 中 l_u8_target = buff_Recv_modbus_tcp[MODBUS_TCP_PDU_ADDR + 1] 后强转)。因此该枚举的任何顺序调整都会改变线上协议;UPGRADE_OBJECT_EMS_E 必须保持为 1。同理 MODBUS_BAUD_RATE_E 的取值(0/1/2)被直接写入 g_t_modbus_config.u8_modbus_baud_rate 并作为 modbus.c 中 switch 的分支条件。

CONFIG_SAVE_FLAG_T 是"写寄存器 → 置标志 → 由配置落盘任务统一存 Flash"的间接层:modbus.c 只置位,落盘动作在其它模块(data/system_config/system_config.c)完成,从而把 Flash 擦写从通信任务中解耦。

5. 对外接口

本文件导出的宏/类型/枚举(被谁使用)

导出项主要使用方
REG_MODBUS_E(寄存器号)modbus.c(读写分派)、sunspec_modbus.c、sunspec_business.c
MODBUS_REQ_T / MODBUS_TCP_TABLEmodbus.c(modbus_rtu_info、modbus_tcp_info)
g_t_modbus_config(extern)midware/interface/interface.c(读写地址/波特率/Sunspec)、midware/ethernt/ethernet.c、data/system_config/system_config.c(默认值初始化)、net/server.c(Sunspec 设置)
g_t_config_save_flag(extern)modbus.c 全文件置位;data/system_config/system_config.c 消费落盘
g_t_time_control_run(extern)modbus.c(周期性时间段写入缓存)、hmi/key.c、net/server.c、midware/inverter/inverter.c、data/system_config/system_config.c
g_t_ate_ctrol(extern)modbus.c(ATE 寄存器)、midware/debug(板测)
buff_send_modbus(extern)midware/inverter/pvcharger.c(PV 充电机主机应答复用同一发送缓冲)
CONFIG_SAVE_FLAG_T / ATE_CTROL_T / DISPLAY_LED_LAMP_PANE_CTROL_U / MODBUS_UPGRADE_OBJECT_E / UPGRADE_CONFIG_ERR_E / MODBUS_BAUD_RATE_E / REG_MOSBUS_ERR_E / MODBUS_EX_CODE_Emodbus.c 内部为主,枚举值经 net/ 升级流程间接使用
LEN_RECV_MODBUS / FUNC_* / MODBUS_TCP_PDU_ADDR / TCP_PDU_CONFIG_LENGTH / MD5_MAX_BYTEmodbus.c、pvcharger.c、sunspec_*
19 个函数原型modbus.c(实现)、midware/interface/interface.c(handle_modbus_ret_recv_data)、midware/ethernt/ethernet.c(ems_to_modbus_tcp、set/get_flag_modbus_force_update)、net/server.c(modbus_sunspec_en_addr_set)、net/ems.c(get_flag_modbus_force_update)、midware/inverter/pvcharger.c(get_para_from_reg_addr、modbus_send_data)

本文件依赖的外部声明(仅 include)

头文件用途
chip.hGD32 平台基础类型 u8/u16/u32/s8/...、TRUE/FALSE
dispatch.h功率/频率/南澳调度结构体(g_t_dispatch_t 相关类型)
logic.hg_t_logic_info、LOGIC_TIME_CONTROL_TAB_T、LOGIC_CONFIG_EXTEND1_TAB_T、LOGIC_CONFIG_EXTEND2_TAB_T、TIME_CONTROL_RUN_TAB_T
debug.hSTATIC_ASSERT 宏、ASSERT_FLASH_SECTOR_SIZE、FLASH_SECTOR_SIZE

6. 依赖关系

7. 备注与风险点

  1. REG_MODBUS_E 中存在明显的笔误枚举名:REG_EMS_SN_5_6_HEE_E(应为 ..._HHE_E,第 665 行)、REG_INVERTER_BACKIP_POWER_L3_H_E(应为 BACKUP,第 422 行)、P_F_UF_DERATING_CUT_F1_E(缺少 REG_ 前缀,第 907 行)、REG_METER_SATRT 与 REG_BATTERY_SATRT(SATRT 应为 START,第 95/195 行)、REG_HOUSEHOLD_BATTERY_MAX(段结束哨兵,缺少 _E 后缀,第 269 行)、REG_DEBUG_MAX(同样无 _E 后缀,第 1086 行)。此外 REG_INVETER_INFO_START_E/REG_MAX_ALPHAESS_TAB_E/REG_INVETER_INFO_MAX_E 等大量枚举名把 INVERTER 拼成 INVETER。这些名字一旦有外部引用就不能随意更正。
  2. MAX/START 哨兵依赖隐式递增(维护风险):枚举中绝大多数 ..._MAX_E、..._START_E 都没有显式赋值,靠上一项 +1 得到。只有部分段起始地址写了显式十六进制值(如 REG_BATTERY_SATRT = 0x0100、REG_EV_START = 0x0200、REG_INVETER_INFO_START_E = 0x0640、REG_SYS_START_E = 0x0740、REG_SYS_CUSTOM_CONFIG_START = 0x2000、REG_AUX_CONFIG_START_E = 0x2200、REG_GC_CONFIG_START_E = 0x2250、REG_PV_CHARGER_CONFIG_START_E = 0x2300),因此段起始地址是稳定的,而段结束哨兵会随段内增删枚举项而漂移。而 modbus.c 的地址合法性判定恰好大量使用这些 MAX 哨兵(REG_MAX_METER_E、REG_HOUSEHOLD_BATTERY_MAX、REG_EV_MAX_E、REG_BATTERY_SN_MAX、REG_SYS_MAX_E、REG_MAX_MODBUS_E …)作为上界——在段内插入一个寄存器常量就会让上界静默移动,可能使原先合法的地址越界、或让相邻段被吞并。是本次分析中最需要警惕的结构性风险。
  3. 枚举值被直接当协议码使用:MODBUS_UPGRADE_OBJECT_E、MODBUS_BAUD_RATE_E、UPGRADE_FLAG_E 的取值参与线上协议和分支判断,重排序会静默破坏兼容性,建议改为显式赋值。
  4. REG_MAX_MODBUS_E 的语义含糊:它既是"主表最大值",又被 modbus.c 用作全局地址上界(register_temp < REG_MAX_MODBUS_E),但主表中实际还包含 ATE/Safety/校准/DEBUG/CUSTOM/AUX/GC/PV_CHARGER 等子表;只要这些子表都排在它之前,语义才成立。
  5. 非标准 Sunspec 地址窗口:Sunspec 常用的是 40000 系列(0x9C40 = 40000 十进制),此处定义与 SunSpec 官方模型编号无关,是项目自定义的映射窗口,注释中标明 SUNSPEC_STRU_NUM = 783(见 sunspec_modbus.h),属于私有实现。
  6. #pragma pack(1) 与 #pragma pack() 的成对使用(第 1391 行开、第 1480 行关)正确;但若后续 include 的其它头文件在此区间内被包含,会继承紧凑对齐,当前文件无中间 include,安全。
  7. STATIC_ASSERT 的依赖风险:ASSERT_FLASH_SECTOR_SIZE 定义在 midware/debug/debug.h,属"调试模块",若某变体工程裁剪该头文件会导致编译失败。
  8. ADDR_MODBUS = 0x55 与 ADDR_SUNSPEC_MODBUS = 0x01 只在 data/system_config/system_config.c 做默认值初始化时使用,modbus.c 中不使用(改用 g_t_modbus_config 现值),因此这两个宏在生产代码里是"初始化常量",不是运行期常量。