ct.h
#pragma pack(1) 与固定地址)4.2 两级采样率的结构设计4.3 校准表的分段组织4.4 与 uCOS-II 任务的配合5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
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 个定长数组:
- 电压 3 相各 2 点(两点折线,通常覆盖低/高压区)
- GRID 有功 3 相各 5 点
- PV 有功 3 相各 5 点
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. 依赖关系
依赖
chip.h— 基础整型定义与STATIC_ASSERTsdram.h— SDRAM 地址分配宏(hardware/sdram/sdram.h:46-sdram.h:48)pcf8563.h— RTC 时间结构struct RTC_DateTimedebug.h— 调试输出
被依赖
midware/meter/ct.c(唯一实现方)midware/meter/meter.h(包含ct.h,以便meter.c使用CT_SAMPLING等类型与ct_read_*)logic/dispatch.c、midware/interface/modbus/modbus.c、data/data.c、data/system_config/system_config.c、net/ems.c、user/main.cuser/main.h(extern OS_EVENT *g_t_ct_sample_sem与task_sampling配套)
7. 备注与风险点
- 两个函数原型没有实现:
adc_inserted_data_recv(ct.h:179)与ct_enenrgy_handle(ct.h:182)在ct.c中全文搜索不到定义。只要没有调用点就不会产生链接错误,但属于明显的版本遗留(adc_inserted_data_recv对应「注入组」采样,当前实现只用了规则组)。 - 拼写错误:
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)。 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 方案不提供无功与功率因数。u8_clear_energy_flag未被使用:CT_RUN_TABLE_T中定义了该字段(ct.h:103),但ct.c与其它模块都没有引用,实际清零走的是ct_energy_clear()直接改t_ct_energy。- 有符号/无符号混用:
s16_calibration_point为s16,而它与无符号的采样量做比较(ct.c:138),且电流校准处还要* 10 / 23后比较,符号语义容易出错。 - 预留区未被清零机制保护:
CT_CONFIG_TABLE_T的u8_reserved[35]与CT_ENERGY_SAVE_TABLE_T的u8_reserved[60]在新增字段时会改变 CRC 覆盖范围,若有旧版本固件已经写入过 Flash,升级后读取旧扇区会因 CRC 不匹配而回退默认值 —— 这是可接受的升级策略,但需在发布说明中确认。 STATIC_ASSERT依赖ASSERT_FLASH_SECTOR_SIZE:该宏定义在sdram.h或其它配置头中,若某板型的 Flash 扇区尺寸变化而结构体尺寸不可整除,编译会直接失败 —— 这是有意设计,但会阻塞新板型适配。