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_len | u32 | 当前组已拼接的字符数(= 2 × 原始字节数) |
u32_afci_log_send_net_len | u32 | 待发往云端的长度,上报 JSON 的 FileLen |
u16_afci_log_seq | u16 | 注释写“当前帧序号”,但全工程无读写点,实际帧序号是本文件 .c 里函数内的 static l_u16_frame_seq |
u8_afci_log_status | u8 | 上传状态,取 AFCI_LOG_UPDATA_STATE_E 值,上报 JSON 的 UploadStatus |
u8_afci_log_send_flag | u8 | 待发标志:为 TRUE 时网络任务发送、逆变器任务停止灌数据 |
u8_afci_log_rev_ok_flag | u8 | 云端已应答标志,由 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_offset | u32 | 本轮已发送包数,上报 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 |
0x01 | AFCI 常规 Modbus 从站 | 本文件 :22 AFCI_SLAVR_ADDRESS |
0xF8 | AFCI OTA 升级通道 | afci_upgrade.h:16 AFCI_UPGRADE_ADDRESS |
AFCI 的寄存器映射(功能码含义见 .c 文档):
| 寄存器/功能码 | 常量 | 读写 | 语义 |
|---|---|---|---|
0x0002 | AFCI_ADDR_REG_WARNING_MESSAGE | R/W | 读 = 自检结果基准码,写 0 = 清告警 |
0x0010+11 | AFCI_ADDR_REG_QUERY_SOFT_VERSION2 | R | 22 字节版本区,需机型重排 |
0x0024 | AFCI_ADDR_REG_SELF_CHECK_FUNCTION_ENABLE | R/W | 写 0x3F = 使能全部通道;读 = 自检状态 |
0x0025 | AFCI_ADDR_REG_SET_SOFT_REBOOT | W | 写 1 = 软重启 |
0x0026 | AFCI_ADDR_REG_SEND_FAC_MODE_CMD | W | 1 = 进工厂模式,0 = 出 |
0x00E0 | AFCI_ADDR_REG_SEND_CLEAR_INFO_CMD | W | 写 0 = 清信息 |
0xE0(功能码) | AFCI_FUNC_REG_SEND_CLEAR_DATA_CMD | W | 裸帧清故障记录 |
0xE1 / 0xE2(功能码) | AFCI_ADDR_REG_GET/REPEAT_LOG_DATA_CMD | R | 取日志 / 重发当前帧 |
注意 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. 对外接口
本文件导出:
- 全局变量声明:
extern AFCI_LOG_DATA_TABLE g_t_afci_log_tab;(:95)—— 由afci_comm.c:27定义并定址到 SDRAM;被net/ems.c(fill_send_afci_log、发送条件判定、清应答标志)与net/server.c:7084读写。 - 13 个函数原型(见第 3 节)。实际调用方集中在
midware/inverter/alphaess/alphaess_comm_usart.c(:5060/5065/5071/5076/5209/5411/5412)、midware/afci/afci_upgrade.c(:55/56/432)、net/ems.c:2270(inverter_read_ver_afci)、net/server.c:7084(set_afci_log_data_upload_send_status)。 - 宏常量:
VERSION_AFCI_HARD/AFCI_TYPE_BYTE_WATT_S/AFCI_TYPE_BYTE_WATT_T被net/afci_download.c(get_afci_hard_version/get_afci_type)使用;DEBUG_ALPHAESS_AFCI被alphaess_comm_usart.c使用。
本文件调用的外部符号:仅 includes.h(:13)。这是工程的总汇头,会引入 stdint/string/uCOS-II/gd32f4xx 等全部基础依赖,因此任何包含本头文件的模块都会被动引入庞大的编译面。
6. 依赖关系
依赖:includes.h(:13)。
被依赖(include afci_comm.h 的文件):
midware/afci/afci_comm.c:15、midware/afci/afci_upgrade.c:15midware/inverter/alphaess/alphaess_comm_usart.c:30net/ems.c:56、net/server.c:55、net/afci_download.c:20
7. 备注与风险点
send_clear_afci_log_data未声明:afci_comm.c:747定义、:934调用,但本头文件没有对应原型。若外部模块需要调用只能自行extern,且编译器无法做原型检查(见afci_comm.c风险点 10)。- 声明的两个函数全工程无调用点:
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)。两者保留易误用。 u16_afci_log_seq是遗留字段:注释为“当前帧序号”,但实现改用函数内static l_u16_frame_seq。该字段从未被读写,仍占 4 字节(含对齐),并出现在定址到 SDRAM 的结构体里。0x00E0与0xE0语义重载:AFCI_ADDR_REG_SEND_CLEAR_INFO_CMD(寄存器地址)与AFCI_FUNC_REG_SEND_CLEAR_DATA_CMD(功能码)值相近、命名相近、用途不同,极易在后续维护中写错。AFCI_LOG_TOTAL_MAX_LEN与AFCI_LOG_GROUP_SIZE的关系未在注释中说明:1088的容量按 17 帧规划,而实际每 8 帧成组发送,容量偏大近一倍;若后续把AFCI_LOG_GROUP_SIZE调到 > 17,长数据帧会立刻触发AFCI_QRY_BUF_FULL分支(该分支会把残包当作末组发出),行为会静默改变。AFCI_TYPE_BYTE_WATT_T的值是"BYTE_AFCI_T"而非"BYTE_AFCI_T10":与逆变器机型枚举INVERTER_TYPE_BYTE_WATT_T(对应SUB_T10)命名不平行,云端型号串匹配依赖此字面量,改动需与云端同步。VERSION_AFCI_HARD是硬编码字符串:get_afci_hard_version()直接返回该宏,与实物 AFCI 上报的软版本(运行期读取)无一致性校验路径,硬件改版必须手工改宏。DEBUG_ALPHAESS_AFCI定义在业务头文件里:该开关控制alphaess_comm_usart.c的打印行为,把调试粒度耦合到 AFCI 头文件;同时afci_comm.c内有大量printf只在== 1时编译,长期处于关闭状态意味着这些代码缺少编译验证(例如:305用了for(int i=...)的 C99 写法,与其他位置的u8 i风格不一致)。- 除
AFCI_LOG_UPDATA_STATE_E外均无显式初值:ALPHAESS_AFCI_STATE_E(3 个)、AFCI_QRY_RET_E(4 个) 都依赖声明顺序取值,且被赋给u8变量。若有人插入新成员,状态机比较会静默错位。