diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c index afbe2d1..a8bc9d6 100644 --- a/utilities/at32f421_freertos_demo/src/TaskLoop.c +++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c @@ -48,6 +48,7 @@ uint16_t g_origin_freeze_tick = 0; // V4.36.26/32: 释放后 Origin 全冻 uint16_t g_origin_lowlearn_tick = 0; // V4.36.32: 冻结后降权低速补偿计数 (2s, 残余低值降权学入) uint16_t g_rel_band_cnt = 0; // V4.36.30: 低Q 环带超时兜底计数 (离开触发深度持续 2.5s → 强制释放) uint32_t g_vacuum_ema = 0; // V4.36.31: 真空 EMA 基线 (B3: 释放/触发参考与锚错 Origin 解耦) +static int32_t g_vac_frac = 0; // V4.37(D): EMA 余数累加器 (消 ±127 counts 整数死区) uint16_t g_ready_hold_tick = 0; // V4.36.36: 判稳后就绪巩固期计数 (5ms tick, poll_green_led 递减; 按 Q 档置 5s/7s/10s) uint32_t loop1_Origin; uint32_t loop1_ORG_SUM; @@ -562,6 +563,7 @@ void INIT_VD(void) g_origin_freeze_tick = 0; /* V4.36.26: 释放冻结计数清零 */ g_rel_band_cnt = 0; /* V4.36.30: 环带兜底计数清零 */ g_vacuum_ema = 0; /* V4.36.31: 真空 EMA 清零 (判稳后重建) */ + g_vac_frac = 0; /* V4.37(D): 余数累加器同步清零 */ g_ready_hold_tick = 0; /* V4.36.36: 就绪巩固期清零 (重建判稳时会再置) */ g_origin_lowlearn_tick = 0; /* V4.36.32: 降权期计数清零 */ loop1_CAP_OK = 0; @@ -1244,6 +1246,7 @@ void vd1_task(void) g_stable_cnt = 0; // 计数退出时清零: 二次稳定期(安全复位)从零开始 g_settle_cnt = 0; g_vacuum_ema = loop1_Origin; /* V4.36.31: 判稳完成建立真空基线 */ + g_vac_frac = 0; /* V4.37(D): 余数累加器同步清零 */ /* V4.36.36: 就绪巩固期按 Q 分档 (高Q 5s/中Q 7s/低Q 10s) — 绿灯继续慢闪期间系统收敛 */ { uint32_t _f0 = calc_freq_khz(loop1_Origin, loop1_LPCNT); @@ -1315,10 +1318,18 @@ void vd1_task(void) int32_t _ema_lim = (int32_t)(loop1_dlt_ORG * 3); if (_ema_d > _ema_lim) _ema_d = _ema_lim; else if (_ema_d < -_ema_lim) _ema_d = -_ema_lim; - if (_ema_d != 0) + if (_ema_d != 0) { /* V4.36.35: cast 顺序修复 — (uint32_t)负值/128 = +3355万/样本(爆炸源!) * 必须 有符号先除: -10/128=0, -200/128=-1(wrap 减) — 20260908 实锤根因 */ - g_vacuum_ema += (uint32_t)(_ema_d / VACUUM_EMA_ALFA); + /* V4.37(D): 余数累加 —— d/128 整数截断有 ±127 counts 死区 + * (|d|<128 步进=0 ⇒ EMA 常驻真空下方 ~127 counts ⇒ vac_ref 被拉低 + * ⇒ 进入线偏低 ⇒ 触发高度漂移, 只能断电上电复位; 2026-09-11 单测实测 127) */ + g_vac_frac += _ema_d; + { int32_t _st = g_vac_frac / VACUUM_EMA_ALFA; + g_vac_frac -= _st * VACUUM_EMA_ALFA; + g_vacuum_ema += (uint32_t)_st; + } + } if (((int32_t)loop1_Origin - (int32_t)g_vacuum_ema) > (int32_t)(loop1_Origin >> 2) || ((int32_t)g_vacuum_ema - (int32_t)loop1_Origin) > (int32_t)(loop1_Origin >> 2)) g_vacuum_ema = loop1_Origin;