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

afci_comm.h

源文件路径:midware/afci/afci_comm.h 所属模块:midware / afci(电弧故障断路器 AFCI 通信与日志) 代码行数:110

1. 文件职责

本头文件是 AFCI 常规通信模块的对外契约:它声明了 AFCI 的从站地址、全部寄存器地址/数量常量、3 个业务状态枚举、日志上传状态块 AFCI_LOG_DATA_TABLE、该状态块的全局实例 g_t_afci_log_tab,以及 afci_comm.c 对外暴露的 13 个函数原型。

它同时充当模块间的常量共享中心:VERSION_AFCI_HARD / AFCI_TYPE_BYTE_WATT_* 被 net/afci_download.c 用于机型与硬版本上报,DEBUG_ALPHAESS_AFCI 还被 alphaess_comm_usart.c 当作 AFCI 分支的调试开关使用。

文件本身不含任何可执行代码,唯一被 include 的依赖是工程总头 includes.h。

2. 关键数据结构与宏

名称类型说明
__AFCI_COMM_H__宏:9-10。包含守卫
DEBUG_ALPHAESS_AFCI宏:16,值 0。AFCI 全链路调试打印总开关(本文件与 alphaess_comm_usart.c:403-425 都在用);置 1 会打开大量 printf
VERSION_AFCI_HARD宏:18,值 "V1.0"。AFCI 硬件版本号,被 net/afci_download.c:112 get_afci_hard_version() 直接返回并上报云端;改硬件需手工同步
AFCI_TYPE_BYTE_WATT_S宏:19,值 "BYTE_AFCI_S"(贝瓦单相机型串)
AFCI_TYPE_BYTE_WATT_T宏:20,值 "BYTE_AFCI_T"(贝瓦三相机型串)
AFCI_SLAVR_ADDRESS宏:22,值 0x01。AFCI 从站地址。与逆变器从站地址 ALPHAESS_SLAVR_ADDRESS(0x03)、升级地址 AFCI_UPGRADE_ADDRESS(0xF8) 共同构成 USART2 上的三路寻址
SELF_CHECK_CHANNEL宏:23,值 0x3F。自检通道使能位图(6 位全开)
AFCI_ADDR_REG_WARNING_MESSAGE / AFCI_NUM_WARNING_MESSAGE宏:25-26。寄存器 0x0002,长度 1。告警/自检结果基准寄存器
AFCI_ADDR_REG_QUERY_SOFT_VERSION2 / AFCI_NUM_QUERY_SOFT_VERSION2宏:28-29。寄存器 0x0010,长度 11(=22 字节)软版本区
AFCI_ADDR_REG_SELF_CHECK_FUNCTION_ENABLE / AFCI_NUM_SELF_CHECK_FUNCTION_ENABLE宏:31-32。寄存器 0x0024,长度 1。写 = 使能自检,读 = 回读状态
AFCI_ADDR_REG_SET_SOFT_REBOOT / ALPHAESS_NUM_SET_SOFT_REBOOT宏:34-35。寄存器 0x0025,长度 1(第二个宏前缀为 ALPHAESS_,命名不一致)
AFCI_ADDR_REG_SEND_FAC_MODE_CMD / AFCI_NUM_SEND_FAC_MODE_CMD宏:37-38。寄存器 0x0026,长度 1。工厂模式开关
AFCI_ADDR_REG_SEND_CLEAR_INFO_CMD / AFCI_NUM_SEND_CLEAR_INFO_CMD宏:40-41。寄存器 0x00E0,长度 1
AFCI_FUNC_REG_SEND_CLEAR_DATA_CMD / AFCI_NUM_SEND_CLEAR_DTA_CMD宏:43-44。功能码 0xE0,长度 1。宏名 DTA 为 DATA 的拼写错误;与上一组的 0x00E0 值近似但语义不同
AFCI_ADDR_REG_GET_LOG_DATA_CMD / AFCI_NUM_GET_LOG_DATA_CMD宏:46-47。功能码 0xE1,长度 1(取新日志)
AFCI_ADDR_REG_REPEAT_LOG_DATA_CMD / AFCI_NUM_REPEAT_LOG_DATA_CMD宏:49-50。功能码 0xE2,长度 1(重发当前帧)
AFCI_GET_MAX_LOG_DATA_LEN宏:52,值 64。单帧最大日志数据字节数
AFCI_LOG_MAX_FRAME_NUM宏:54,值 17。日志缓冲容纳的帧数
AFCI_LOG_TOTAL_MAX_LEN宏:55。64 * 17 = 1088,即 afci_log_buff 尺寸。注意缓冲存的是 HEX 文本,实承载 544 字节原始数据,因此 17 帧只是“字符串长度上的 17 帧”
AFCI_LOG_GROUP_SIZE宏:57,值 8。每成组上传的帧数(小于 17,所以单包里含 8 帧的拉取进度)
ALPHAESS_AFCI_STATE_E枚举:59-64。自检状态机:AFCI_START_STATE(0) / AFCI_SELF_CHECK_STATE(1) / AFCI_FAULT_STATE(2)。无显式值,靠顺序隐式赋值,且被存进 u8 变量
AFCI_LOG_UPDATA_STATE_E枚举:66-71。日志上传状态:AFCI_DATA_NONE(0x00) / AFCI_DATA_UPDATA(0x01) / AFCI_UPDATA_COMPLETE(0x02)。该值直接写进上报云端的 JSON UploadStatus 字段,属于外部协议契约,不可随意改值
AFCI_QRY_RET_E枚举:73-78。日志帧查询返回值:AFCI_QRY_OK / AFCI_QRY_FAIL / AFCI_QRY_END / AFCI_QRY_BUF_FULL。AFCI_QRY_END 在当前 afci_comm.c 中与 FAIL 同等对待
AFCI_LOG_DATA_TABLE结构体:80-91。AFCI 故障日志上传的跨任务共享状态块,字段见下

AFCI_LOG_DATA_TABLE 字段表

字段类型说明
u32_afci_log_send_lenu32当前组已拼接的字符数(= 2 × 原始字节数)
u32_afci_log_send_net_lenu32待发往云端的长度,上报 JSON 的 FileLen
u16_afci_log_sequ16注释写“当前帧序号”,但全工程无读写点,实际帧序号是本文件 .c 里函数内的 static l_u16_frame_seq
u8_afci_log_statusu8上传状态,取 AFCI_LOG_UPDATA_STATE_E 值,上报 JSON 的 UploadStatus
u8_afci_log_send_flagu8待发标志:为 TRUE 时网络任务发送、逆变器任务停止灌数据
u8_afci_log_rev_ok_flagu8云端已应答标志,由 net/ems.c:6211 在发完后清、由 set_afci_log_data_upload_send_status() 置回
afci_log_pack_flag[32]char[]包标识/时间戳字符串(net/ems.c:2679 用 snprintf 写入 "YYMM/MM/DD HH:MM:SS")
u32_afci_log_send_offsetu32本轮已发送包数,上报 JSON 的 FileOffset;为 0 时 fill_send_afci_log 会刷新 afci_log_pack_flag
afci_log_buff[AFCI_LOG_TOTAL_MAX_LEN]char[]1088 字节 ASCII HEX 缓冲区,上报 JSON 的 FileData

sizeof(AFCI_LOG_DATA_TABLE) ≈ 1137 字节(含对齐),落在 SDRAM_AFCI_FAULT_LOG_ADDR 预留的 2 KB 区间内。

3. 函数清单

本文件不定义函数,只声明以下 13 个原型(全部定义于 afci_comm.c):

函数名作用域说明
query_afci_software_version全局声明:97。查询并解析 AFCI 软版本,同时判定 AFCI 是否存在
afci_self_check_handle全局声明:98。AFCI 自检状态机推进
set_afci_fac_mode全局声明:99。写工厂模式寄存器(1 进 / 0 退)
send_afci_clear_warning_message全局声明:100。清 AFCI 告警
afci_fault_log_data_handle全局声明:101。AFCI 故障日志分帧拉取
set_afci_log_data_upload_send_status全局声明:102。云端应答后的上传状态回调
ems_send_ctrl_data_to_afci全局声明:103。通用 Modbus 0x06/0x10 写帧
alphaess_afci_recv_data全局声明:104。同步收一帧 AFCI 应答并校验
get_afci_soft_version全局声明:105。返回软版本字符串指针(无调用点)
inverter_read_ver_afci全局声明:106。返回软版本字符串指针(带末尾截断保护)
send_afci_clear_info全局声明:107。清 AFCI 信息(无调用点)
set_afci_soft_reboot全局声明:108。AFCI 软重启
afci_log_init全局声明:109。日志状态块清零并复位触发标志

声明缺口:afci_comm.c:747 定义的全局函数 send_clear_afci_log_data() 未在本头文件声明,外部模块无法正常引用(仅本文件内部使用)。

4. 核心逻辑解析

4.1 三组常量构成的寻址空间

USART2 上跑着三个逻辑设备,靠首字节区分(这是使用方 alphaess_afci_recv_data / alphaess_recv_data 的判据):

首字节含义定义处
0x03阿尔法逆变器从站alphaess_comm_usart.h:23 ALPHAESS_SLAVR_ADDRESS
0x01AFCI 常规 Modbus 从站本文件 :22 AFCI_SLAVR_ADDRESS
0xF8AFCI OTA 升级通道afci_upgrade.h:16 AFCI_UPGRADE_ADDRESS

AFCI 的寄存器映射(功能码含义见 .c 文档):

寄存器/功能码常量读写语义
0x0002AFCI_ADDR_REG_WARNING_MESSAGER/W读 = 自检结果基准码,写 0 = 清告警
0x0010+11AFCI_ADDR_REG_QUERY_SOFT_VERSION2R22 字节版本区,需机型重排
0x0024AFCI_ADDR_REG_SELF_CHECK_FUNCTION_ENABLER/W写 0x3F = 使能全部通道;读 = 自检状态
0x0025AFCI_ADDR_REG_SET_SOFT_REBOOTW写 1 = 软重启
0x0026AFCI_ADDR_REG_SEND_FAC_MODE_CMDW1 = 进工厂模式,0 = 出
0x00E0AFCI_ADDR_REG_SEND_CLEAR_INFO_CMDW写 0 = 清信息
0xE0(功能码)AFCI_FUNC_REG_SEND_CLEAR_DATA_CMDW裸帧清故障记录
0xE1 / 0xE2(功能码)AFCI_ADDR_REG_GET/REPEAT_LOG_DATA_CMDR取日志 / 重发当前帧

注意 0x00E0 与 0xE0:同一个数值既是寄存器地址(配功能码 0x06)又是功能码(裸帧),是本模块最容易混淆的设计点。

4.2 日志缓冲尺寸的推导链

AFCI_GET_MAX_LOG_DATA_LEN = 64        // 单帧最多 64 字节原始数据
AFCI_LOG_MAX_FRAME_NUM    = 17        // 缓冲按 17 帧规划
AFCI_LOG_TOTAL_MAX_LEN    = 64*17 = 1088   // = afci_log_buff 字符容量
AFCI_LOG_GROUP_SIZE       = 8         // 但每 8 帧就成组发出

因为缓冲存的是 %02X HEX 文本,1088 字符只承载 544 字节原始数据。上界守卫在 afci_comm.c:800 用 >= 判断,因此刚好填满也判 BUF_FULL,留出末字节给 '\0'(实际 '\0' 写在 afci_log_buff[send_len],因守卫是严格 <,下标必然 ≤ 1087,安全)。

由于 AFCI_LOG_GROUP_SIZE(8) < AFCI_LOG_MAX_FRAME_NUM(17),正常流程下每组只用掉 8×64×2 = 1024 字符就发出,1088 的容量是给「一条帧就返回长数据」或残包兜底用的,AFCI_QRY_BUF_FULL 分支正是为此准备的。

4.3 状态枚举的隐式赋值与外部契约

ALPHAESS_AFCI_STATE_E 与 AFCI_QRY_RET_E 无显式初值,靠声明顺序取 0,1,2(,3)。它们只在 afci_comm.c 内部作为 static u8 的比较对象使用,改动顺序会静默改变语义(不会编译报错)。

AFCI_LOG_UPDATA_STATE_E 则是对外协议:0x01 = 中途包、0x02 = 末包,直接进入 net/ems.c:2700 的 JSON "UploadStatus":"%d",云端据此重组文件;net/server.c:7084 的 set_afci_log_data_upload_send_status() 又用 status == AFCI_UPDATA_COMPLETE 决定是否清除 AFCI 侧记录。因此这个枚举值一旦修改,云端协议与 AFCI 清记录时机都会一起错位。

5. 对外接口

本文件导出:

本文件调用的外部符号:仅 includes.h(:13)。这是工程的总汇头,会引入 stdint/string/uCOS-II/gd32f4xx 等全部基础依赖,因此任何包含本头文件的模块都会被动引入庞大的编译面。

6. 依赖关系

依赖:includes.h(:13)。

被依赖(include afci_comm.h 的文件):

7. 备注与风险点

  1. send_clear_afci_log_data 未声明:afci_comm.c:747 定义、:934 调用,但本头文件没有对应原型。若外部模块需要调用只能自行 extern,且编译器无法做原型检查(见 afci_comm.c 风险点 10)。
  2. 声明的两个函数全工程无调用点:get_afci_soft_version()(:105)与 send_afci_clear_info()(:107)。get_afci_soft_version 与 inverter_read_ver_afci 功能几乎重复(后者多一次 '\0' 兜底),实际云端上报走的是 inverter_read_ver_afci(net/ems.c:2270)。两者保留易误用。
  3. u16_afci_log_seq 是遗留字段:注释为“当前帧序号”,但实现改用函数内 static l_u16_frame_seq。该字段从未被读写,仍占 4 字节(含对齐),并出现在定址到 SDRAM 的结构体里。
  4. 0x00E0 与 0xE0 语义重载:AFCI_ADDR_REG_SEND_CLEAR_INFO_CMD(寄存器地址)与 AFCI_FUNC_REG_SEND_CLEAR_DATA_CMD(功能码)值相近、命名相近、用途不同,极易在后续维护中写错。
  5. AFCI_LOG_TOTAL_MAX_LEN 与 AFCI_LOG_GROUP_SIZE 的关系未在注释中说明:1088 的容量按 17 帧规划,而实际每 8 帧成组发送,容量偏大近一倍;若后续把 AFCI_LOG_GROUP_SIZE 调到 > 17,长数据帧会立刻触发 AFCI_QRY_BUF_FULL 分支(该分支会把残包当作末组发出),行为会静默改变。
  6. AFCI_TYPE_BYTE_WATT_T 的值是 "BYTE_AFCI_T" 而非 "BYTE_AFCI_T10":与逆变器机型枚举 INVERTER_TYPE_BYTE_WATT_T(对应 SUB_T10)命名不平行,云端型号串匹配依赖此字面量,改动需与云端同步。
  7. VERSION_AFCI_HARD 是硬编码字符串:get_afci_hard_version() 直接返回该宏,与实物 AFCI 上报的软版本(运行期读取)无一致性校验路径,硬件改版必须手工改宏。
  8. DEBUG_ALPHAESS_AFCI 定义在业务头文件里:该开关控制 alphaess_comm_usart.c 的打印行为,把调试粒度耦合到 AFCI 头文件;同时 afci_comm.c 内有大量 printf 只在 == 1 时编译,长期处于关闭状态意味着这些代码缺少编译验证(例如 :305 用了 for(int i=...) 的 C99 写法,与其他位置的 u8 i 风格不一致)。
  9. 除 AFCI_LOG_UPDATA_STATE_E 外均无显式初值:ALPHAESS_AFCI_STATE_E(3 个)、AFCI_QRY_RET_E(4 个) 都依赖声明顺序取值,且被赋给 u8 变量。若有人插入新成员,状态机比较会静默错位。