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

sunspec_modbus.h

源文件路径:midware/interface/modbus/sunspec_modbus.h 所属模块:midware/interface/modbus(SunSpec 协议设备侧从站数据模型) 代码行数:459

1. 文件职责

本文件是 SunSpec Modbus 从站(EMS 侧为 Server/Slave)的数据模型与协议常量总声明。它定义了整张寄存器映射表的行结构 SUNSPEC_MODBUS_T(数据指针 / 寄存器地址 / 默认值 / 初始化类型 / 大小端 / 倍率 / 读写权限),以及按 SunSpec 信息模型拆分的各结构体:公共块(Model 1)、DER AC 测量(701)、DER 容量铭牌(702)、DER AC 控制(704)、储能容量(713)、DER 直流测量(714)、AC 电表(203)。所有实际数据实体都在 sunspec_modbus.c 中定义并 extern 到本头文件,由 sunspec_business.c 和 midware/interface/modbus/modbus.c 使用。它处在数据流的最末端:上游各模块(逆变器、电表、BMS、逻辑调度)把运行数据写进这些结构体,再由寄存器表回答外部 SunSpec 主站的读写请求。

2. 关键数据结构与宏

名称类型说明
SUNSPEC_STRU_NUM宏 783寄存器映射表 g_t_sunspec_mudbus[] 的元素个数,与 40000~40782 的地址跨度严格 1:1(sunspec_modbus.h:11)
E_R_W枚举读写权限:RO=0x01、WO=0x02、RW=0x03。代码用按位与判断(rw & RO、rw & WO),因此 RW 同时具备读与写(sunspec_modbus.h:16-20)
E_BIG_ENDIAN枚举字节序:BIG_ENDIAN、LIT_ENDIAN。LIT_ENDIAN 的寄存器在读/写时会做高低字节交换(sunspec_modbus.h:22-25)
E_SCALE_FACTOR枚举倍率,取值本身就是"×1000 的倒数":SCALE_0_001=1、SCALE_0_01=10、SCALE_0_1=100、SCALE_1=1000、SCALE_10=10000、SCALE_100=100000、SCALE_1000=1000000(sunspec_modbus.h:27-35)
E_SUNSPEC_WSET_ENA枚举有功功率调度相关寄存器地址常量(40000 偏移后的绝对地址):WSET_ENA_40300~WSET_ENA_40310、MAX_CHG_40260、MAX_DISCHG_40261。用于 switch 分派特殊写处理(sunspec_modbus.h:37-51)
E_SUNSPEC_NAME枚举信息模型实例编号。因客户要求"每个电表前增加通用模型 1",同一型号会出现多个 Model 1/203 实例:ID_1、ID_701、ID_702、ID_704、ID_713、ID_714、ID_GRID_1、ID_GRID_203、ID_PV_1、ID_PV_203、ID_END、ID_MAX(sunspec_modbus.h:58-71)
E_INIT_TYPE枚举INIT=初始化为默认值;RUNING=运行数据不初始化(sunspec_modbus.h:78-81)
E_SUNSPEC_INV_TYPE枚举逆变器机型索引,对应 sunspec_business.c 中的铭牌数组下标:SUNSPEC_G3_S5/S6/S8/B5/3_6/T4/T5/T6/T8/T10/T12_VAVE/T15_VAVE/T15_INO/T20_INO,共 14 项,SUNSPEC_INV_MAX 为上限(sunspec_modbus.h:83-99)
SUNSPEC_MODBUS_T结构体整张寄存器表的核心行结构:data_p(u16* 实际内存)、addr(u16 SunSpec 地址)、default_value(s16)、init_type、big_endian、scale(倍率)、rw。注意被注释掉的 sunspec_call_back_deal 函数指针说明扩展点曾被考虑但未启用(sunspec_modbus.h:101-111)
SUNSPEC_ID_T结构体信息模型实例的 model_id / model_len 两个字(sunspec_modbus.h:115-119)
SUNSPEC_DATA_BASE_T结构体Model 1 公共块:sunspec_star[5]("SunS" 标识)、mn[32](厂商)、md[32](型号)、opt[16](可选描述)、ver[16](版本)。注释掉的 device_addr/end_model 是遗留字段(sunspec_modbus.h:121-129)
SUNSPEC_DATA_DEFAULT_T结构体仅含 operating_sta,映射到 40073(Model 701 的 Operating State)(sunspec_modbus.h:131-134)
SUNSPEC_RUN_DATA_T结构体Model 701 运行数据聚合:void_data(哑元/占位寄存器,见风险点)、inv_sta、grid_connect、inv_alarms、DER_mode、inv_cur、inv_LLV/inv_LNV、inv_reactive_energy_input/output(u64)、ambient_temp/cabinet_temp、inv_phase_num、throttle_source、max_feedin_percent、pf、inv_apparent_power/inv_reactive_power,以及 10 个倍率字段(sunspec_modbus.h:136-169)
E_SUNSPEC_NORMAL_CATEGORY_U枚举正常工况类别 SUNSPEC_CAT_A/SUNSPEC_CAT_B(sunspec_modbus.h:171-174)
E_SUNSPEC_ABNORMAL_CATEGORY_U枚举异常工况类别 SUNSPEC_CAT_1/2/3(sunspec_modbus.h:176-180)
SUNSPEC_NAMEPLATE_T结构体Model 702 容量铭牌,同时被复用为调度限值来源。含额定值段(max_actpower、max_apparentpower、max_charge_rat/max_discharge_rat、rate_AC_volt、Max_AC_cur、supported_control_mode(u32)、intentional_island 等)与 *_set 设置值段,末尾 7 个 *_scale 为 SunSpec 标准的 SF 比例因子(sunspec_modbus.h:182-239)
SUNSPEC_POWER_FACTOR_SET_T结构体功率因数曲线点:PFWinj_PF/Ext、PFWinjRvrt_PF/Ext、PFWAbs_*、PFWAbsRvrt_*(sunspec_modbus.h:241-250)
SUNSPEC_CONTROL_T结构体Model 704 控制块。分四组:PF 注入/吸收控制(PFWinj*、PFWAbs*)、有功限值(WMaxLimPct*)、有功调度(WsetEna/WsetMod/Wset/WsetRvrt/WsetPct/WsetRvrtTms/WsetRvrtRem)、无功调度(VarSet*),加 w_fac_set[2] 曲线点、6 个 *_SF 比例因子,以及 EMS 自用字段 RvrtTms_refresh_tick、RvrtTms_refresh_flag、mppt_percentage、mppt_over_count(sunspec_modbus.h:252-302)
SUNSPEC_BAT_T结构体Model 713 储能容量:energy_rating、energy_available、storage_sta(0 正常/1 告警/2 故障)、soh、energy_scale、soc_scale(sunspec_modbus.h:304-311)
SUNSPEC_DC_GROUP_T结构体Model 714 的单个直流端口:PrtTyp、id、id_str[16]、DCA、DCV、DCW、DCWhinj/DCWhAbs(u64)、tmp、DCSta、DC_alrm(u32)(sunspec_modbus.h:313-325)
SUNSPEC_DC_T结构体Model 714 汇总:DC_alarms(u32)、DC_Ports_num、DC_total_cur、DC_total_power、DCWhinj_total/DCWhAbs_total(u64)、6 个 *_SF,加 group[4](实际只填 group[0]=电池、group[1]=PV)(sunspec_modbus.h:327-340)
SUNSPEC_METER_EVT_U联合体Model 203 电表事件位域:all_bit(u32) 与 BIT 结构体(M_EVENT_Power_Failure、Under_Voltage、Low_PF、Over_Current、Over_Voltage、Missing_Sensor 及 15 个 OEM 位)共用(sunspec_modbus.h:342-379)
SUNSPEC_AC_METER_T结构体Model 203 电表数据:cur_total、vol_ln/vol_ll_ln、apparent_power[_a/b/c]、9 个倍率字段、双向无功/视在电能四象限累积量(energy_imp_*_Q1/Q2、energy_exp_*_Q3/Q4)、meter_Evt、meter_addr(sunspec_modbus.h:382-428)
SUNSPEC_COMM_T结构体通信存活标记:refresh_tick + refresh_flag,用于 30 s 超时判定 SunSpec 主站是否还在轮询(sunspec_modbus.h:430-433)
g_t_sunspec_base / _GRID / _PVextern 变量3 份 Model 1 公共块(主/电网电表/PV 电表)(sunspec_modbus.h:435-437)
g_t_sunspec_default、g_t_sunspec_run、g_t_sunspec_inv_nameplate、g_t_sunspec_ctlAC、g_t_sunspec_bat、g_t_sunspec_DC、g_t_sunspec_AC_meter、g_t_sunspec_PV_meterextern 变量各信息模型数据实体,定义在 sunspec_modbus.c(sunspec_modbus.h:439-452)
g_t_sunspec_mudbus[SUNSPEC_STRU_NUM]extern 变量783 行寄存器映射表本体。注意声明末尾 __attribute__((at(SDRAM_SUNSPEC_DATA_ADDR))) 被注释掉,因此该表落在普通 RAM(sunspec_modbus.h:455)

3. 函数清单

本文件为纯声明头文件,不包含任何函数定义,仅有 14 个 extern 变量声明(sunspec_modbus.h:435-455)。

4. 核心逻辑解析

4.1 寄存器表的寻址模型

整张表按 addr 升序排列(源码注释明确要求 midware/interface/modbus/sunspec_modbus.c:46"必须保持升序排列"),覆盖 40000~40782 共 783 个保持寄存器,因此地址可以直接用二分查找定位,查找算法在 sunspec_business.c 中实现。

4.2 数据/元数据分离

SUNSPEC_MODBUS_T.data_p 指向的不是表内缓存,而是各业务模块的全局变量本体(如 g_t_meter.t_grid_info.t_data.s16_current[PHASE_A]、g_t_inv_info.t_run_info.s32_inv_actpower_a)。这意味着:

4.3 字节序与倍率的语义

4.4 读写权限分布

可写(RW)共 78 行,其余 705 行为 RO,不存在 WO。可写寄存器集中在:

地址段含义
40068g_t_modbus_config.u16_sunspec_addr,允许主站改从站地址
40252~40270Model 702 的 *_set 段(含 40260/40261 = MAX_CHG_40260/MAX_DISCHG_40261)
40280~40299Model 704 的 PF / WMaxLimPct 控制组
40300~40329Model 704 的 Wset 有功调度组(WSET_ENA_40300~40310)与 VarSet 无功调度组
40336~40351w_fac_set[0]/[1] 功率因数曲线点
40497、40672GRID / PV 电表的 meter_addr

Model 1/203/701/713/714 的测量数据全部只读。

4.5 与 uCOS-II 任务的关系

本文件不含代码,不直接参与任务调度。相关的运行时序由 sunspec_business.c(刷新)与 midware/interface/modbus/modbus.c(帧解析/应答)承担,本头文件只提供它们共享的数据契约。

5. 对外接口

本文件导出的内容(供其他模块使用)

本文件依赖的外部内容

6. 依赖关系

7. 备注与风险点

  1. g_t_sunspec_mudbus 的 SDRAM 放置被注释掉(sunspec_modbus.h:455)。783 行 × sizeof(SUNSPEC_MODBUS_T)(指针 4 + u16 2 + s16 2 + 4 个 int 枚举 16 = 24 字节,含对齐)= 约 18.4 KB 常驻 RAM,且因带初值全部落在 .data 段(同时占用 Flash 副本)。注释掉 at(SDRAM_...) 后这块内存占用了内部 SRAM。
  2. E_SCALE_FACTOR 的取值方向容易误用:SCALE_1 = 1000 而 SCALE_0_1 = 100,命名与数值是"倒数关系"。使用方若直接拿 scale 当乘数会得到 1000 倍错误结果,必须除以 1000(见 sunspec_business.c:936)。
  3. SUNSPEC_RUN_DATA_T.void_data 是单一 u16 变量,却被 110 个寄存器共用(如 40060~40067、40087、40089~40094、40224 等)。主站对这些地址的写操作会互相覆盖、读回值永远相同;占用寄存器空间但不承载数据。这在 SunSpec 一致性上属于"垫片",但如果客户按语义解释这些地址会出错。
  4. SUNSPEC_RUN_DATA_T.inv_LLV / inv_LNV 在寄存器表里未见映射(sunspec_modbus.c 中出现的是 g_t_alphaess_comm_info...u16_grid_volt_rs/r/st/rt/t/s),属于结构体内未使用的字段,可能是协议演进残留。
  5. SUNSPEC_MODBUS_T 中的函数指针回调被注释(sunspec_modbus.h:109)。sunspec_business.c:1003-1006 的注释也印证:"这种数量又特别少,故在这里处理即可,以后多了建议在结构体中加入函数指针……否则这函数容易成屎山"。当前特殊写处理依靠 switch(addr) 硬编码,随需求增加会持续膨胀。
  6. SUNSPEC_NAMEPLATE_T 中 supported_control_mode 是 u32,但 *_set 段缺少对应的 supported_control_mode_set;实际以 40249/40250 两行映射同一 u32 的高低字。标准 SunSpec 702 该字段为 bitfield32,是否可写应确认(当前 40249/40250 均为 RO)。
  7. E_SUNSPEC_WSET_ENA 枚举中 WSET_ENA_40302 到 WSET_ENA_40310 依赖"枚举隐式递增"(从 40300 起逐 1 递增),若将来在中间插入枚举项会导致地址全部错位,建议显式赋值。
  8. 头文件使用 __SUNSPES_MODBUS_H__(拼写少一个 C)作为保护宏,与文件名 sunspec 不一致,属历史拼写遗留,无功能影响但易在检索时漏掉。