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

ct.h

源文件路径:midware/meter/ct.h 所属模块:midware/meter(CT 采样) 代码行数:193

1. 文件职责

本头文件是 CT(电流互感器)交流采样模块的类型与接口契约:它定义了采样滤波深度、波形曲线缓冲尺寸、有功限幅等编译期常量,定义了两张 NVRAM 持久化表(CT_CONFIG_TABLE_T 校准表、CT_ENERGY_SAVE_TABLE_T 电量表)与两套运行表(GRID_SAMPLING_CURVE_T / GRID_SERVER_SAMPLING_CURVE_T),并把它们聚合为 CT_TABLE_T。所有采样结果都通过本文件声明的全局 g_t_ct 与两个 SDRAM 绝对地址结构对外暴露,上层(meter.c 的 ct_handle()、modbus.c 寄存器映射、logic/dispatch.c 频率判断)只经 ct_read_*() 接口取数,不直接触碰内部缓冲。它是 ct.c 的唯一头文件,同时被 meter.h 等模块间接引用。

2. 关键数据结构与宏

名称类型说明
DEBUG_SAMPLING宏0,置 1 打开采样频率/任务循环计数统计(ct.h:20)
FILTER_DEPTH_MID宏200,中值(DC 偏置)滤波深度(ct.h:22)
CALIBRATION宏1,总开关,控制是否启用分段线性校准(ct.h:24)
FILTER_DEPTH_VOLT宏5,GRID 电压滑动平均窗口(ct.h:25)
FILTER_DEPTH_FREQ宏10,频率滑动平均窗口(ct.h:26)
FILTER_DEPTH_GRID_CURR宏10,GRID 电流滑动平均窗口(ct.h:27)
FILTER_DEPTH_PV_CURR宏10,PV 电流滑动平均窗口(ct.h:28)
FILTER_DEPTH_GRID_POWER宏10,GRID 有功滑动平均窗口(ct.h:29)
FILTER_DEPTH_PV_POWER宏10,PV 有功滑动平均窗口(ct.h:30)
CT_MAX_POWER宏18000,单相有功功率写入表的限幅门限(ct.h:32)
SAMPLING_CURVE_CHANNEL宏2,本地曲线通道数(电压 + 电流)(ct.h:34)
SAMPLING_CURVE_NUM宏1000,本地曲线每通道点数(100ms 曲线 10 周期)(ct.h:35)
SAMPLING_CURVE_BUF_LEN宏SAMPLING_CURVE_CHANNEL * SAMPLING_CURVE_NUM = 2000(ct.h:36)
SERVER_SAMPLING_CURVE_CHANNEL宏2,上报服务器曲线通道数(ct.h:38)
SERVER_SAMPLING_CURVE_NUM宏5000,上报服务器曲线每通道点数(500ms 曲线 50 周期)(ct.h:39)
SERVER_SAMPLING_CURVE_BUF_LEN宏2 * 5000 = 10000(ct.h:40)
CT_SITE_E枚举CT 安装位置:GRID_CT = 1、PV_CT、FAST_GRID_CT、MAX_CT_SITE(ct.h:42)。FAST_GRID_CT 专指 0.001Hz 分辨率频率
CT_PHASE_E枚举相位选择:CT_PHASE_A = 0、B、C、T(电表总值)(ct.h:50)
GRID_SAMPLING_CURVE_T结构体本地双缓冲波形录制:u8_sampling_curve_en(总使能)、u8_sampling_curve_buf_flag(当前在用哪块缓冲)、通道1 的发送标志/缓冲/计数、通道2 的发送标志/缓冲/计数(ct.h:59)。#pragma pack(1),保证放在 SDRAM 固定地址时的布局可控
GRID_SERVER_SAMPLING_CURVE_T结构体上报服务器用波形:s_grid_ct_sampling_info_time(采集时刻 RTC)、u8_server_sampling_curve_en、u8_server_sampling_curve_send_flag、计数、u16_server_sampling_curve_buf[SERVER_SAMPLING_CURVE_BUF_LEN](ct.h:71)
CT_DATA_T结构体单路 CT 实时数据:u16_ct_volt_a/b/c、s16_ct_current_a/b/c、s32_ct_actpower_a/b/c/t、s32_ct_reactpower、s32_ct_apparentpower、s16_ct_factor、u16_ct_frequent(0.01Hz)、u16_fast_ct_frequent(0.001Hz)、u32_ct_energy_input/output(ct.h:80)
CT_RUN_TABLE_T结构体运行表:u8_clear_energy_flag + CT_DATA_T t_ct_data(ct.h:101)
CT_CALIBRATION_TABLE_T结构体单个校准点:s16_calibration_point(分段分界点)、s16_calibration_coef(系数,实除以 10000)、s16_calibration_offset(偏移量)(ct.h:107)
CT_CONFIG_TABLE_T结构体持久化校准总表:u16_head、A 相电压 2 点、GRID 有功 B/A/C 各 5 点、PV 有功 A/B/C 各 5 点、B/C 相电压各 2 点、u8_reserved[35]、u8_reserved_flag、u16_crc_code(ct.h:114)。注意字段声明顺序与命名不对称(B 相有功排在 A 相之前),但数组本身是独立成员,顺序无所谓
CT_ENERGY_SAVE_TABLE_T结构体持久化电量表:u16_head + GRID 各相及总输入/输出电量 8 个 u32 + PV 同结构 8 个 u32 + u8_reserved[60] + u16_crc_code(ct.h:134)
CT_TABLE_T结构体顶层聚合:t_grid_ct_info、t_pv_ct_info、t_ct_config、t_ct_energy(ct.h:161)
STATIC_ASSERT(...)宏编译期断言(ct.h:132、ct.h:159):ASSERT_FLASH_SECTOR_SIZE % sizeof(CT_CONFIG_TABLE_T) == 0、ASSERT_FLASH_SECTOR_SIZE % sizeof(CT_ENERGY_SAVE_TABLE_T) == 0,保证结构体尺寸能整除 Flash 扇区以便按页搬运
g_t_ct全局变量(extern)CT_TABLE_T 实例,CT 模块唯一的全局数据表(ct.h:170)
g_grid_sampling_curve_t全局变量(extern)定位在 SDRAM_GRID_SAMPLING_CURVE_ADDR 的本地波形缓冲(ct.h:171)
g_server_grid_sampling_curve_t全局变量(extern)定位在 SDRAM_SEVER_GRID_SAMPLING_CURVE_ADDR 的服务器波形缓冲(ct.h:172)

3. 函数清单

本文件为纯声明型头文件,不含任何函数定义;以下是它导出的全部函数原型(均在 ct.c 中实现)。

函数名作用域说明
ct_sampling_init全局采样链路(ADC2/DMA1_CH0/TIM1/TIM2/EXTI10_15)初始化(ct.h:175)
grid_freq_sampling_handle全局电网频率采样处理,由 TIM2/下降沿中断调用(ct.h:177)
adc_regular_data_recv全局ADC2 规则组 DMA 传输完成回调(ct.h:178)
adc_inserted_data_recv全局已声明,在 ct.c 中无实现(ct.h:179)——见备注
task_sampling全局uCOS-II 采样任务主体(ct.h:181)
ct_enenrgy_handle全局已声明,在 ct.c 中无实现(ct.h:182);函数名拼写有误(enenrgy)
ct_read_voltage全局读线电压(ct.h:184)
ct_read_current全局读电流(ct.h:185)
ct_read_actpower全局读有功功率(ct.h:186)
ct_read_reactpower全局读无功功率(ct.h:187)
ct_read_factor全局读功率因数(ct.h:188)
ct_read_frequent全局读频率(ct.h:189)
ct_read_einput全局读累计输入电量(ct.h:190)
ct_read_eoutput全局读累计输出电量(ct.h:191)
ct_energy_clear全局清零指定 CT 电量(ct.h:192)

4. 核心逻辑解析

4.1 内存布局约束(#pragma pack(1) 与固定地址)

CT_CONFIG_TABLE_T、CT_ENERGY_SAVE_TABLE_T 与两个波形结构都包在 #pragma pack(1)(ct.h:58-ct.h:168)内。前两者要按 Flash 扇区整块读写(data/system_config/system_config.c 中的 feeprom_write/feeprom_init_write),因此必须无填充字节,STATIC_ASSERT 就是用来在编译期守住「结构体尺寸整除扇区」这条不变量。两个波形结构则通过 __attribute__((at(ADDR))) 落在 SDRAM 固定地址(ct.h:171-ct.h:172),配合 hardware/sdram/sdram.h:46-sdram.h:48 的地址宏分配(本地曲线 10K、服务器曲线 20K)——pack(1) 保证布局在不同编译选项下不会漂移从而覆盖相邻区域。

4.2 两级采样率的结构设计

CT_SITE_E 里 GRID_CT(0.01Hz 频率)与 FAST_GRID_CT(0.001Hz)并存,对应 CT_DATA_T 中的 u16_ct_frequent 与 u16_fast_ct_frequent 两个字段。这反映了实际采样链路的双速率:常规频率由 FILTER_DEPTH_FREQ(10 周期窗口)平滑,快速频率直接给最近一次测量值,供 logic/dispatch.c 的快速越限判断使用(dispatch.c:626 用 ct_read_frequent(FAST_GRID_CT) > 44000)。

4.3 校准表的分段组织

CT_CONFIG_TABLE_T 把校准按「电气量 × 相」拆成 14 个定长数组:

ct.c 里电流校准实际只用了每个 5 点数组的前 4 点(grid_active_curr_filter、pv_active_curr_filter 的第 4 段是 else 兜底),第 5 点仅作为上界占位。u8_reserved[35] 是留给后续增加校准维度的空间,u8_reserved_flag 配合 CRC 用于判断该扇区是否已被写过有效数据。

4.4 与 uCOS-II 任务的配合

本头文件本身不含任务代码,但通过 task_sampling 与 g_t_ct 的声明确定了模块的并发契约:g_t_ct.t_grid_ct_info/t_pv_ct_info 由 task_sampling 单写、多读(ct_handle() 在同一个任务上下文中读,modbus.c/dispatch.c 在其他任务中读),没有加锁,依赖「字长对齐的 32 位读写天然原子」这一在 Cortex-M4 上成立的前提。两个波形结构的 _en/send_flag 标志则由其他任务写、采样任务读,属于典型的无锁单写者模式。

5. 对外接口

本文件导出

名称类型使用者
g_t_ct全局变量midware/meter/meter.c、data/system_config/system_config.c、midware/auxiliary/system_aux.c、hmi/ 等
g_grid_sampling_curve_t全局变量(SDRAM 定位)HMI / 采样曲线命令处理
g_server_grid_sampling_curve_t全局变量(SDRAM 定位)net/ems.c
ct_sampling_init、grid_freq_sampling_handle、adc_regular_data_recv、task_sampling函数原型ct.c 自身、user/main.c(任务创建)、中断向量表
ct_read_voltage/current/actpower/reactpower/factor/frequent/einput/eoutput函数原型midware/meter/meter.c、midware/interface/modbus/modbus.c、logic/dispatch.c
ct_energy_clear函数原型data/data.c
CT_SITE_E / CT_PHASE_E / CT_DATA_T / CT_TABLE_T 等类型类型所有 CT 数据使用者
CALIBRATION / FILTER_DEPTH_* / CT_MAX_POWER 等宏宏ct.c(编译期裁剪)

本文件依赖的外部声明

chip.h(u8/u16/s32 等基础类型与 STATIC_ASSERT、FALSE/TRUE)、sdram.h(SDRAM_GRID_SAMPLING_CURVE_ADDR、SDRAM_SEVER_GRID_SAMPLING_CURVE_ADDR、ASSERT_FLASH_SECTOR_SIZE 来源)、pcf8563.h(struct RTC_DateTime,供 GRID_SERVER_SAMPLING_CURVE_T 使用)、debug.h(printf 等调试宏)。

6. 依赖关系

依赖

被依赖

7. 备注与风险点

  1. 两个函数原型没有实现:adc_inserted_data_recv(ct.h:179)与 ct_enenrgy_handle(ct.h:182)在 ct.c 中全文搜索不到定义。只要没有调用点就不会产生链接错误,但属于明显的版本遗留(adc_inserted_data_recv 对应「注入组」采样,当前实现只用了规则组)。
  2. 拼写错误:ct_enenrgy_handle 应为 ct_energy_handle(ct.h:182);同类问题还有 GRID_SERVER_SAMPLING_CURVE_T 对应的地址宏 SDRAM_SEVER_GRID_SAMPLING_CURVE_ADDR(sdram.h:47,SEVER 少一个 R)。
  3. CT_DATA_T 中大部分字段无人写入:s32_ct_reactpower、s32_ct_apparentpower、s16_ct_factor 在 ct.c 中只有被清零(ct.c:1129-ct.c:1131)和桩函数读取(ct_read_reactpower、ct_read_factor 恒返回 0),从未计算赋值 —— 即当前 CT 方案不提供无功与功率因数。
  4. u8_clear_energy_flag 未被使用:CT_RUN_TABLE_T 中定义了该字段(ct.h:103),但 ct.c 与其它模块都没有引用,实际清零走的是 ct_energy_clear() 直接改 t_ct_energy。
  5. 有符号/无符号混用:s16_calibration_point 为 s16,而它与无符号的采样量做比较(ct.c:138),且电流校准处还要 * 10 / 23 后比较,符号语义容易出错。
  6. 预留区未被清零机制保护:CT_CONFIG_TABLE_T 的 u8_reserved[35] 与 CT_ENERGY_SAVE_TABLE_T 的 u8_reserved[60] 在新增字段时会改变 CRC 覆盖范围,若有旧版本固件已经写入过 Flash,升级后读取旧扇区会因 CRC 不匹配而回退默认值 —— 这是可接受的升级策略,但需在发布说明中确认。
  7. STATIC_ASSERT 依赖 ASSERT_FLASH_SECTOR_SIZE:该宏定义在 sdram.h 或其它配置头中,若某板型的 Flash 扇区尺寸变化而结构体尺寸不可整除,编译会直接失败 —— 这是有意设计,但会阻塞新板型适配。