diff --git a/project/at32f421_board/at32f421_board.c b/project/at32f421_board/at32f421_board.c index 1d6930b..82dc4f3 100644 --- a/project/at32f421_board/at32f421_board.c +++ b/project/at32f421_board/at32f421_board.c @@ -236,7 +236,7 @@ void loop_timer_io_init(void) g_tmr_input_config_struct.input_channel_select = TMR_SELECT_CHANNEL_2; g_tmr_input_config_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT; g_tmr_input_config_struct.input_polarity_select = TMR_INPUT_RISING_EDGE; - _div = TMR_CHANNEL_INPUT_DIV_4; + _div = TMR_CHANNEL_INPUT_DIV_2; tmr_input_channel_init(TMR3, &g_tmr_input_config_struct, _div); for(i = 0; i< _div; i++){ g_input_div *= 2; diff --git a/utilities/at32f421_freertos_demo/inc/TaskLoop.h b/utilities/at32f421_freertos_demo/inc/TaskLoop.h index 7362eb9..f8e9776 100644 --- a/utilities/at32f421_freertos_demo/inc/TaskLoop.h +++ b/utilities/at32f421_freertos_demo/inc/TaskLoop.h @@ -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; // 离开防抖计数 + /*=========================================================================== * 全局状态变量 — 计数器 *===========================================================================*/ diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c index df3a921..24c7d66 100644 --- a/utilities/at32f421_freertos_demo/src/TaskLoop.c +++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c @@ -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);