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 / _PV | extern 变量 | 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_meter | extern 变量 | 各信息模型数据实体,定义在 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)。这意味着:
- 下游驱动只需在刷新时把值写进这些结构体,寄存器表自动"看到"最新值(读路径零拷贝);
- 但对 16 位量做了 32/64 位拆分:
((u16*)&字段)+1取高 16 位,(u16*)&字段取低 16 位(小端 ARM 下低字在前); - 同一个变量可被多个寄存器重复映射(如
g_t_sunspec_run.pf出现在 40083/40114/40137/40160,即三相 PF 共用同一值)。
4.3 字节序与倍率的语义
LIT_ENDIAN的行在读写时按((v>>8)&0xFF)|((v<<8)&0xFF00)交换字节(sunspec_business.c:941-944、994-997);字符串类字段(mn/md/opt/ver)全部是LIT_ENDIAN,而数值字段全部BIG_ENDIAN(统计:BIG_ENDIAN599 行、LIT_ENDIAN184 行)。scale字段在 783 行中有 780 行为SCALE_1(=1000),仅 40115/40116/40117 三行为SCALE_0_1(=100)。实际换算代码为scale / 1000,见第 7 节风险点。
4.4 读写权限分布
可写(RW)共 78 行,其余 705 行为 RO,不存在 WO。可写寄存器集中在:
| 地址段 | 含义 |
|---|---|
| 40068 | g_t_modbus_config.u16_sunspec_addr,允许主站改从站地址 |
| 40252~40270 | Model 702 的 *_set 段(含 40260/40261 = MAX_CHG_40260/MAX_DISCHG_40261) |
| 40280~40299 | Model 704 的 PF / WMaxLimPct 控制组 |
| 40300~40329 | Model 704 的 Wset 有功调度组(WSET_ENA_40300~40310)与 VarSet 无功调度组 |
| 40336~40351 | w_fac_set[0]/[1] 功率因数曲线点 |
| 40497、40672 | GRID / PV 电表的 meter_addr |
Model 1/203/701/713/714 的测量数据全部只读。
4.5 与 uCOS-II 任务的关系
本文件不含代码,不直接参与任务调度。相关的运行时序由 sunspec_business.c(刷新)与 midware/interface/modbus/modbus.c(帧解析/应答)承担,本头文件只提供它们共享的数据契约。
5. 对外接口
本文件导出的内容(供其他模块使用)
- 类型/枚举:
SUNSPEC_MODBUS_T、SUNSPEC_ID_T、SUNSPEC_DATA_BASE_T、SUNSPEC_DATA_DEFAULT_T、SUNSPEC_RUN_DATA_T、SUNSPEC_NAMEPLATE_T、SUNSPEC_POWER_FACTOR_SET_T、SUNSPEC_CONTROL_T、SUNSPEC_BAT_T、SUNSPEC_DC_GROUP_T、SUNSPEC_DC_T、SUNSPEC_METER_EVT_U、SUNSPEC_AC_METER_T、SUNSPEC_COMM_T,以及全部E_*枚举。 - 常量宏:
SUNSPEC_STRU_NUM。 - 全局变量:
g_t_sunspec_base、g_t_sunspec_base_GRID、g_t_sunspec_base_PV、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_meter、g_t_sunspec_mudbus[]。 - 主要使用方:
sunspec_modbus.c(定义)、sunspec_business.c/sunspec_business.h(读写)、midware/interface/modbus/modbus.c(引用SUNSPEC_STRU_NUM)。
本文件依赖的外部内容
#include "sdram.h"(sunspec_modbus.h:9)——提供u8/u16/s16/u32/s32/u64等类型定义;被注释掉的 SDRAM 属性宏也来自此头文件。
6. 依赖关系
- 依赖:
sdram.h(基础类型)。 - 被依赖:
midware/interface/modbus/sunspec_modbus.c(定义全部extern变量);midware/interface/modbus/sunspec_business.h(#include "sunspec_modbus.h");- 经
sunspec_business.h间接被logic/ac_control.c、logic/logic.c、logic/dispatch.c、midware/interface/interface.c、net/server.c、data/system_config/system_config.c使用; midware/interface/modbus/modbus.c使用SUNSPEC_STRU_NUM。
7. 备注与风险点
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。E_SCALE_FACTOR的取值方向容易误用:SCALE_1 = 1000而SCALE_0_1 = 100,命名与数值是"倒数关系"。使用方若直接拿scale当乘数会得到 1000 倍错误结果,必须除以 1000(见sunspec_business.c:936)。SUNSPEC_RUN_DATA_T.void_data是单一 u16 变量,却被 110 个寄存器共用(如 40060~40067、40087、40089~40094、40224 等)。主站对这些地址的写操作会互相覆盖、读回值永远相同;占用寄存器空间但不承载数据。这在 SunSpec 一致性上属于"垫片",但如果客户按语义解释这些地址会出错。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),属于结构体内未使用的字段,可能是协议演进残留。SUNSPEC_MODBUS_T中的函数指针回调被注释(sunspec_modbus.h:109)。sunspec_business.c:1003-1006的注释也印证:"这种数量又特别少,故在这里处理即可,以后多了建议在结构体中加入函数指针……否则这函数容易成屎山"。当前特殊写处理依靠switch(addr)硬编码,随需求增加会持续膨胀。SUNSPEC_NAMEPLATE_T中supported_control_mode是 u32,但*_set段缺少对应的supported_control_mode_set;实际以 40249/40250 两行映射同一 u32 的高低字。标准 SunSpec 702 该字段为 bitfield32,是否可写应确认(当前 40249/40250 均为 RO)。E_SUNSPEC_WSET_ENA枚举中WSET_ENA_40302到WSET_ENA_40310依赖"枚举隐式递增"(从 40300 起逐 1 递增),若将来在中间插入枚举项会导致地址全部错位,建议显式赋值。- 头文件使用
__SUNSPES_MODBUS_H__(拼写少一个 C)作为保护宏,与文件名sunspec不一致,属历史拼写遗留,无功能影响但易在检索时漏掉。