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

380 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 参考项目代码分析
> 分析对象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)
```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 = 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: 无车!
```
### 基线跟踪(仅无车时)
```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-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 级:
```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 完整分析 |