Files
DLD154V4B/docs/reference_analysis.md
2026-06-22 18:34:13 +08:00

11 KiB
Raw Blame History

参考项目代码分析

分析对象M1HSTC12C5202 / C和 TLD-110P87LPC762 / ASM 目的:为 DLD154V4BAT32F421提供算法参考


一、项目概览

项目 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)

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 = 1SENS = 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:  无车!

基线跟踪(仅无车时)

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-1104 取中值)
  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 级:

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 完整分析