Files
STM32F4-Base/App/algo/phasor.h
T
wandering1 593c5d0c84 refactor(编号): 采集链分层 L1/L1.5/L2/L2.5/L3/L4/L5 → 语义名(批次 1)
用户裁定(2026-10-28):L1/L1.5/L2/L2.5/L3 这套层号「谁能看懂」,改用语义名。
映射(同一批定稿,含 L4/L5):
  L1   → 语义取数与有效性
  L1.5 → 标定折算
  L2   → 全周傅氏相量
  L2.5 → 测频与遥测快照
  L3   → 保护判据
  L4   → 出口与记录
  L5   → 动作留痕

实测规模:384 站点 / 62 文件(App/algo、App/task、test/host 六个套件、docs/算法、
产品需求、架构总览、启动顺序、ADC 采样节拍、IEC104 上行、采集短板评测、内存管理、
AGENTS.md、README.md、docs/README.md、.pre-commit-config.yaml 与 scripts 里的注释)。

改法(不是全局替换,逐模式有上下文规则):
- 先吃同位语再落裸词:L1 有效性校验 → 语义取数与有效性校验、L2 相量层 → 全周傅氏
  相量层、L3 保护 → 保护判据、L2.5 遥测快照 → 测频与遥测快照,避免「保护判据保护判据」
  这类重复(第一版就是这么坏掉的,已整体回滚重做)。
- .c/.h 只改注释:先把字符串字面量切出去(引号数为奇数的跨行注释按整行处理),
  C 字符串里的 L2-in ring 之类原样保留——AGENTS 铁律「字符串字面量必须纯 ASCII」。
- 层内条目号(L1-3 / L2-3 这类)**本批不动**,属批次 2;另外三族(UI 菜单层级
  L0~L3、链路延迟分段 L1~L8、CubeMX 防丢失三层)也不动,属批次 3。
- 顺手修的措辞:范围写法 L1~L3 → 「分层(语义取数与有效性 → 保护判据)」、
  CI 段「不含 L1/L2/L3」→「不含采集链分层」、目录地图里同一处并列表述。

验证:@build 0 错 0 警(Code=236456,与改前逐字节同尺寸——纯注释改动);
内存布局配图已按新脚本重生成(自检通过);doc-links --all --sections-strict 通过
(195 文档);mojibake / bom-guard / coding-standard / 新编号门禁自查 全 rc=0;
git diff --check 干净。
2026-10-28 13:04:02 +08:00

121 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:相量计算层(全周傅氏相量计算)
* 模块功能:全周傅氏(全周波傅里叶)算法——对一周波 20 点采样做单频 DFT,
* 产出基波/谐波相量。系数表**预乘 √2/N**(口径见
* `docs/算法/傅氏算法详解.md` §2.3),故 `fAmSQ = √(fRe²+fIm²)`
* **直接就是有效值**,无需再除 √2。
* 覆盖规划 §3.2:全周傅氏系数表 / 基波相量实例 / 相量有效值输出 /
*(保护功能清单见 docs/算法/继电保护功能复现规划.md)
* 每 1 ms 滑动窗刷新 / 双区指针原子交换。
* ⚠ 本层**纯算法**:不碰寄存器、不碰任务调度、不自己取数(输入由
* `sample_ring` 提供)→ 主机侧可单测(L0.5)。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:王建锋
* 创建日期:2026-10-10
* 修改记录:
* v1.0 2026-10-10 王建锋 创建:全周傅氏系数表 等(基波 + 谐波相量)
*/
#ifndef PHASOR_H
#define PHASOR_H
#include <stdint.h>
#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,故直接即有效值)
* 相位输出按需由 `atan2(fIm, fRe)` 导出,不常驻本结构。 */
typedef struct {
float fRe;
float fIm;
float fAm;
float fAmSQ;
} phasor_t;
/* 基波相量实例:**数据驱动**——新增实例只需在实例表尾加一行 */
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);
/*
* 函数功能:取相量实例数
* 入口参数:无
* 返 回 值:实例个数
* 限定条件:无
* 函数说明:供遍历 / 日志打印。
*/
uint8_t phasor_inst_count(void);
/*
* 函数功能:取相量实例描述
* 入口参数:idx - 实例下标
* 返 回 值:指向静态实例表的指针;idx 越界返回 NULL
* 限定条件:无
* 函数说明:返回静态存储地址,调用方不得修改。
*/
const phasor_inst_t *phasor_inst(uint8_t idx);
/*
* 函数功能:重算全部实例并从计算区原子切换到使用区(每 1 ms 滑动窗刷新 + 双区指针原子交换)
* 入口参数:无
* 返 回 值:无
* 限定条件:仅任务上下文调用;须先经 `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 次相量(全周傅氏系数表 + 相量有效值输出)
* 入口参数: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 */