perf: 提高测量精度和响应速度

- TIM3 分频 DIV_4→DIV_2(中断率×2,CPU仍<3%)
- 去掉 XNSUM_FOR_ORIGIN_FACTOR (>>6),保留全部采样精度
- LPCNT = MEASUREMENT_BASE(131072)/Xn,替代 (32768<<6)/Xn
- 测量窗口 17.5ms→~1ms(快16倍)
- Origin 范围 32K→131K,灵敏度阈值自动按比例缩放
- 离开增加 cnt_release>=3 防抖,防瞬间噪声误落杆
This commit is contained in:
wangfq
2026-06-23 11:02:12 +08:00
parent 95bf13a5ef
commit eff59c9ba9
3 changed files with 43 additions and 30 deletions

View File

@@ -33,10 +33,11 @@
/*===========================================================================
* 频率测量参数
* XNSUM_FOR_ORIGIN_FACTOR: Value/LPCNT 的归一化右移量
* 使 Origin 保持在合理的 uint32 范围内
* MEASUREMENT_BASE: 自适应测量窗口目标值 (≈131072)
* LPCNT = MEASUREMENT_BASE / Xn, 使 Value ≈ MEASUREMENT_BASE
* 121072 = 2^17, 兼顾精度和 Origin 范围
*===========================================================================*/
#define XNSUM_FOR_ORIGIN_FACTOR 6 // >>6
#define MEASUREMENT_BASE 131072 // 2^17
/*===========================================================================
* 灵敏度表 — 对齐 M1H
@@ -81,6 +82,9 @@ extern uint8_t loop1_FLAG_OUT; // 离开延时中
extern uint8_t loop1_FLAG_PLUSE; // 脉冲输出中
extern uint8_t loop1_SensLevel; // 当前灵敏度等级 (0~3)
/* 离开防抖计数器(连续 CAPVD 恢复到阈值以上才释放) */
extern uint8_t loop1_cnt_release; // 离开防抖计数
/*===========================================================================
* 全局状态变量 — 计数器
*===========================================================================*/

View File

@@ -50,6 +50,7 @@ uint8_t loop1_FLAG_IN;
uint8_t loop1_FLAG_OUT;
uint8_t loop1_FLAG_PLUSE;
uint8_t loop1_SensLevel;
uint8_t loop1_cnt_release;
/*===========================================================================
* 全局状态变量 — 计数器
@@ -288,6 +289,7 @@ void INIT_VD(void)
loop1_FLAG_IN = 0;
loop1_FLAG_OUT = 0;
loop1_FLAG_PLUSE = 0;
loop1_cnt_release = 0;
loop1_LC_HOLD = 0;
loop1_LC_Reset = 0;
@@ -360,15 +362,14 @@ void TMR3_GLOBAL_IRQHandler(void)
if (loop1_LPCNT == 0) {
if (loop1_CapCnt > 10) {
/*
* 修复: 先乘后除,避免截断为 0
* 原代码: loop1_LPCNT = (32768 / Xn) << 6 ← 小 Xn 时溢出
* 新代码: (32768UL << 6) / Xn = 2097152 / Xn
* 自适应测量窗口: MEASUREMENT_BASE / Xn
* 使归一化 Value ≈ 131072无需后续 >>6
*/
loop1_LPCNT = (32768UL << XNSUM_FOR_ORIGIN_FACTOR) / loop1_Xn;
loop1_LPCNT = MEASUREMENT_BASE / loop1_Xn;
PRINT("First_calc_loop1_LPCNT:%d, loop1_Xn:%d\n",
loop1_LPCNT, loop1_Xn);
if (loop1_LPCNT == 0) {
loop1_LPCNT = 1000;
loop1_LPCNT = 100;
}
loop1_CAPVD = 0;
loop1_CapSum = 0;
@@ -379,7 +380,7 @@ void TMR3_GLOBAL_IRQHandler(void)
loop1_CapSum += loop1_Xn;
if (loop1_CapCnt >= loop1_LPCNT) {
loop1_CAPVD = loop1_CapSum;
loop1_Origin = loop1_CAPVD >> XNSUM_FOR_ORIGIN_FACTOR;
loop1_Origin = loop1_CAPVD; // 不再 >>6
PRINT("First_capSum:%d, Origin:%d\n",
loop1_CapSum, loop1_Origin);
loop1_INI_LOOP = 0;
@@ -560,13 +561,11 @@ void TMR15_GLOBAL_IRQHandler(void)
*===========================================================================*/
void vd1_task(void)
{
uint32_t tmp_value;
if (loop1_Origin == 0) return;
/*--- 1. IIR 一阶低通滤波(对齐 M1H 公式) ---*/
tmp_value = loop1_Value >> XNSUM_FOR_ORIGIN_FACTOR;
loop1_CAPVD = get_flt_value(tmp_value, loop1_CAPVD);
/* Value 已经是 MEASUREMENT_BASE 级别的原始值,不再右移 */
loop1_CAPVD = get_flt_value(loop1_Value, loop1_CAPVD);
if (!loop1_VD_FLAG) {
/*================================================================
@@ -581,9 +580,8 @@ void vd1_task(void)
loop1_dlt_ORG = ((uint32_t)loop1_Origin * SensTable[loop1_SensLevel]) >> 16;
if (loop1_CAPVD < (loop1_Origin - loop1_dlt_ORG)) {
PRINT("Car_In, Value:%d, CAPVD:%d, Origin:%d, dlt:%d, freq:%d\n",
tmp_value, loop1_CAPVD, loop1_Origin,
loop1_dlt_ORG, g_crm_clocks_freq_struct.sclk_freq);
PRINT("Car_In, Value:%d, CAPVD:%d, Origin:%d, dlt:%d\n",
loop1_Value, loop1_CAPVD, loop1_Origin, loop1_dlt_ORG);
loop1_VD_FLAG = 1;
loop1_FLAG_IN = 1;
@@ -600,29 +598,40 @@ void vd1_task(void)
loop1_ORG_CNT = 0;
loop1_ORG_SUM = 0;
loop1_cnt_release = 0; // 重置离开防抖
}
} else {
/*================================================================
* 有车状态
*================================================================*/
/*--- 离开检测(滞回阈值 SensTable_1 ≈ SensTable 的 50% ---*/
/*--- 离开检测(滞回阈值 SensTable_1 ≈ SensTable 的 50%
* 增加 cnt_release >= 3 防抖:连续 3 次恢复到阈值以上才释放
* 避免因瞬间噪声导致误落杆 ---*/
loop1_dlt_ORG = ((uint32_t)loop1_Origin * SensTable_1[loop1_SensLevel]) >> 16;
if ((loop1_Origin - loop1_dlt_ORG) < loop1_CAPVD) {
PRINT("Car_OFF, Value:%d, CAPVD:%d, Origin:%d, dlt:%d, freq:%d\n",
tmp_value, loop1_CAPVD, loop1_Origin,
loop1_dlt_ORG, g_crm_clocks_freq_struct.sclk_freq);
loop1_cnt_release++;
if (loop1_cnt_release >= 3) {
PRINT("Car_OFF, Value:%d, CAPVD:%d, Origin:%d, dlt:%d\n",
loop1_Value, loop1_CAPVD, loop1_Origin, loop1_dlt_ORG);
loop1_VD_FLAG = 0;
loop1_FLAG_OUT = 1;
loop1_VD_HOLD = 0;
loop1_LC_HOLD = 0;
LEDB_OFF;
loop1_VD_FLAG = 0;
loop1_FLAG_OUT = 1;
loop1_VD_HOLD = 0;
loop1_LC_HOLD = 0;
LEDB_OFF;
loop1_ORG_CNT = 0;
loop1_ORG_SUM = 0;
Hold_CNT = 0;
loop1_ORG_CNT = 0;
loop1_ORG_SUM = 0;
Hold_CNT = 0;
loop1_cnt_release = 0;
}
} else {
/* CAPVD 又掉回阈值以下 → 重置防抖,车还在 */
if (loop1_cnt_release > 0) {
loop1_cnt_release = 0;
}
}
}
}
@@ -693,7 +702,7 @@ void loop_task_function(void *pvParameters)
_dbg_cnt++;
if (_dbg_cnt >= 200) { // 200 × 10ms = 2s
_dbg_cnt = 0;
PRINT("SET_DLY:%d, SET_SAFE:%d, Xn:%d, LPCNT:%d, "
PRINT("SET_DLY:%d, SAFE:%d, Xn:%d, LPCNT:%d, "
"CAPVD:%d, Origin:%d, VD:%d\n",
SET_DLY, SET_SAFE, loop1_Xn, loop1_LPCNT,
loop1_CAPVD, loop1_Origin, loop1_VD_FLAG);