modbus.h
REG_MODBUS_E)4.2 请求结构与 TCP 头布局4.3 配置存储契约4.4 升级相关枚举的取值耦合5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
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)。各主段如下(十六进制):
| 地址段 | 起始 | 结束哨兵 | 内容 |
|---|---|---|---|
| 电网电表 | 0x0000 | REG_MAX_METER_E | CT 使能/倍率、总买/卖电量、三相电压电流频率、有功/无功/视在功率、功率因数,含 A/B/C 相分相买电量与卖电量(0x37~0x3C) |
| PV 电表 | 0x0080 | 同上 | 与电网电表同结构,整体偏移 0x80 |
| 户用电池(BMS) | 0x0100 | REG_HOUSEHOLD_BATTERY_MAX | 电压/电流/SOC/状态/继电器、单体最高最低电压与温度、充放截止、BMU/LMU/ISO 版本、容量类型 SOH、6 组 Warning 与 6 组 Fault、充放电量、MOS 控制、SOC 校准 |
| 充电桩 EV | 0x0200 | REG_EV_MAX_E | 4 台 EV 各 20 个寄存器(0x0200、0x0228、0x0250、0x0278),含放电模式、模式、标志、功率设定、三相电压电流、充电电量、故障码 |
| 电池 SN / 混用类型 | 0x02E0 | REG_BATTERY_SN_MAX = 0x03AC | 12 组电池 SN(每组 16 寄存器 = 32 字节),紧接 12 个 REG_BATTERY{n}_MIX_TYPE_E |
| 逆变器实时量 | 0x0400 | REG_HOUSEHOLD_INVERTER_MAX_E | 三相电压电流功率、备电侧量、PV1~PV6、温度、2 组 Warning/2 组 Fault、PV 总发电量、工作模式、电池侧量、无功/视在、4 组扩展故障 |
| ALPHAESS 扩展量 | 0x0500 | REG_MAX_ALPHAESS_TAB_E | 额定电网参数、逆变输出/输入电量、电池输出/输入电量、运行时间、工作模式、各路温度、母线电压、PV 与组串电流、Buck/Boost 电流功率、RST 相电压电流、孤岛备电量、4 组 Warning/4 组 Fault、EMS 设定 AC/充/放电功率、强制充电标志、三相不平衡模式 |
| 逆变器信息(只读标识) | 0x0640 | REG_INVETER_INFO_MAX_E | 主/从/ARM 软件版本各 5 寄存器、SN 10 寄存器、机型 16 寄存器 |
| HHE 定制段 | 0x06FB | REG_EMS_INFO_MAX_HHE_E | 电池容量、SOC 显示上下限、MOS 控制、馈网百分比、故障字、时间、EMS SN、DO/DI、高/中/低版本 |
| 系统信息/设置 | 0x0740 | REG_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 Test | 0x0FF0、0x1000 | REG_SAFETY_MAX_E | 安规版本、电网规约、安规测试使能、安全模式、PF/P-V/Q-V/S-PF 曲线、OVP/UVP/OFP/UFP 多级保护阈值与时间、恢复值、P-F 降载参数、保护限值与重合闸延时 |
| ATE 测试 | 0x1100 | REG_MAX_ATE_TAB_E | 复位模式、EMS SN/MAC/服务器指向、语言、逆变器类型、单板测试、OEM 标志、ATE 模式、DSP 软复位、N-N 短接、逆变器硬复位、下载使能、临时开关机、LED 控制、CAN 透传测试 |
| EMS 指令寄存器组(CT 校准) | 0x1150 | REG_EMS_GET_MAX_E | 校准模式/复位、RST 电压电流、PV 电表 RST 电流、充放电功率校准点 0/1、清除指令 0x116D、设置值 0x1170~0x1173(写)、读回值 0x1174~0x1177(读) |
| CT 校准表 | 0x11B7 | REG_MAX_CALIBRATION_TAB_E | 采样曲线使能、电网频率/电压、电网与 PV CT 电流/功率、电压 2 点、电网电流 5 点、电网功率 5 点、PV 电流 5 点、PV 功率 5 点的 point/coef/offset |
| DEBUG | 0x1200 | REG_DEBUG_MAX | 23 组 32 位调试量(REG_DEBUG1_H_E~REG_DEBUG23_L_E) |
| SOC 校准 | 0x1900 | REG_SYS_SOC_CALIBRATION_MAX | 使能、周期设置/周期、天数、年/月/日/分钟 定点时刻 |
| 系统自定义(OEM) | 0x2000 | REG_SYS_CUSTOM_MAX | 复位、显示使能/类型、逆变器机型 16 组、登录公司名 16 组、登录密码 16 组、以太网使能/加密使能、服务器 64 组、端口 1/2、加密端口 1/2 |
| AUX 干接点 | 0x2200 | REG_AUX_CONFIG_MAX_E | 2 个通道各 17 项:使能、控制模式、两组起止时间、日期使能、充电 SOC、充电模式、UPS 使能、开关机功率、延时、持续时间、暂停 |
| 油机 GC | 0x2250 | REG_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_TABLE | modbus.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_E | modbus.c 内部为主,枚举值经 net/ 升级流程间接使用 |
LEN_RECV_MODBUS / FUNC_* / MODBUS_TCP_PDU_ADDR / TCP_PDU_CONFIG_LENGTH / MD5_MAX_BYTE | modbus.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.h | GD32 平台基础类型 u8/u16/u32/s8/...、TRUE/FALSE |
dispatch.h | 功率/频率/南澳调度结构体(g_t_dispatch_t 相关类型) |
logic.h | g_t_logic_info、LOGIC_TIME_CONTROL_TAB_T、LOGIC_CONFIG_EXTEND1_TAB_T、LOGIC_CONFIG_EXTEND2_TAB_T、TIME_CONTROL_RUN_TAB_T |
debug.h | STATIC_ASSERT 宏、ASSERT_FLASH_SECTOR_SIZE、FLASH_SECTOR_SIZE |
6. 依赖关系
- 依赖:
chip.h(类型系统)、dispatch.h、logic.h、debug.h。不依赖modbus.c,二者构成"声明/实现"配对。 - 被依赖:
midware/interface/modbus/modbus.c(唯一实现者)、sunspec_modbus.c/sunspec_business.c(同目录,共用MODBUS_REQ_T与 Sunspec 地址窗口)、midware/interface/interface.c、midware/inverter/pvcharger.c、midware/ethernt/ethernet.c、net/server.c、net/ems.c、data/system_config/system_config.c、hmi/key.c。
7. 备注与风险点
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。这些名字一旦有外部引用就不能随意更正。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…)作为上界——在段内插入一个寄存器常量就会让上界静默移动,可能使原先合法的地址越界、或让相邻段被吞并。是本次分析中最需要警惕的结构性风险。- 枚举值被直接当协议码使用:
MODBUS_UPGRADE_OBJECT_E、MODBUS_BAUD_RATE_E、UPGRADE_FLAG_E的取值参与线上协议和分支判断,重排序会静默破坏兼容性,建议改为显式赋值。 REG_MAX_MODBUS_E的语义含糊:它既是"主表最大值",又被modbus.c用作全局地址上界(register_temp < REG_MAX_MODBUS_E),但主表中实际还包含 ATE/Safety/校准/DEBUG/CUSTOM/AUX/GC/PV_CHARGER 等子表;只要这些子表都排在它之前,语义才成立。- 非标准 Sunspec 地址窗口:Sunspec 常用的是 40000 系列(
0x9C40= 40000 十进制),此处定义与 SunSpec 官方模型编号无关,是项目自定义的映射窗口,注释中标明SUNSPEC_STRU_NUM = 783(见sunspec_modbus.h),属于私有实现。 #pragma pack(1)与#pragma pack()的成对使用(第 1391 行开、第 1480 行关)正确;但若后续 include 的其它头文件在此区间内被包含,会继承紧凑对齐,当前文件无中间 include,安全。STATIC_ASSERT的依赖风险:ASSERT_FLASH_SECTOR_SIZE定义在midware/debug/debug.h,属"调试模块",若某变体工程裁剪该头文件会导致编译失败。ADDR_MODBUS = 0x55与ADDR_SUNSPEC_MODBUS = 0x01只在data/system_config/system_config.c做默认值初始化时使用,modbus.c中不使用(改用g_t_modbus_config现值),因此这两个宏在生产代码里是"初始化常量",不是运行期常量。