/* * 模块名称:相量计算层(L2 相量计算) * 模块功能:全周傅氏(全周波傅里叶)算法——对一周波 20 点采样做单频 DFT, * 产出基波/谐波相量。系数表**预乘 √2/N**(口径见 * `docs/算法/傅氏算法详解.md` §2.3),故 `fAmSQ = √(fRe²+fIm²)` * **直接就是有效值**,无需再除 √2。 * 覆盖规划 §3.2:L2-1 系数表 / L2-2 实例 / L2-3 有效值输出 / * L2-6 每 1 ms 滑动窗 / L2-7 双区指针原子交换。 * ⚠ 本层**纯算法**:不碰寄存器、不碰任务调度、不自己取数(输入由 * `sample_ring` 提供)→ 主机侧可单测(L0.5,落实登记簿 A-4)。 * 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU) * 作者:王建锋 * 创建日期:2026-10-10 * 修改记录: * v1.0 2026-10-10 王建锋 创建:L2-1/2/3/6/7(基波 + 谐波相量) */ #ifndef PHASOR_H #define PHASOR_H #include #include "adc_input.h" /* adc_semantic_t:实例按语义通道绑定 */ #ifdef __cplusplus extern "C" { #endif /* 每周波采样点数(1000 Hz @ 50 Hz,见 docs/子系统设计/ADC采样节拍设计说明.md) */ #define PHASOR_N 20U /* 相量结果(**有效值口径**)。字段名沿用参考系统 `{fRe, fIm, fAm, fAmSQ}` * (规划 §10.2 术语表:实部/虚部/幅值/有效值): * fRe - 实部 = a1/√2(有效值相量实部) * fIm - 虚部 = b1/√2(有效值相量虚部) * fAm - 幅值 = √2·√(fRe²+fIm²)(正弦峰值 A1) * fAmSQ - 有效值 = √(fRe²+fIm²)(系数已折算 √2/N,故直接即有效值) * 相位(L2-4)按需由 `atan2(fIm, fRe)` 导出,不常驻本结构。 */ typedef struct { float fRe; float fIm; float fAm; float fAmSQ; } phasor_t; /* 相量实例(L2-2):**数据驱动**——新增实例只需在实例表尾加一行 */ typedef struct { const char *name; /* 实例名(日志 / UI 用) */ adc_semantic_t sem; /* 语义通道 */ uint8_t harm; /* 谐波次数(1=基波,2=二次,5=五次…) */ } phasor_inst_t; /* * 函数功能:相量层初始化 * 入口参数:无 * 返 回 值:0 - 成功 * 限定条件:内核启动前调用(无 RTOS 依赖) * 函数说明:清双区结果与有效标志,并复位采样环缓冲;可重复调用(幂等)。 */ int phasor_init(void); /* * 函数功能:取相量实例数(L2-2) * 入口参数:无 * 返 回 值:实例个数 * 限定条件:无 * 函数说明:供遍历 / 日志打印。 */ uint8_t phasor_inst_count(void); /* * 函数功能:取相量实例描述 * 入口参数:idx - 实例下标 * 返 回 值:指向静态实例表的指针;idx 越界返回 NULL * 限定条件:无 * 函数说明:返回静态存储地址,调用方不得修改。 */ const phasor_inst_t *phasor_inst(uint8_t idx); /* * 函数功能:重算全部实例并从计算区原子切换到使用区(L2-6 滑动窗 + L2-7 双区交换) * 入口参数:无 * 返 回 值:无 * 限定条件:仅任务上下文调用;须先经 `sample_ring_push_frame()` 压入本拍数据 * 函数说明:以"当前时刻为终止的前一周波"为窗,**20 点全部重算**(暴力法, * 无累积误差)。**任一实例数据不足一周波则本拍整体不产出**(不切换 * 使用区),避免部分新部分旧的混合结果。每拍更新,故相量刷新周期 = 1 ms。 */ void phasor_run(void); /* * 函数功能:读实例结果(使用区,无锁) * 入口参数:idx - 实例下标 * out - 输出相量 * 返 回 值:0 - 成功;-1 - 参数错;-2 - 尚无有效结果(未攒满一周波) * 限定条件:无 * 函数说明:读的是"使用区",与正在写的"计算区"物理隔离 → 无撕裂、无锁。 */ int phasor_get(uint8_t idx, phasor_t *out); /* * 函数功能:对 n 点窗口算 harm 次相量(L2-1 系数表 + L2-3 有效值) * 入口参数:x - 采样窗(按时间序,旧 → 新;长度须 = PHASOR_N) * n - 窗长(必须等于 PHASOR_N) * harm - 谐波次数(>=1) * out - 输出相量 * 返 回 值:无(参数非法时 out 保持不动) * 限定条件:无 * 函数说明:**纯函数**(无状态),可脱离采样环独立调用,便于单测与复用。 * 索引步进 = 谐波次数即可取任意次谐波(sin 以 2π 为周期, * 故 `sin(2π·((n·h) mod N)/N) ≡ sin(2π·n·h/N)`)。 */ void phasor_calc(const float *x, uint8_t n, uint8_t harm, phasor_t *out); #ifdef __cplusplus } #endif #endif /* PHASOR_H */