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

sunspec_business.h

源文件路径:midware/interface/modbus/sunspec_business.h 所属模块:midware/interface/modbus(Sunspec Modbus 协议应用层) 代码行数:35

1. 文件职责

这是 Sunspec 协议业务数据层的对外接口头文件,只做两件事:声明 sunspec_business.c 对外暴露的 15 个函数原型,以及 #include "sunspec_modbus.h" 把 Sunspec 的类型体系(u8/u16 等基础类型、SUNSPEC_MODBUS_T、各 SUNSPEC_* 结构体与 g_t_sunspec_* 全局变量声明)传递给调用方。

它本身不含任何数据类型定义、宏或变量定义,是一个纯粹的"函数声明清单",不承载逻辑,也不参与数据流。

被 modbus.c(从站读写与初始化)、interface.c(Modbus 任务调度)、logic.c / ac_control.c(取限值、MPPT 百分比、调度使能)、system_config.c 与 server.c(配置变更触发初始化)等 8 个 .c 文件包含。

2. 关键数据结构与宏

本文件没有定义任何结构体、枚举、联合体、位域或宏常量,全部内容来自其包含的头文件(sunspec_modbus.h):

名称类型说明
sunspec_modbus.h被包含的头文件本文件唯一的依赖,提供 u8/u16/s16/s32/s64/u64 类型(经 sdram.h)、SUNSPEC_* 结构与枚举、g_t_sunspec_* 全局变量 extern 声明、SUNSPEC_STRU_NUM 等宏。
__SUNSPEC_BUSINESS_H__宏(include guard)第 6~7 行定义,第 34 行 #endif,防止重复包含。

注:本文件未声明 sunspec_business.c 中定义的两个全局变量 g_sunspec_comm 与 g_t_sunspec_inv_nameplate_array,因此它们对其它编译单元不可见(实质为文件私有)。

3. 函数清单

本文件为头文件,不含函数体,仅 15 条函数原型声明(全部为全局作用域,无 static):

函数名作用域说明
sunspec_modbus_data_init全局(声明)Sunspec 数据初始化:清 base/run 结构、填标识串、按 init_type==INIT 写默认值。
sunspec_modbus_data_refresh全局(声明)Sunspec 运行数据总刷新,由 Modbus-RTU 任务周期调用。
sunspec_modbus_data_get全局(声明)按 Sunspec 地址查表读取寄存器值,返回 16 位数据。
sunspec_modbus_data_set全局(声明)按 Sunspec 地址查表写入寄存器值。
sunspec_modbus_dischg_get全局(声明)取电池最大放电功率设定值 max_dischg_set。
sunspec_modbus_chg_get全局(声明)取电池最大充电功率设定值 max_charge_set。
sunspec_modbus_Wset_ena_get全局(声明)取 Sunspec 有功功率调度使能 WsetEna。
sunspec_modbus_mppt_percentage_get全局(声明)取 Sunspec 调度下的 MPPT 百分比(10000 = 100%)。
sunspec_modbus_mppt_percentage_set全局(声明)设置 MPPT 百分比,上限 10000。
sunspec_refresh_flag_set全局(声明)收到合法 Sunspec 帧时刷新通信看门狗时间戳。
sunspec_refresh_flag_get全局(声明)读通信标志,超 30s 未刷新自动清零。
sunspec_modbus_mppt_over_count_add全局(声明)"PV 功率过大"计数自增。
sunspec_modbus_mppt_over_count_get全局(声明)取"PV 功率过大"计数。
sunspec_modbus_max_charge_rat_get全局(声明)取电池额定充电功率 max_charge_rat。
sunspec_modbus_max_discharge_rat_get全局(声明)取电池额定放电功率 max_discharge_rat。

(sunspec_business.c 内的 sunspec_active_power_dispatch_refresh 为 static,故意未在此暴露。)

4. 核心逻辑解析

本文件没有可执行逻辑,只有"接口契约",因此这里说明契约本身:

声明分组(第 16~31 行按职责分组排列)

参数约定

所有寄存器读写接口都以 (u16 sunspec_addr, u16 stru_size) 为参数,stru_size 即地址表长度 SUNSPEC_STRU_NUM(783),这个值不由本头文件固定,而是由调用方在 modbus.c 中以局部变量 l_u16_sunspec_stru_len = SUNSPEC_STRU_NUM 传入(modbus.c:8204、8258、8309)。这意味着表长一旦变更,调用方无需改动,但也意味着调用方传入错误的表长不会被类型系统拦住。

未涉及状态机、帧格式、定时器与 uCOS-II 同步原语——这些都在 .c 与 modbus.c 中。

5. 对外接口

本文件导出的内容

本文件调用的外部内容

6. 依赖关系

依赖

被依赖(包含本头文件的文件,共 8 处)

文件用途
midware/interface/modbus/sunspec_business.c:14自身实现
midware/interface/modbus/modbus.c:42从站读写与 Sunspec 使能/地址变更时的初始化
midware/interface/interface.c:29Modbus-RTU 任务:任务入口初始化 + 每帧后的数据刷新
logic/logic.c:28logic_read_mppt_percentage() 取 MPPT 百分比与调度使能
logic/ac_control.c:15充放电限幅、PV 关断/恢复的滞回控制
logic/dispatch.c:22仅 include,未实际调用(冗余依赖)
data/system_config/system_config.c:29Modbus 配置落盘后调用 sunspec_modbus_data_init()
net/server.c:57云端下发 SunspecEN 后调用 sunspec_modbus_data_init()

7. 备注与风险点

  1. 文件头注释块是模板复制产物(第 1~5 行):/* ... #include "sunspec_business.h" author : mike date : 2025/10/18 ... */ —— 多行注释里写了一行 #include 指令,本意应是描述"使用方式",实际把指令写进了注释。同目录的 sunspec_modbus.h 有完全一样的写法,属于复制头模板时未清理。不影响编译,但会误导阅读者。
  2. 头文件日期(2025/10/18)与同目录 sunspec_modbus.h(2025/09/26)不一致,且 sunspec_modbus.h 中的 E_SUNSPEC_NAME 注释写的是"时间:2026年5月7日"。日期信息相互矛盾,无法作为版本追溯依据。
  3. 头文件暴露了实现细节:本头文件直接 include sunspec_modbus.h,使所有包含者对 g_t_sunspec_mudbus[783](783 × SUNSPEC_MODBUS_T 的表)以及全部 Sunspec 业务全局变量拥有可见性。这打破了 sunspec_business.c 想隐藏 g_sunspec_comm、g_t_sunspec_inv_nameplate_array 的意图——任何调用方都能绕开封装函数直接改这些结构体字段,是并发一致性的隐患(Sunspec 数据在 Modbus 任务与逻辑任务间被无锁共享)。
  4. 接口缺少参数校验约定:sunspec_modbus_data_get/set 的 stru_size 由调用方传入,头文件未说明其取值必须等于地址表实际长度;传错表长会退化为错误区间上的二分查找,可能读/写到错误的地址项。
  5. 函数命名前缀不统一:sunspec_refresh_flag_set/get 少了 modbus 段,与其余 13 个 sunspec_modbus_* 不一致;sunspec_modbus_data_get/set 又是 _data_ 中缀。这是历史命名遗留,检索时容易漏(例如按 sunspec_modbus_* 通配搜不全)。
  6. 无版本/变更记录:头文件无 @version、无修改历史,author : mike 与空的 version 字段(在 .c 的文件头注释中)不能支撑变更追溯。