inovance_comm_usart.c
inovance_inverter_comm(),2571-2868 行)4.3 寄存器映射与参数换算4.4 运行数据解析与故障码翻译4.5 变化检测器(inovance_inverter_data_check(),2392-2564 行)4.6 黑匣子(故障录波)状态机(read_blackbox_handle(),3053-3196 行)4.7 澳洲 CEC 特殊处理4.8 与 uCOS-II 的协作方式5. 对外接口5.1 本文件导出的函数(声明于 inovance_comm_usart.h:775-781)5.2 本文件导出的全局变量5.3 本文件调用的外部函数/变量6. 依赖关系7. 备注与风险点源文件路径:
midware/inverter/inovance/inovance_comm_usart.c所属模块:midware/inverter/inovance(汇川 Inovance 逆变器通信协议) 代码行数:3229
1. 文件职责
本文件是汇川(Inovance)逆变器与 EMS 之间 SCI(RS485 串口,Modbus-RTU)通道 的 EMS 侧实现,与同目录 inovance_comm_can.c(CAN 私有协议通道)构成"双通道"分工:CAN 通道负责高频的有功/无功下发与实时运行数据接收,本文件负责设备识别、参数整定(安规参数整批下发与回读)、电池类型/加热、RTC 校准、启停机、软重启、能量统计、故障码解析,以及故障录波(黑匣子)数据回传。
数据流位置:向上从 g_t_inv_info(inverter.h 的逆变器总表,含 t_config_data/t_safty_info/t_run_info/t_control_cmd)、g_t_bat_info(BMS)、g_t_meter、g_t_logic_info 读取目标值与配置,向下经 usart2 硬件层把 Modbus-RTU 帧发到逆变器;反向把逆变器回读的安规参数、运行数据、故障/告警位写入 g_t_inv_info,并把故障录波写入 g_t_fault_scord_data(位于 SDRAM,供 net/ems.c 上报云端)。
被谁驱动:由 inverter.c:1045 的 uCOS-II 任务 task_inverter() 每个循环依次调用 inovance_inverter_comm()(inverter.c:1132)与 inovance_inverter_data_check()(inverter.c:1134)。初始化入口 inovance_comm_init() 在 inverter.c:102(机型识别后)、inovance_upgrade_init()(本文件 2306)和软重启流程(本文件 412)中被调用。
本文件不创建任务、不使用信号量或消息邮箱,全部以"轮询 + 事件标志位 + OSTimeGet() tick 时间戳 + OSTimeDlyHMSM() 阻塞延时"方式与 uCOS-II 协作。所有收发共用同一个串口 usart2 与同一个接收缓冲区 s_u8_inovance_recv_buf,是"单发单收、一问一答"的同步事务模型。
2. 关键数据结构与宏
2.1 本文件定义的全局对象
| 名称 | 类型 | 说明 |
|---|---|---|
g_t_inovance_comm_info | INOVANCE_TABLE_T(定义于 inovance_comm_usart.h:719) | 汇川 SCI/CAN 通信总表:事件标志、各周期 tick、故障/告警位域、运行信息、安规使能位域、待存盘标志 |
g_t_inovance_special_safety | INOVANCE_SPECIAL_SAFETY_TABLE_T(inovance_comm_usart.h:754) | 特殊安规暂存表:功率调节相关寄存器(0x1600 块)中无对应 EMS 字段的中间量 |
s_u8_inovance_recv_buf | static u8[512](本文件 32) | 全文件唯一的接收缓冲,长度由 INOVANCE_INV_RECV_BUFFER_SIZE 决定 |
2.2 本文件主要使用的宏
| 名称 | 类型 | 说明 |
|---|---|---|
INOVANCE_INV_DEBUG | 宏 | 本文件串口收发/解析调试打印总开关,inovance_comm_usart.h:17,默认 0 |
INOVANCE_SAFETY_DEBUG | 宏 | 安规参数下发/回读调试打印开关,inovance_comm_usart.h:18,默认 0 |
INOVANCE_SLAVE_ADDRESS = 0x01 | 宏 | 逆变器 Modbus 从站地址(inovance_comm_usart.h:40) |
INOVANCE_FUNC_READ_HOLDING_REGISTER = 0x03 | 宏 | 读保持寄存器功能码(:41) |
INOVANCE_FUNC_WRITE_SIGNAL_HOLDING_REGISTER = 0x06 | 宏 | 写单个保持寄存器功能码(:42) |
INOVANCE_FUNC_WRITE_MULTIPLE_HOLDING_REGISTER = 0x10 | 宏 | 写多个保持寄存器功能码(:43) |
INOVANCE_MAX_REGISTER_NUM = 100 | 宏 | 单次读写寄存器数量上限(:23),用作写帧合法性判据 |
INOVANCE_INV_RECV_BUFFER_SIZE = 512 | 宏 | 接收缓冲长度(:24) |
INOVANCE_DAT_PCK_INTERVAL_INV = 100 | 宏 | 两帧之间的最小间隔(ms),同时作为 usart2_send_data 的超时参数(:25) |
INOVANCE_EMS_INV_COMM_LOST_TIME = 30000 | 宏 | SCI 通讯丢失判据:距上次成功事务超过 30 s(:26) |
INOVANCE_INV_INIT_TIME = 2000 | 宏 | 上电初始化阶段查询设备信息的重试周期(:27) |
INOVANCE_BLACK_BOX_TIME = 4000 | 宏 | 黑匣子各查询步骤之间的等待时间(:28) |
INOVANCE_BLACK_BOX_POINTS_T = 320 | 宏 | 录波总点数(:30) |
INOVANCE_BLACK_BOX_POINTS_S = 4 | 宏 | 每帧返回的点数(:31) |
INOVANCE_BLACK_BOX_POINTS_NUM = 80 | 宏 | 录波帧数(80 × 4 = 320)(:32) |
INOVANCE_BLACK_BOX_DATA_OFFSET = 70 | 宏 | 黑匣子响应帧中每个录波点的字节步长(:33) |
MAX_REQUEST_NUM = 30 | 宏 | 黑匣子流程最大请求次数保护阈值(:34) |
TOTAL_CHANNELS_16 = 19 | 宏 | 录波 16 位通道数(:35) |
TOTAL_CHANNELS_32 = 8 | 宏 | 录波 32 位通道数(:36) |
S16_DATA_START_OFFSET = 5 / S32_DATA_START_OFFSET = 43 | 宏 | 录波点内 16/32 位数据起始偏移(:37-38)——定义了但代码中未使用,save_fault_scord() 仍写死 5 和 43 |
INOVANCE_BBOX_ADDR = 0xFE | 宏 | 黑匣子模块的 Modbus 从站地址(:144) |
FUNC_READ_BBOX = 0x03 / FUNC_READ_BBOX_INDEX = 0x06 / FUNC_READ_BBOX_DATA = 0x16 | 宏 | 黑匣子三个功能码(:145-147) |
INOVANCE_ADDR_REGISTER_* | 宏 | 逆变器保持寄存器地址表,共约 25 个块,见 inovance_comm_usart.h:45-122(详见 4.3 节映射表) |
INOVANCE_TYPE_T12/T15/T20/T20_OLD = 1/2/3/52 | 枚举值 | 机型编码(inovance_comm_usart.h:161),query_inv_device_info() 据此选择额定参数与 SUB_* 子机型 |
INOVANCE_OPERATE_NONE/STOP/START = 0/1/2 | 枚举值 | 启停操作码(inovance_comm_usart.h:171) |
INOVANCE_*_VAR_RESPONSE_MODE_E | 枚举 | 无功响应模式:0 无、1 固定功率因数、2 cosφ(p)、3 固定 Q、4 Q(U) 线性、5 Q(U) 滞环(inovance_comm_usart.h:149),query_inv_safety_reactive_power_data() 据此设置 safty_mode_u.BIT |
BLACKBOX_STATE_E | 枚举 | 黑匣子读取状态机(inovance_comm_usart.h:709):QUERY_BLACK_BOX / WAIT_DIRECTORY_UPLOAD / READ_DIRECTORY_CONTENT / SET_INDEX_NUM / WAIT_FAULTDATA_UPLOAD / READ_DIRECTORY |
INVERTER_TYPE = INVERTER_NULL | 宏 | 编译期机型选择(inverter.h:172),文件末尾黑匣子整段代码被 #if (INVERTER_TYPE == INOVANCE_TYPE) 包裹(2871、3197) |
2.3 位域联合体(故障/告警/标志)
| 名称 | 类型 | 说明 |
|---|---|---|
INOVANCE_ERROR1_U | 联合体 | 故障字 1(64 位),按 BYTE0~BYTE7 逐位命名(母线过压、PV 反接、IGBT 过温、GFCI、绝缘、EMS SCI/CAN 等),inovance_comm_usart.h:178 |
INOVANCE_ERROR2_U | 联合体 | 故障字 2,BYTE0~:电网过流、备电过压/欠压、PV 硬件过压、负载过流、各相零漂故障、加热相关故障;BYTE2 之后为未命名占位位(:275) |
INOVANCE_WARNING1_U | 联合体 | 告警字 1:电网过压/欠压/过频/欠频、电池开断、风扇故障、黑匣子 FLASH、RTC、孤岛、HVRT/LVRT、板温告警(:371) |
INOVANCE_WARNING2_U | 联合体 | 告警字 2,仅保留 word 视图,无逐位定义(:468) |
INOVANCE_SAFETY_FUNCTION_ENABLE_U | 联合体 | 安规功能使能位域(写入寄存器 0x1200/0x1201 两个 16 位字),含 u8_actpowet_control_enable、u8_slope_power_enable、u8_grid_volt_power_reduce_enable、u8_reactive_power_control_enable、u8_lvrt_enable、u8_hvrt_enable、u8_grid_volt_protect_enable、u8_island_detect_enable、u8_dci/iso/gfci_detect_enable 等(:482) |
INOVANCE_SCI_FLAG_U | 联合体 | 本文件的核心事件标志表(u64_sci_flag):BYTE0~BYTE2 为查询类标志(u8_query_*),BYTE5~BYTE7 为设置类标志(u8_set_*),另有 u8_check_inv_info_flag、u8_special_Australia_cec_flag(:579) |
INOVANCE_RUN_INFO_T | 结构体 | SCI 通道特有的运行信息(与 CAN 通道互补):机温 1~5、机型、额定电压频率、PV 总功率、u8_generator_mode、u8_mppt_scan_enable、u8_grid_forming_enable、u8_bat_type、u8_phase_adaptive_enable、加热使能/电压/电流/继电器状态、6 个 tmp 调试槽(:676) |
3. 函数清单
| 函数名 | 作用域 | 说明 |
|---|---|---|
inovance_write_data (72) | 全局 | 统一串口发送出口:保证两帧最小间隔 timeout ms,再 usart2_clear_buffer() + usart2_send_data() |
send_query_data_to_inovance (104) | static | 组读保持寄存器帧(0x03)并发送,8 字节固定长度 |
ems_send_ctrl_data_to_inovance (129) | static | 组写寄存器帧(0x10 多写 / 0x06 单写)并发送,带长度合法性校验 |
inovance_recv_data (169) | static | 从 usart2 异步缓冲读出整帧,校验 Modbus CRC、从站地址与功能码,失败置长度为 0 |
set_inv_rtc_calibration (227) | static | 用 SYSTEM_DATETIME 组 YYMM/DDHH/MMSS 三字写入 0x0500,成功后清 u8_set_inv_rtc_calibration_flag |
set_clear_energy (265) | static | 写 0x1000=1 清电量,成功后清 t_control_cmd.u8_clean_energy |
set_clear_fault (294) | static | 写 0x1001=1 清故障,成功后清 t_control_parameter.u8_clearing_fault |
inovance_set_inv_start_stop (323) | 全局 | 写 0x1002 启停命令;返回 TRUE 成功 / FALSE 应用层异常回复(长度 5) / 2 无回复(判定在 boot) |
inovance_set_inv_on_of (359) | 全局 | 写 0x1003 逆变器开关机命令,返回值语义同上 |
set_inv_dsp_restart (395) | static | 写 0x1004=1 软重启;成功后清 t_control_cmd.u8_reset 并重新执行 inovance_comm_init() + inovance_comm_init_can() |
set_inv_machine_mode (426) | static | 油机模式设置:先停机 → 延时 500 ms → 写 0x1005 → 延时 200 ms → 重启机 |
query_inv_machine_mode (460) | static | 读 0x1005 回填 t_run_info.u8_generator_mode |
set_inv_mppt_scan_status (487) | static | 写 0x1008 阴影扫描使能 |
query_inv_mppt_scan_enable (515) | static | 读 0x1008 回填 u8_mppt_scan_enable |
set_inv_grid_forming_enable (540) | static | grid-forming 设置:停机 → 延时 500 ms → 写 0x1009 → 延时 200 ms → 重启机 |
query_inv_grid_forming_enable (572) | static | 读 0x1009 回填 u8_grid_forming_enable |
set_inv_phase_adaptive_enable (597) | static | 写 0x100A 相序自适应使能,并置位回读标志 |
query_inv_phase_adaptive_enable (626) | static | 读 0x100A 回填 u8_phase_adaptive_enable |
inovance_set_bat_type (651) | static | 写 0x100B 电池串并类型(源 pvcharger_read_bat_series()) |
inovance_set_bat_heating_mode (715) | static | 连写 0x100F/0x1010/0x1011 三个寄存器:加热使能 / 加热电压(0.1 V) / 加热电流(0.01 A) |
query_inv_bat_heating_enable (752) | static | 读 0x100F~0x1011 三寄存器回填加热使能/电压/电流 |
inovance_set_bat_heaer_state (781) | static | 写 0x1012 电池加热膜接入状态(1 全部接入 / 2 全部切出) |
query_inv_bat_heater_state (812) | static | 读 0x1012 回填 u8_bat_heater_state |
set_inv_safety_function_enable (838) | static | 组 64 位安规功能使能位域(同步自 g_t_inovance_comm_info.u_safety_function_enable 后按 EMS 配置覆盖),写 0x1200 起 2 个寄存器 |
query_inv_safety_function_enable (902) | static | 读 0x1200 起 2 个寄存器,回写 u_safety_function_enable 并同步到 g_t_inv_info.t_safty_info / t_run_info |
set_inv_safety (945) | static | 写 0x1400 主安规编号(停机 → 写 → 延时 → 置位 8 个回读标志 → 重启机) |
set_inv_safesub (985) | static | 连写 0x1400/0x1401 主安规 + 子安规,并额外置位澳洲 CEC 特殊标志 |
set_inv_safety_voltage_protect (1029) | static | 组 18 个寄存器写 0x1402:首并网过/欠压过/欠频、OVP3/2/1(时间 ×10)、UVP2/1、10 min 过压 |
query_inv_safety_voltage_protect (1115) | static | 读 0x1402 起 18 个寄存器回填,时间字段 ÷10 还原 |
set_inv_safety_frequency_protect (1180) | static | 组 14 个寄存器写 0x1416:OFP3/2/1、UFP3/2/1(时间 ×10)与频率变化保护门限/时间 |
query_inv_safety_frequency_protect (1250) | static | 读 0x1416 起 14 个寄存器回填,频率变化时间 ÷1000 |
set_inv_safety_argument1 (1304) | static | 组 5 个寄存器写 0x1426:并网等待/重连时间、ISO 门限、DCI 门限与时间(×1000) |
query_inv_safety_argument1 (1346) | static | 读 0x1426 起 5 个寄存器回填,DCI 时间 ÷1000 |
set_inv_safety_argument2 (1381) | static | 组 8 个寄存器写 0x142D:GFCI 4 档门限、功率因数(×10)、固定无功(×2)、f2 门限、恢复斜率 |
query_inv_safety_argument2 (1431) | static | 读 0x142D 起 8 个寄存器回填,PF ÷10、固定 Q ÷2 |
set_inv_safety_argument3 (1471) | static | 组 12 个寄存器写 0x1013:恢复点、过频降额率(×8)、欠频模式、f2(减 1)、欠频降额率(×200)、恢复斜率、P-V 响应时间(×30)、有功斜率使能 |
query_inv_safety_argument3 (1533) | static | 读 0x1013 起 12 个寄存器回填,各比例因子反向还原 |
set_inv_safety_power_regulate_data (1582) | static | 组 8 个寄存器写 0x1600:调节率、反向机率、启动机率、P-V 降压使能、P-V 曲线 V3/V4(未映射字段走 g_t_inovance_special_safety) |
query_inv_safety_power_regulate_data (1637) | static | 读 0x1600 起 8 个寄存器回填 |
set_inv_safety_reactive_power_data (1682) | static | 组 17 个寄存器写 0x1700:无功模式、Q(U) 曲线 4 点、P-PF 曲线 4 点、PF5 等 |
query_inv_safety_reactive_power_data (1781) | static | 读 0x1700 起 17 个寄存器回填,并按模式值把 safty_mode_u.BIT 置一 |
inovance_parse_inv_err_msg (1863) | static | 把 u64_inv_fault1/2、u64_inv_warning1/2 的原始位域"多对一"翻译为 EMS 统一故障/告警位(g_t_inv_info.t_run_info.u_fault_code 等) |
query_inv_device_info (1986) | static | 读 0x0000 起 27 个寄存器:机型、SN、额定功率、软硬件版本;按机型写额定参数并置存盘标志 |
query_inv_energy_statistics (2094) | static | 读 0x010A 起 2 个寄存器,仅解析 PV 总发电量到 u32_energy_pv_input |
query_inv_running_data (2131) | static | 读 0x010C 起 66 个寄存器:机温、PV1~4、三相电网/备电电压电流、无功/视在功率、母线/电池、故障告警 8 个字;并驱动故障录波触发 |
inovance_upgrade_init (2304) | 全局 | 升级前初始化:inovance_comm_init() + inovance_comm_init_can(),清通信丢失标记,清零 PV 电压到运行模式之间的运行数据区 |
inovance_comm_init (2320) | 全局 | SCI 通道初始化:usart2_init(115200),置位全部首次查询/下发标志,同步安规主/子编号 |
inovance_special_Australia_cec (2357) | 全局 | AS4777_2(澳洲)特殊处理:强制有功控制使能、无功模式 4、恢复 UVP=2160、AUSTRALIA_C 的 OFP 恢复 5050、NEW_ZEALAND 的 10 min 过压 2580 |
inovance_inverter_data_check (2392) | 全局 | 变化检测器:比对安规编号、AC/DC 额定功率、相序自适应、grid-forming、油机模式、启停、开关机、MPPT、RTC、电池类型、电池加热/加热膜、频压曲线使能,按变化置对应下发标志;并触发配置存盘 |
inovance_inverter_comm (2571) | 全局 | 本文件主循环:升级分支 → 通讯丢失判定 → 初始化查询分支 → 按标志位顺序执行全部设置/查询 → 500 ms 运行数据、60 s 能量统计、24 h RTC 校准周期任务 |
send_command_to_blackbox (2878) | 全局 | 向黑匣子(从站 0xFE)发 6 字节命令 + CRC,共 8 字节 |
blackbox_recv_data (2903) | static | 黑匣子响应接收与校验(CRC + 地址 + 功能码),失败置长度 0 |
save_fault_scord_time_code (2961) | static | 解析录波目录帧:故障时间(YYMM/DDHH/MMSS)与故障字 1/2、告警字 1/2 写入 g_t_fault_scord_data |
save_fault_scord (3000) | static | 解析一帧 4 个录波点:19 个 16 位通道 + 8 个 32 位通道,写入 s16_channel/s32_channel 对应列 |
generate_random_digits (3034) | 全局 | 生成 8 位十进制随机字符串作为录波记录 ID(rand() % 10) |
read_blackbox_handle (3053) | 全局 | 黑匣子读取状态机主函数(停机 → 查目录 → 取目录内容 → 设索引 → 8 s → 逐帧读 80 包录波 → 生成 ID → 恢复运行) |
完整 56 个函数,无遗漏。文件顶部 37-64 行有一份前向声明列表,声明了其中 26 个 static 函数(含已注释掉的
query_inv_tmp_data)。另有inovance_get_self_test_data仅在头文件 782 行声明、全工程无定义。
4. 核心逻辑解析
4.1 传输层:Modbus-RTU 帧格式与收发事务
所有 SCI 通信都建立在 usart2(usart2_init(115200),见 2322 行)之上,采用标准 Modbus-RTU 帧,从站地址固定 0x01。
读请求帧(send_query_data_to_inovance(),104-121 行,固定 8 字节):
| 偏移 | 0 | 1 | 2-3 | 4-5 | 6 | 7 |
|---|---|---|---|---|---|---|
| 含义 | 从站地址 0x01 | 功能码 0x03 | 起始寄存器地址(大端) | 寄存器数量(大端) | CRC 低字节 | CRC 高字节 |
写多个寄存器帧(ems_send_ctrl_data_to_inovance(),142-149 行):
| 0 | 1 | 2-3 | 4-5 | 6 | 7 ~ 7+N-1 | 末尾 2 字节 |
|---|---|---|---|---|---|---|
| 0x01 | 0x10 | 起始地址 | 寄存器数 | 字节数 N | 数据域 | CRC 低/高 |
写单个寄存器帧(150-154 行):| 0x01 | 0x06 | 地址 | 数据(2B) | CRC |,共 8 字节。
写入前的合法性判据(140 行):register_num <= 100 && len_buff <= 200 && len_buff == register_num * 2,三者同时满足才组帧;否则 l_u8_len 保持 0,inovance_write_data(buf, 0, ...) 实际不会发出有效帧(发送长度 0)。CRC 由 GetCrcCode_Modbus() 计算,按"低字节在前、高字节在后"填入。
接收与校验(inovance_recv_data(),169-219 行):使用 usart2 的异步接收缓冲模型——先 usart2_is_recv_async_data() 判断有无数据,usart2_get_data_len() 取长度,再循环 usart2_read_data_async() 逐字节搬入 s_u8_inovance_recv_buf。校验三项全部通过才认为有效:
- CRC:接收帧末两字节(
buf[len-1]<<8 | buf[len-2])与GetCrcCode_Modbus(buf, len-2)相等; - 首字节等于
INOVANCE_SLAVE_ADDRESS; - 第二字节属于 0x03 / 0x06 / 0x10 之一。
任一项失败或不满足,则 *len = 0。注意:本层不做超时等待,也不重试——它只读取当前已经到达串口缓冲的数据。因此"超时重试"实际上由上层标志位机制实现:设置类函数只有在收到有效响应时才清除 u8_set_xxx_flag,否则该标志保持 TRUE,主循环下一轮会再次下发,形成无限重试。
帧间节流(inovance_write_data(),72-96 行):用静态 s_u32_send_pack_tick 记录上次发送时刻,若与当前 OSTimeGet() 之差小于 timeout(本文件统一传 INOVANCE_DAT_PCK_INTERVAL_INV = 100 ms),则 OSTimeDlyHMSM() 补足差额再发;同时该 timeout 也是 usart2_send_data() 的发送超时。这保证了"每 100 ms 最多一个事务"的节拍。
4.2 主循环与事件标志调度(inovance_inverter_comm(),2571-2868 行)
主循环不维护显式状态机,而是"标志位表驱动":所有行为由 g_t_inovance_comm_info.u64_sci_flag 的位决定是否执行。
if 固件升级完成/服务器已更新 (2575)
→ 一次性 inovance_upgrade_init(),置 u8_run_mode 为 cUpdateMaster/Slave/Arm,调用 inovance_upgrade_handle()
else
├─ if (OSTimeGet() - u32_ems_inv_comm_tick) > 30 s → 置 inverter_comm_lost_flag 并 inovance_comm_init() 重新初始化
├─ if u8_query_inv_device_info_flag == TRUE ← 初始化阶段
│ u8_check_inv_info_flag = FALSE(暂停其他检测)
│ 每 2 s 查询一次 query_inv_device_info(),直到成功(成功后该标志被清)
└─ else ← 正常运行阶段
u8_check_inv_info_flag = TRUE(允许数据检测器工作)
按固定顺序执行 30+ 个 "if(标志) 执行对应函数"
+ 时间驱动:500 ms 运行数据 / 60 s 能量统计 / 24 h RTC 校准
执行顺序(2627-2865 行):安规主/子编号 → 清电量 → 清故障 → DSP 软重启 → 查询油机模式 → MPPT 回读 → grid-forming 回读/下发 → 相序自适应回读/下发 → 油机模式下发 → RTC 校准 → 启停 → 开关机 → MPPT 下发 → 安规功能使能下发/回读 → 电压保护下发/回读 → 频率保护下发/回读 → 参数 1/2/3 下发/回读 → 功率调节下发/回读 → 无功下发/回读 → 电池类型 → 故障录波 → 电池加热下发/回读 → 加热膜状态下发/回读。
设置-回读闭环:几乎所有 set_* 函数在收到有效响应后除了清自己的 u8_set_*_flag,还会把对应的 u8_query_*_flag 置 TRUE(如 878、1081、1221、1410、1508 行等),下一轮主循环再把参数读回写入 g_t_inv_info.t_safty_info,实现"下发 → 逆变器确认 → EMS 侧数据与实际一致"的闭环。set_inv_safety()(945)和 set_inv_safesub()(985)在收到响应后一次性置位 8 个回读标志(963-970、1005-1012 行)。
停机后改参数:set_inv_safety()、set_inv_safesub()、set_inv_machine_mode()、set_inv_grid_forming_enable() 都采用"先 inovance_set_inv_start_stop(INOVANCE_OPERATE_STOP) → OSTimeDlyHMSM(0,0,0,500) → 写寄存器 → 延时 200 ms → 重新启动"的模式(953-972、995-1015、434-446、548-558 行),因为这些参数只能在停机状态下生效。
时间戳/tick 一览:
| 字段 | 更新时机 | 用途 |
|---|---|---|
u32_ems_inv_comm_tick | 每次收到有效响应 | 通讯在线判据(> 30 s 判丢失) |
u32_query_inv_device_info_tick | 每次执行设备信息查询 | 初始化阶段 2 s 节流 |
u32_query_inv_running_data_tick | 每次执行运行数据查询 | 500 ms 节流(2818) |
u32_query_inv_energy_statistics_tick | 每次执行能量统计查询 | 60 s 节流(2829) |
u32_set_inv_rtc_calibration_tick | 初始化与每次校准 | 24 h 节流(2852),另在 RTC 故障恢复时归零(2497) |
每个节流点都附带 else if (tick > OSTimeGet()) 的回绕保护(2604、2618、2823、2835、2857 行):一旦发现记录的 tick 大于当前 tick(说明系统 tick 计数器回绕),立即把记录值重置为当前值,避免长期不再触发。
4.3 寄存器映射与参数换算
| 寄存器 | 宏 | 数量 | 方向 | 内容与换算 |
|---|---|---|---|---|
| 0x0000 | QUERY_INV_DEVICE_INFO | 27 | 读 | 机型(1)、SN(16 B)、额定功率、HW/MASTER/ARM/SLAVE 版本;snprintf 组装 V%d.%d.%d.%d |
| 0x010A | QUERY_INV_ENERGY_STATISTICS | 2 | 读 | 仅取前 4 字节为 PV 总发电量(大端 u32) |
| 0x010C | QUERY_INV_RUNNING_DATA | 66 | 读 | 见 4.5 节偏移表 |
| 0x0500 | SET_INV_RTC_CALIBRATION | 3 | 写 | YYMM、DDHH、MMSS 各占一寄存器(十进制打包,如 2025 年 7 月 → 2507) |
| 0x1000 | SET_INV_CLEAR_ENERGY | 1 | 写 | 写 1 清电量 |
| 0x1001 | SET_INV_CLEAR_FAULT | 1 | 写 | 写 1 清故障 |
| 0x1002 | SET_INV_START_STOP | 1 | 写 | 1 停机 / 2 开机 |
| 0x1003 | SET_INV_ON_OFF | 1 | 写 | 逆变器开关机 |
| 0x1004 | SET_INV_SOFT_RESTART | 1 | 写 | 写 1 软重启 |
| 0x1005 | SET_INV_MACHINE_MODE | 1 | 读写 | 油机模式:1 关 / 2 开 |
| 0x1008 | SET_INV_MPPT_SCAN_ENABLE | 1 | 读写 | 阴影扫描:1 关 / 2 开 |
| 0x1009 | SET_INV_GRID_FORMING_ENABLE | 1 | 读写 | grid-forming:1 关 / 2 开 |
| 0x100A | SET_INV_GRID_ADAPTIVE_ENABLE | 1 | 读写 | 相序自适应:1 关 / 2 开 |
| 0x100B | SET_INV_BAT_TYPE | 1 | 写 | 电池串并类型 |
| 0x100F~0x1011 | SET_INV_BAT_HEATING | 3 | 读写 | 加热使能(0/1/2)、电压 0.1 V、电流 0.01 A |
| 0x1012 | SET_INV_BAT_HEATER_STATE | 1 | 读写 | 加热膜 1 全部接入 / 2 全部切出 |
| 0x1013 | SET_INV_SAFETY_ARGUMENT3 | 12 | 读写 | 见 4.4 节换算表 |
| 0x1200/0x1201 | SET_INV_SAFETY_PROTECT_ARG1 | 2 | 读写 | 安规功能使能 64 位位域的低 32 位 |
| 0x1400/0x1401 | SET_INV_SAFETY | 1 或 2 | 写 | 主安规编号(+ 子安规编号) |
| 0x1402 | SET_INV_SAFETY_VOLTAGE_PROTECT | 18 | 读写 | 电压/频率保护点 |
| 0x1416 | SET_INV_SAFETY_FREQUENCY_PROTECT | 14 | 读写 | 频率保护点 |
| 0x1426 | SET_INV_SAFETY_ARGUMENT1 | 5 | 读写 | 并网等待/重连、ISO、DCI |
| 0x142D | SET_INV_SAFETY_ARGUMENT2 | 8 | 读写 | GFCI、PF、固定 Q |
| 0x1600 | SET_INV_SAFETY_POWER_REGULATE | 8 | 读写 | 有功调节率与 P-V 曲线 |
| 0x1700 | SET_INV_SAFETY_REACTIVE_POWER | 17 | 读写 | 无功 Q(U)/P-PF 曲线 |
关键换算(下发 ×,回读 ÷,二者严格互逆):
| 字段 | 下发 | 回读 |
|---|---|---|
| OVP2/3 时间、UVP1/2/3 时间 | ×10(1045-1068) | ÷10(1131-1143) |
| 频率保护 OFP/UFP 时间 | ×10(1187-1208) | ÷10(1262-1272) |
| 频率变化保护时间 | 原值直传(1211-1212) | ÷1000(1274) |
| DCI 保护时间 | ×1000(1317-1318) | ÷1000(1361) |
功率因数 s8_set_power_factor | ×10(1394) | ÷10(1446) |
固定无功 s16_set_fix_reactive_power | ×2(1396) | ÷2(1447) |
| 过频降额率 | ×8(1484) | ÷8(1548) |
| 欠频 f2 门限 | -1(1490) | +1(1551) |
| 欠频降额率 | ×200(1492) | ÷200(1552) |
| P-V 响应时间 | ×30(1496) | ÷30(1554) |
| Q-V 响应时间 | ×300(1698) | ÷300(1811) |
| P-PF 模式 P2 | ×10(1719) | ÷10(1822) |
| PF5 | ×10(1731) | ÷10(1829) |
4.4 运行数据解析与故障码翻译
query_inv_running_data()(2131-2295 行)按固定字节偏移解析 66 个寄存器(132 字节)的响应。响应帧结构为 [addr][func][byteCount][data...][crc][crc],因此数据起始偏移为 3。主要偏移:
| 偏移 | 长度 | 内容 |
|---|---|---|
| 3-12 | 10 B | 机温 1~5(s16),并由机温 1 ÷10 得 t_run_info.s8_machine_temp |
| 13-14 | 1 寄存器 | 当前安规编号 t_safty_info.u8_safety |
| 17-40 | 24 B | PV1~PV4 电压/电流/功率 |
| 43-52 | 6 B | 三相电网电流(电压字段被注释,因与 CAN 帧重复,见 2143 行注释) |
| 53-64 | 12 B | 三相备电电压/电流 |
| 65-76 | 12 B | 三相无功、三相视在功率(并求和得总量,2179、2183 行) |
| 77-86 | 10 B | 运行功率因数、母线电压、电池电压/电流 |
| 87-118 | 32 B | 故障字 1、故障字 2、告警字 1、告警字 2(各 4 个 16 位字) |
| 131-132 | 1 寄存器 | 子安规编号 u8_safesub |
解析完成后:
- 调用
inovance_parse_inv_err_msg()(1863-1978 行)把原始位域"多对一"映射为 EMS 统一故障码——例如 PV1~PV4 反接合并为u8_pv_reverse、四个过温位合并为u8_over_temperature、逆变器零漂与三相电网/负载零漂共 7 个位合并为u8_inv_zero_drift_fault、四个风扇故障合并为u8_fan_abnormal_alarm(1874-1886、1892-1895、1909-1915、1964-1967 行)。映射为单向:EMS 统一码不会反向写回逆变器原始位。 - 非 AS4777_2 时强制
u8_safesub = SAFESUB_DEFAULT(2211-2214 行)。 - 若读回的安规/子安规编号与
t_config_data不一致,则回写配置并置u8_save_config_flag(2216-2222 行)。 - 故障录波触发:用两个
static u64缓存上一拍的故障字 1/2,一旦发生变化且新值非 0,就置位u8_query_fault_record_flag(2224-2241 行)——即"只在新故障出现时触发录波,故障消失不触发"。原 2235-2240 行"故障清 0 后自动重启机"的逻辑已被注释掉。
4.5 变化检测器(inovance_inverter_data_check(),2392-2564 行)
该函数是"EMS 配置 ↔ 逆变器状态"的差异比较器,运行在主循环的 u8_check_inv_info_flag == TRUE 阶段(即设备信息查询完成之后,2409-2412 行提前返回)。它把"EMS 期望值"与"逆变器当前已知值"比较,不等则更新本地缓存并置对应下发标志:
| 检测项 | 期望值来源 | 目标值/使能值编码 | 触发标志 |
|---|---|---|---|
| 安规编号 | t_config_data.u8_safety/u8_safesub | 直传 | u8_set_inv_safety_flag 或 u8_set_inv_safesub_flag(非 AS4777_2 走前者,2417-2424) |
| AC/DC 额定充放电功率 | t_run_info.u32_*_rate_* | 直传 | u8_save_config_flag(2428-2442) |
| 相序自适应 | t_config_data.u8_phase_negation_en | TRUE→2,FALSE→1 | u8_set_phase_adaptive_enable_flag(2445-2450) |
| grid-forming | g_t_meter.t_config_data.u8_gridforming_en | TRUE→2,FALSE→1 | u8_set_grid_forming_enable_flag(2453-2458) |
| 油机模式 | g_t_logic_info.u8_generator_on | TRUE→2,FALSE→1 | u8_set_inv_machine_mode(2461-2466) |
| 启停 | t_control_cmd.u8_start_stop | 直传 | u8_set_inv_start_stop_flag(2469-2473) |
| 开关机 | t_run_info.u8_set_inv_on_off | 直传 | u8_set_inv_on_off_flag(2475-2479) |
| MPPT 阴影扫描 | t_config_data.u8_inv_mpptscan_enable | TRUE→2,FALSE→1 | u8_set_mppt_scan_enable_flag(2483-2488) |
| RTC 故障恢复 | u64_inv_warning1.bit.u8_rtc_fault 由 1→0 | — | u8_set_inv_rtc_calibration_flag 并把 24 h 计数归零(2491-2501) |
| 电池类型 | pvcharger_read_bat_model() | 直传 | u8_set_bat_type_flag(2504-2508) |
| 电池加热 | g_t_bat_info.t_run_info.u8_inv_heat_cmd | TRUE→2,FALSE→1 | u8_set_bat_heating_mode_flag(2516-2525) |
| 加热膜状态 | g_t_bat_info.t_run_info.u8_heat_relay_sta | TRUE→1,FALSE→2 | u8_set_bat_heater_state_flag(2527-2533) |
| 频压曲线使能 | parallel_read_freq_dispatch_en() | 并机调频时强制 FALSE,否则 TRUE | u8_set_inv_safety_function_flag + u8_set_inv_safety_argument3_flag(2536-2563) |
存盘:u8_save_config_flag == TRUE 时清标志并 save_job_post(INVERTER_CONFIG_PAGE)(2510-2514 行),即把配置写入掉电保持区。
4.6 黑匣子(故障录波)状态机(read_blackbox_handle(),3053-3196 行)
整段代码由 #if (INVERTER_TYPE == INOVANCE_TYPE) 包裹(2871、3197 行),默认编译配置 INVERTER_TYPE == INVERTER_NULL(inverter.h:172)时不参与编译。
通信协议(黑匣子从站地址 0xFE,帧尾同样为 Modbus CRC 低/高字节,命令帧共 8 字节):
| 命令 | 内容 | 用途 |
|---|---|---|
read_blackbox | FE 03 14 1F 00 01 | 触发黑匣子生成本次故障录波 |
read_catalog_set | FE 06 14 3C 00 51 | 设置/读取目录指针 |
read_catalog_data | FE 16 00 01 00 01 | 读取目录内容(含故障时间与故障/告警字) |
read_rundata_index | FE 06 14 1E 00 01 | 设置录波数据索引 |
read_rundata_set | FE 06 14 3C 00 41 | 设置录波数据读取模式 |
read_rundata_data | FE 16 00 02 00 01 | 读取一帧录波数据,每次发送前把第 5 字节 +1 递增(3159 行) |
状态迁移(BLACKBOX_STATE_E s_e_blackbox_read_status,静态变量):
QUERY_BLACK_BOX ──收到响应且 buf[5]!=0──> WAIT_DIRECTORY_UPLOAD
↑ │ (等待 4 s)
│ ↓
│ READ_DIRECTORY_CONTENT ──收到响应──> SET_INDEX_NUM
│ │ 失败 │ 收到响应
│ └──────────────┐ ↓
│ │ WAIT_FAULTDATA_UPLOAD
│ │ │ 收到响应
│ │ ↓
│ │ READ_DIRECTORY
│ │ │ 循环 80 帧
└───────────────────────────────────────────────────────┴──────────────┘
(任一环节无响应/校验失败即回到 QUERY_BLACK_BOX)
进入 QUERY_BLACK_BOX 时先 inovance_set_inv_start_stop(INOVANCE_OPERATE_STOP) 停机并 OSTimeDlyHMSM(0,0,0,500),再 fault_scord_init() 初始化录波缓冲;READ_DIRECTORY 完成 80 帧后 generate_random_digits() 生成 8 位记录 ID 写入 g_t_fault_scord_data.record_id,set_fault_scord_status() 置上报状态,延时 200 ms 后重新开机,清 u8_query_fault_record_flag。
超时保护:s_u8_requst_num 在每次函数调用末尾自增,累加超过 MAX_REQUEST_NUM(30)即强制回 QUERY_BLACK_BOX、清录波标志、开机(3185-3195 行),避免通讯异常时永久卡死。
录波点解析(save_fault_scord(),3000-3026 行):一帧含 4 个点(INOVANCE_BLACK_BOX_POINTS_S),点号基址 u16_point_num = frame_num * 4,点内字节步长 INOVANCE_BLACK_BOX_DATA_OFFSET = 70:
- 16 位通道
ch= 0..18:取data_ptr[5 + ch*2] << 8 | data_ptr[6 + ch*2],写入g_t_fault_scord_data.s16_channel[ch][u16_point_num + i]; - 32 位通道
ch= 0..7:取data_ptr[43 + ch*4 .. 46 + ch*4]四字节大端拼接,写入s32_channel[ch][u16_point_num + i]。
g_t_fault_scord_data 类型为 FAULT_SCORD_T(net/ems.h:454-456):s16_channel[19][320] + s32_channel[8][320],共 320 个点,与"80 帧 × 4 点 = 320"一致,下标不会越界。目录帧解析(save_fault_scord_time_code(),2961-2991 行)从偏移 6 开始取 YYMM/DDHH/MMSS,再取故障字 1 的 4 个字、故障字 2 的第 1 个字、告警字 1 的前 2 个字(其余字段已注释)。
4.7 澳洲 CEC 特殊处理
inovance_special_Australia_cec()(2357-2385 行)由标志 u8_special_Australia_cec_flag 触发(该标志在 set_inv_safesub() 成功后置位,1013 行)。当 t_safty_info.u8_safety == AS4777_2 时:
- 强制
t_config_data.u8_actpowet_control_enable = TRUE,置无功模式safty_mode_u.u16_value = 4(Q(U) 线性),置位无功下发标志与安规功能使能标志; - 强制
u16_uvp_restore = 2160(即 216.0 V),置位参数 3 下发标志; - 若子安规为
AUSTRALIA_C,强制u16_ofp_restore = 5050(50.50 Hz); - 若子安规为
NEW_ZEALAND,强制u16_ovp10min_value = 2580(258.0 V)并置位电压保护下发标志。
4.8 与 uCOS-II 的协作方式
- 不使用信号量/邮箱/事件标志组;跨任务数据交换完全依赖
g_t_inovance_comm_info、g_t_inv_info等全局结构体的标志位段。 - 阻塞点:
inovance_write_data()内的帧间隔延时(最多 100 ms)、set_inv_*中的 500/200 ms 停机-改参-开机延时、黑匣子流程中的 500/200 ms 以及READ_DIRECTORY内 80 次逐帧读取(每次经inovance_write_data至少间隔 100 ms)。这些都在task_inverter任务上下文里同步阻塞。 - 软件延时不能挂起调度器之外的东西,但由于
OSTimeDlyHMSM会让出 CPU,其他任务仍可运行。
5. 对外接口
5.1 本文件导出的函数(声明于 inovance_comm_usart.h:775-781)
| 导出函数 | 调用方 |
|---|---|
inovance_write_data | 本文件内部;inovance_upgrade.c(升级握手帧复用同一串口出口) |
inovance_set_inv_start_stop | 本文件黑匣子流程、inovance_upgrade.c:486(升级前停机)、inovance_upgrade.c:828(升级后开机) |
inovance_set_inv_on_of | 本文件主循环(2699) |
inovance_inverter_comm | inverter.c:1132(task_inverter) |
inovance_inverter_data_check | inverter.c:1134 |
inovance_comm_init | inverter.c:102、本文件 412(软重启)、2306(升级初始化) |
inovance_upgrade_init | 本文件 2580(升级开始) |
inovance_special_Australia_cec | 本文件主循环(2864) |
read_blackbox_handle | 本文件主循环(2794) |
send_command_to_blackbox | 本文件黑匣子流程(6 处) |
generate_random_digits | 本文件黑匣子流程(3171) |
5.2 本文件导出的全局变量
| 变量 | 声明位置 | 外部使用者 |
|---|---|---|
g_t_inovance_comm_info | inovance_comm_usart.h:772 | inovance_comm_can.c(CAN 通道共用标志与 u16_inv_type)、inverter.c 等 |
g_t_inovance_special_safety | inovance_comm_usart.h:773 | 目前仅本文件内部使用 |
5.3 本文件调用的外部函数/变量
| 来源模块 | 使用内容 |
|---|---|
hardware/usart2/usart2.h | usart2_init、usart2_clear_buffer、usart2_send_data、usart2_read_data_async、usart2_get_data_len、usart2_is_recv_async_data |
common/crc.h | GetCrcCode_Modbus |
inverter.h | g_t_inv_info(t_run_info / t_config_data / t_safty_info / t_control_cmd / t_control_parameter)、INVERTER_CONTROL_CMD_TABLE_T、SUB_T12/T15/T20/NULL、SAFESUB_DEFAULT、AS4777_2、AUSTRALIA_C、NEW_ZEALAND、INV_STARTUP、cUpdateMaster/Slave/Arm |
inovance_comm_can.h | inovance_comm_init_can |
inovance_upgrade.h | inovance_read_upgrade_flag_master/slave/fpga、inovance_upgrade_handle |
logic.h | g_t_logic_info.u8_generator_on |
system_config.h | SYSTEM_DATETIME(RTC 时间)、save_job_post(INVERTER_CONFIG_PAGE) |
ems.h | Set_Setup_Config_Status、g_t_fault_scord_data、fault_scord_init、set_fault_scord_status、FAULT_SCORD_T |
inv_download.h | is_inverter_firm_download_finished |
upd_download.h | Get_Status_Is_Updated_From_Server(UPDT_INV3) |
meter.h | g_t_meter.t_config_data.u8_gridforming_en |
pvcharger.h | pvcharger_read_bat_series、pvcharger_read_bat_model |
parallel.h | parallel_read_freq_dispatch_en |
bms.h | g_t_bat_info.t_run_info(u8_inv_heat_cmd、u16_heat_volt、u16_heat_current、u8_heat_relay_sta) |
generator.h / pcf8563.h | 随 includes.h 引入,本文件未直接调用其符号 |
| Keil C 库 | memcpy、memcmp、memset、snprintf、printf、abs、rand、size_t |
6. 依赖关系
依赖(本文件 include / 使用)
- 直接 include:
inverter.h、inovance_comm_usart.h、inovance_comm_can.h、usart2.h、logic.h、system_config.h、ems.h、inv_download.h、crc.h、meter.h、pcf8563.h、generator.h、bms.h(第 13-25 行)。 - 间接依赖:
includes.h(基础类型u8/u16/u32/s16/s32/u64与 uCOS-II API)、upd_download.h、parallel.h、pvcharger.h、inovance_upgrade.h(经头文件引入)。
被依赖(谁会用到它)
midware/inverter/inverter.c:调用inovance_comm_init()(102)、inovance_inverter_comm()(1132)、inovance_inverter_data_check()(1134)。midware/inverter/inovance/inovance_comm_can.c:共用g_t_inovance_comm_info中的u16_inv_type等字段与头文件宏。midware/inverter/inovance/inovance_upgrade.c:调用inovance_set_inv_start_stop()与inovance_write_data()。net/ems.c:消费本文件填充的g_t_fault_scord_data(录波上报,ems.c:4244起)。
7. 备注与风险点
- 写帧缓冲区存在溢出隐患。
ems_send_ctrl_data_to_inovance()使用u8 l_u8_tx_buf[128](131 行),而合法性判据允许register_num最大 100、len_buff最大 200(140 行)。当register_num = 100时l_u8_len = 7 + 200 = 207,memcpy(l_u8_tx_buf + 7, tx_buff, 200)会越界约 79 字节,覆盖栈上其他局部变量。当前所有调用点最大只用 18 个寄存器(l_u8_len= 43),所以尚未触发,但该函数是 public static 风格的通用组帧工具,接口本身不安全。 - 文件头注释与实际文件名/内容不一致。第 2 行
@file :inovance_comm.c,实际文件名为inovance_comm_usart.c;且注释仍保留 2017 年的初版信息。 S16_DATA_START_OFFSET/S32_DATA_START_OFFSET定义了但从未使用(inovance_comm_usart.h:37-38)。save_fault_scord()的 3009/3017 行仍硬编码偏移5和43,注释里也写着"原硬编码5/43"——常量集中化的重构只做了一半,后续若表结构变化容易改漏。- 录波点字节步长与通道数据极可能重叠。
INOVANCE_BLACK_BOX_DATA_OFFSET= 70,而 32 位通道取的最后一个字节是data_ptr[46 + 7*4] = data_ptr[74],已越过 70 字节的步长边界,会读到下一个点的数据。需要与汇川黑匣子协议文档核对:要么步长应为 ≥ 75,要么 32 位通道实际只有部分有效。 blackbox_recv_data()的功能码校验形同虚设(2936-2939 行):判据写成buf[1] == command[1] || buf[1] == command[2] || buf[1] == command[3],而command[2]/[3]是命令帧的数据字节(如 0x14、0x1F、0x3C),不是功能码。这使校验失去意义,理论上可能把不相关帧当作有效响应。read_blackbox_handle()在任务上下文长时间阻塞。READ_DIRECTORY分支(3151-3179)在单次调用内循环 80 次收发,每次受inovance_write_data()的 100 ms 帧间隔约束,累计约 8 s,期间task_inverter无法处理其他逆变器事务;函数头部还有 500 ms 停机延时。整体流程会让逆变器通信停滞十余秒。s_u8_requst_num的计数语义可疑(3066、3185-3195 行)。它在每次函数调用结束时都自增,只在READ_DIRECTORY成功完成时被清零;而MAX_REQUEST_NUM的判定被放在switch之后、对所有状态生效。这意味着进入黑匣子流程后,只要 30 次调用内没走完整个状态机(正常流程需要 4 次 4 s 等待 + 80 帧读取,远超 30 次调用),就会被强制中断退出。read_blackbox_handle()中time_delay变量几乎无用(3065 行):QUERY_BLACK_BOX分支给它赋值(3082),但后续所有等待判据用的是s_u32_time_delay,属于遗留/冗余变量。generate_random_digits()的随机性不可靠(3034-3046 行)。使用rand()但全文件未见srand()调用,若启动时未播种,每次上电会生成同一序列,8 位"故障识别码"可能重复,削弱"同一故障录波数据一致"的设计意图。set_inv_safety_function_enable()与query_inv_safety_function_enable()中残留无条件printf(881-891、932-934 行)。文件头定义INOVANCE_SAFETY_DEBUG期望用宏开关控制打印,但这两处的#if/#endif已被注释掉,导致每次下发/回读安规功能使能都会向串口输出十几行调试信息,与"调试宏默认关闭"的意图相悖。set_inv_safety_voltage_protect()的收发字段长度不自洽(1029-1074 行)。代码只填充了l_u8_tx_buf[0..33](含两行被注释的 34/35),但调用时声明寄存器数 18、长度 36,l_u8_tx_buf[34]/[35]未赋值即随帧发出(栈上残留值)。同时 1057-1064 行把u16_uvp2_value/time连续写了两遍,u16_uvp3_value/u16_uvp3_time(g_t_inv_info中存在该字段)的下发被漏掉,而回读侧(1138-1139)却会解析 UVP3,形成"下发不含 UVP3、回读含 UVP3"的不对称。query_inv_device_info()的 AC 功率字段解析明显可疑(2009-2010 行):u32_ac_rate_charge_power与u32_ac_rate_discharge_power取自完全相同的两个字节[37]/[38],两者恒等。而inovance_inverter_data_check()又用"AC 额定充放电功率是否变化"判定配置存盘(2428-2442),此处赋值错误可能掩盖放电功率的变化检测。u8_generator_mode被当作 u16 使用(431-432、546-547、602-603、786-787 等行)。INOVANCE_RUN_INFO_T.u8_generator_mode声明为u8,但代码一律按>> 8/& 0xFF的两字节大端方式组帧,高位恒为 0;读回时(470 行)又按两字节拼回u8,属于命名与用法不一致的遗留写法,本身不致命但容易误读。u16_inv_type(u16)与INOVANCE_TYPE_E枚举值比较(2014-2036 行)依赖隐式类型提升,且SUB_NULL分支把最大充放电电流置 0(2042-2044),若读到未知机型会直接让 EMS 侧限流为 0。属预期降级行为,但值得在机型兼容性变更时复核。inovance_write_data()的abs()节流对 tick 回绕处理不完整(77-81 行)。abs(OSTimeGet() - s_u32_send_pack_tick)在 uCOS-II tick 回绕(OSTime为 32 位、每 tick 1 ms 时约 49.7 天)瞬间会产生巨大差值,可能跳过或错误插入延时。相比之下主循环中的节流点都有专门的else if (tick > OSTimeGet())回绕保护分支,此处没有。inovance_get_self_test_data声明无定义(inovance_comm_usart.h:782)。全工程仅此一处出现,属于残留接口声明,链接不会报错(无人调用),但会误导后续开发者。- 大量寄存器宏已无引用:
INOVANCE_ADDR_REGISTER_SET_INV_WEAK_POWER_GRID(0x100C)、SET_INV_BAT_AWAKE(0x1007)、SET_INV_PARALLEL_MODE(0x1006)、SET_INV_ZERO_DRIFT(0x100D)、SET_INV_EMS_RAMP_STATE(0x101E)、QUERY_INV_ERROR_MSG(0x0136)、QUERY_INV_PARALLEL_RUNNING_DATA(0x0400)、EMS_INV_ID_CODE("ALPHAESS") 在本文件均无使用(SET_INV_ZERO_DRIFT仅出现在被注释的inovance_zero_drift_type()中,685-705 行)。另外INOVANCE_WARNING2_U无逐位定义、INOVANCE_ERROR2_U的bit20~bit63为未命名占位,说明协议表尚未完整建模。 - 故障录波相关代码在默认编译配置下完全不生效。文件末尾黑匣子整段(2871-3197)及主循环调用点(2791-2796)均被
#if (INVERTER_TYPE == INOVANCE_TYPE)包裹,而inverter.h:172中INVERTER_TYPE默认为INVERTER_NULL。因此该功能只在显式选择汇川机型编译时才存在,阅读时勿按"已生效"理解。 save_fault_scord()内有无条件printf(3014 行),每次解析一点都打印一行;80 帧 × 4 点 = 320 行日志,且不受INOVANCE_INV_DEBUG控制,会显著拖慢录波流程。