diff --git a/docs/reference_analysis.md b/docs/reference_analysis.md new file mode 100644 index 0000000..095580b --- /dev/null +++ b/docs/reference_analysis.md @@ -0,0 +1,379 @@ +# 参考项目代码分析 + +> 分析对象:M1H(STC12C5202 / C)和 TLD-110(P87LPC762 / ASM) +> 目的:为 DLD154V4B(AT32F421)提供算法参考 + +--- + +# 一、项目概览 + +| 项目 | MCU | 语言 | 通道 | 年份 | 代码量 | +|------|-----|------|------|------|--------| +| M1H | STC12C5202 (8051) | C | 1 路 | 2008 | 379 行 | +| TLD-110 | P87LPC762 (8051) | ASM | 1~2 路 | 2003~2006 | 1563 行 | + +**共同点:** +- 都基于 8051 架构 +- 都使用线圈 LC 谐振频率偏移检测车辆 +- 都通过 DIP 开关设置灵敏度 +- 都输出继电器信号 + +--- + +# 二、M1H 分析 + +## 2.1 整体数据流 + +``` +线圈振荡 → PCA捕获(CCAP0) → 周期差值(Xn) + │ + ┌───────────────┴────────────────┐ + ▼ (初始化) ▼ (正常运行) + 累加 Xn 测一个完整周期 累加 Xn 满 LPCNT 次 + LPCNT = 32768 / Xn Value = ΣXn + Origin = ΣXn (首窗口) │ + │ ▼ + │ IIR 低通滤波 + │ CAPVD = α·Value + (1-α)·CAPVD + │ α = 79/256 + │ │ + └─────────┬───────────────────────┘ + ▼ + ┌─── 有车? ───┐ + ▼ 无车 ▼ 有车 + 慢速基线跟踪 ┌──进入检测──┐ + ORG_SUM += CAPVD │ │ + 每100次平均→Origin ▼ 进入 ▼ 离开 + CAPVD < CAPVD > + Origin-阈值 Origin-恢复阈值 +``` + +## 2.2 频率测量 (CAP0 ISR) + +``` +捕获中断触发 + ├─ 读 CCAP0H:L → CapThis (16bit 捕获值) + ├─ 首次中断: CapLast = CapThis, 置 RF_FLAG + └─ 后续中断: + ├─ Xn = CapThis - CapLast (相邻边沿周期差) + ├─ CapLast = CapThis + └─ 累加 Xn → CapSum, 计数 CapCnt +``` + +**测量窗口自适应:** +- 初始化阶段:等 CapCnt > 10 后,`LPCNT = 32768 / Xn` +- LPCNT 含义:每 LPCNT 次捕获产生一个 Value(约 1 秒的积分窗口) +- Xn 大(频率低) → LPCNT 小 → 测量快 +- Xn 小(频率高) → LPCNT 大 → 测量更精确 + +## 2.3 IIR 滤波 (VD1_TASK) + +```c +if (Value > CAPVD) + CAPVD = CAPVD + ((Value - CAPVD) * 79) >> 8; +else + CAPVD = CAPVD - ((CAPVD - Value) * 79) >> 8; +``` + +等效公式:**CAPVD_new = 0.3086 × Value + 0.6914 × CAPVD_old** + +- 响应速度:约 3~4 次更新达到 63% +- 对单个野值有良好抑制 + +## 2.4 检测算法 + +### 灵敏度表 + +| DIP (SA1,SA0) | SENS | 进入阈值(比例) | 离开阈值(比例) | +|---------------|------|---------------|---------------| +| 00 | 3 (最高灵敏) | 10/65536 ≈ 0.015% | 9/65536 ≈ 0.014% | +| 01 | 2 | 36/65536 ≈ 0.055% | 18/65536 ≈ 0.027% | +| 10 | 1 | 108/65536 ≈ 0.16% | 72/65536 ≈ 0.11% | +| 11 | 0 (最低灵敏) | 216/65536 ≈ 0.33% | 108/65536 ≈ 0.16% | + +> 注:DIP 拨到 ON = 1,SENS = 3 - (sw & 0x03) + +### 进入判据 + +``` +dlt_ORG = (Origin × SensTable[SENS]) >> 16 +IF CAPVD < Origin - dlt_ORG: 有车! +``` + +### 离开判据(滞回) + +``` +dlt_ORG = (Origin × SensTable1[SENS]) >> 16 // 约为进入阈值的 50% +IF CAPVD > Origin - dlt_ORG: 无车! +``` + +### 基线跟踪(仅无车时) + +```c +ORG_SUM += CAPVD; +if (++ORG_CNT == 100) { + Origin = ORG_SUM / 100; // 每 100 次平均更新 + ORG_CNT = 0; + ORG_SUM = 0; +} +``` + +## 2.5 时序状态机 (Timer1 ISR, 50ms tick) + +``` + IN_DELAY=10 OUT_DELAY=38 + [空闲] ──有车──→ [进入延时] ──超时──→ [有车确认] + ↑ │ + │ 车辆离开 + │ ↓ + └──脉冲结束──── [脉冲输出] ←──超时── [离开延时] + PLUSE_DELAY=19 +``` + +| 参数 | 值 | 时间 | +|------|-----|------| +| IN_DELAY | 10 | 500ms (进入防抖) | +| OUT_DELAY | 38 | 1.9s (离开防抖) | +| PLUSE_DELAY | 19 | 950ms (脉冲宽度) | + +## 2.6 拨码逻辑 + +``` +SA_1(PA0), SA_2(PA1) → 灵敏度 (4级) +SW_3(PA2) → 0=存在输出, 1=脉冲输出 +SW_4(PA3) → 0=无延时, 1=延时 +SW_5(PA4) → 安全复位 +``` + +拨码去抖:连续 5 次读取一致才生效。 + +## 2.7 输出逻辑 + +``` +SOLA (继电器1) = VD_FLAG | FLAG_OUT (有车或有离开延时) +SOLB (继电器2) = VD_FLAG | FLAG_OUT (SET_PLUS模式) + FLAG_PULSE (非脉冲模式) +``` + +--- + +# 三、TLD-110 分析 + +## 3.1 整体数据流 + +``` +线圈振荡边沿 → EX0中断触发 + │ + ▼ + Timer0定时 + Timer1计数 + (门控频率测量法) + │ + ▼ + 4次扫描取中值 + (SUM - MAX - MIN) / 2 → SQ + │ + ┌───────────┴───────────┐ + ▼ 初始化 ▼ 运行 + 频率范围校验 Δ = Q - SQ + 32样本平均→Q基线 │ + INI_T0校准 ├─ Δ>0 (频率↓): 可能来车 + CAL_TH(阈值计算) │ ├─ Δ > TR: SET A_VD + │ └─ Δ ≤ TR: 累加到APY + │ 16次后更新Q基线 + └─ Δ≤0 (频率↑): + ├─ A_VD=1 且 Δ < TF: 离开 + └─ A_VD=0: 正常 +``` + +## 3.2 频率测量 (MAIN_VD → GET_VD) + +**门控频率测量法:** + +``` +1. Timer0 装载 INI_T0,向下计数(门控时间 ≈ 50ms) +2. Timer1 清零,向上计数(对线圈脉冲计数) +3. 使能 EX0 外部中断 +4. 线圈第一个上升沿 → EX0 ISR: 启动 TR0 + TR1 +5. Timer0 溢出 → TF0 ISR: 停止 TR0 + TR1 +6. 读 Timer1 的 TH1:TL1 → 脉冲计数 +``` + +**中值滤波(4 次采样):** +- 记录 4 次测量的 SUM、MAX、MIN +- 结果 = (SUM - MAX - MIN) / 2 → 相当于平均中间两个值 +- 能有效剔除单个毛刺 + +## 3.3 初始化流程 + +``` +1. TEST_VD: 粗测频率 → 软件延时门控 +2. 频率范围校验: + - 下限: SQ > 0x0154 (频率不过低) + - 上限: SQ < 0x0DF0 (频率不过高) + - SQ = 0 → STATUS=1 (线圈断开) +3. 计算 INI_T0: INI_T0 = 0xFFFF - (0xC350 / SQ) + → 使门控时间内计数值约为 3125 +4. 32 个样本累加 → 右移 5 位 (/32) → 校准基线 Q + - 校验: Q ≠ 0 (否则重新初始化) +``` + +## 3.4 检测算法 + +### 灵敏度表 + +| TAB_SENS | HEX | DEC | 说明 | +|----------|-----|-----|------| +| [0] | 0x46 | 70 | 最低灵敏度 | +| [1] | 0x37 | 55 | | +| [2] | 0x28 | 40 | | +| [3] | 0x14 | 20 | 最高灵敏度 | + +### 阈值计算 (CAL_TH_A) + +``` +进入阈值 TR = Q × SensTable[SENS] / 100000 +离开阈值 TF = Q × SensTable[SENS+1] / 100000 // 更严格 +``` + +以 Q=100000 为例: + +| SENS | TR(进入) | TF(离开) | 说明 | +|------|----------|----------|------| +| 3 (高灵敏) | 20 → 0.02% | 下一档=70 → 0.07% | 离开更容易 | +| 2 | 40 → 0.04% | 55 → 0.055% | | +| 1 | 55 → 0.055% | 70 → 0.07% | | +| 0 (低灵敏) | 70 → 0.07% | — | 最不灵敏 | + +### 动态基线更新 (ADJ_A_QT) + +``` +当 Δ≤TR (频率变化不跨阈值): + 累加 SQ 到 APY (16次) + 16次后: + 如果无车、无输出、无延时: + Q = APY_sum / 32 → 更新基线 + 否则: 不更新 + APY清零 +``` + +> TLD-110 的基线更新比 M1H 更谨慎——有车时绝不更新基线。 + +## 3.5 方向判别 (MODEL=200) + +``` +ATOB: A先有车 → B后有车 → 方向 A→B +BTOA: B先有车 → A后有车 → 方向 B→A + +触发条件: + A_VD=1, B_VD=1 → 判断先后 + - 如果先有 ATOB flag: 方向 A→B + - 如果先有 BTOA flag: 方向 B→A +``` + +## 3.6 输出模式 + +| MODE | 说明 | A_SOL | B_SOL | +|------|------|-------|-------| +| 0 | 存在输出 | OUT_A (离开延时后) | OUT_B | +| 1 | 进入脉冲 | IN_A | IN_B | +| 2 | 离开脉冲 | !IN_A & A_VD | !IN_B & B_VD | +| 3 | 存在+LED | A_VD \| OUT_A | B_VD \| OUT_B | +| 4 | 方向 A→B | ATOB | BTOA | +| 5 | 方向+延时 | ATOB & IN_B | BTOA & IN_A | + +## 3.7 故障指示 (FLASH_LED) + +通过 LED 闪烁模式指示线圈状态: + +| STATUS | 故障 | LED 闪烁 | +|--------|------|----------| +| 0 | 正常 | 灭 | +| 1 | 线圈断开(SQ=0) | 均匀闪烁 | +| 2 | 频率过低 | 1-4-6-7 ON 短码 | +| 3 | 频率过高 | 1-4-6-7-8-9 ON 长码 | + +--- + +# 四、两项目关键差异对比 + +| 特性 | M1H | TLD-110 | +|------|-----|---------| +| 频率测量 | PCA 周期捕获 | 门控脉冲计数 | +| 滤波方式 | IIR 指数平滑 (α=0.31) | 4取中值 | +| 基线跟踪 | 100次滑动平均(有车也跟踪) | 16次累积更新(有车不更新) | +| 滞回 | 进入/离开用不同阈值表 | 进入/离开用相邻灵敏度档 | +| 进入判断 | CAPVD < Origin - 阈值 | ΔQ > TR (delta超阈值) | +| 防抖 | IN_DELAY=500ms, OUT_DELAY=1.9s | DELAY_VALUE=10或40 | +| 方向判别 | 不支持 | 支持 (ATOB/BTOA) | +| 故障检测 | 仅 LOOP_OK | 断开/过低/过高 3种 | + +--- + +# 五、DLD154V4B 建议采用的方案 + +综合两个参考项目的优点: + +## 5.1 频率测量 + +使用 AT32F421 的 **TIM3_CH2 输入捕获**(硬件捕获),结合 DMA 或定时器溢出中断: + +``` +方案:TIM3 自由运行计数 + CH2 捕获模式 +- 每次捕获中断读取 CCR2 → 得到相邻边沿时间差 +- 同 M1H:计算 Xn,累加 N 次产生 Value +``` + +## 5.2 滤波 + +**级联滤波:** +1. 第一级:中值滤波(仿 TLD-110,4 取中值) +2. 第二级:IIR 指数平滑(仿 M1H,α 可配置) + +## 5.3 检测 + +``` +进入: CAPVD < Origin - Origin × SensTable[SENS] / 65536 +离开: CAPVD > Origin - Origin × SensTable1[SENS] / 65536 +``` + +## 5.4 基线跟踪 + +仿 TLD-110:**有车时冻结基线**,无车时慢速跟踪。 + +``` +if (!VD_FLAG) { + ORG_SUM += CAPVD; + if (++ORG_CNT >= 64) { + Origin = ORG_SUM >> 6; // /64 + ORG_CNT = 0; ORG_SUM = 0; + } +} +``` + +## 5.5 时序 + +沿用 M1H 的 Timer 状态机模式(用 AT32F421 的 SysTick 或 TIM1): + +| 参数 | 默认值 | 说明 | +|------|--------|------| +| IN_DELAY | 10 tick | 进入防抖 | +| OUT_DELAY | 38 tick | 离开防抖 | +| PULSE_WIDTH | 19 tick | 脉冲输出宽度 | +| HOLD_TIME | 不限 | 安全模式保持时间 | + +## 5.6 灵敏度表 + +沿用 M1H 的 4 级: + +```c +const uint16_t SensTable[4] = {216, 108, 36, 10}; // 进入 +const uint16_t SensTable1[4] = {108, 72, 18, 9}; // 离开(滞回) +``` + +--- + +# 修订记录 + +| 版本 | 时间 | 说明 | +|------|------|------| +| V1.00 | 2026-06-22 | 初版,M1H + TLD-110 完整分析 |