Files
DLD154Pro/docs/modbus-active-report-analysis.md
T
wangfq 2088cc267c docs: Modbus 主动上报 MCU 资源占用分析
- ISR 层不受 TX 阻塞影响 (TMR0/TMR1 独立运行)
- @9600 活动态 TX 阻塞 45ms (30% CPU), 余量 55ms/150ms → 可行但临界
- @19200 TX 阻塞减半至 22ms (15% CPU) → 推荐
- RAM 增量 <170B, Flash 增量 ~8.5KB
- 优化建议: 提高波特率 / TX FIFO 成组填充 / 间隔参数可配
2026-07-30 17:34:17 +08:00

9.4 KiB
Raw Blame History

DLD154Pro Modbus 主动上报 — MCU 资源占用分析

CH591R RISC-V @60MHz | 18KB RAM | BLE + 单路线圈 + RS485


1. 系统并发任务概览

┌──────────────────────────────────────────────────────┐
│ ISR 层 (抢占式, 不受主循环阻塞影响)                    │
│                                                      │
│  TMR0 捕获 ISR  ──── 线圈频率测量 (每周期触发)        │
│  TMR1 5ms ISR    ──── 50ms tick / 继电器 / LED / PWM │
│  UART0 RX ISR    ──── RS485 接收缓冲                  │
│  BLE RF ISR      ──── 蓝牙链路层                      │
│                                                      │
├──────────────────────────────────────────────────────┤
│ 主循环 (round-robin, 被 rs485_send 阻塞时可暂停 45ms) │
│                                                      │
│  TMOS_SystemProcess()  ── BLE 协议栈调度              │
│  poll_dbn_ble()        ── BLE 数据收发                │
│  cjq_srv()             ── 线圈算法 / 进出车检测        │
│  opt_input_poll()      ── 光耦防抖 / 状态机           │
│  modbus_poll()         ── Modbus 帧处理 + 主动上报 TX  │
└──────────────────────────────────────────────────────┘

关键事实: ISR 层永远不受 rs485_send 阻塞影响。线圈捕获/继电器输出/光耦消抖(TMR1 部分)在中断上下文运行,实时性有保证。


2. CPU 时间预算分析

2.1 中断负载 (固定开销,不可压缩)

中断源 频率 单次耗时 CPU 占比
TMR0 捕获 ~60 kHz (50120 kHz 线圈) ~25 cycles ~2.5%
TMR1 5ms 200 Hz ~200 cycles (含 PWM 呼吸) ~0.07%
UART0 RX 主机轮询时偶发 ~50 cycles 可忽略
BLE RF 连接维护 ~30ms 间隔 ~500 cycles ~0.03%
ISR 合计 ~2.6%

TMR0 捕获 ISR 是最重的固定负载。线圈频率越高,中断越密。

2.2 主循环 (正常状态,无主动上报 TX)

任务 单次耗时 说明
TMOS_SystemProcess ~1.5 ms BLE 协议栈 (底层在 ISR,这里是调度)
poll_dbn_ble ~0.5 ms 无待发数据时快速返回
cjq_srv ~1.0 ms CAP_OK 触发时跑 vd1_task (IIR+基线+检测)
opt_input_poll ~0.3 ms 3 样本多数表决 + 状态机分支
modbus_poll (RX only) ~0.1 ms 检查缓冲 + CRC 校验

主循环一次约 3.4 ms。两次 CAP_OK 间隔 ~8.74ms,主循环约跑 2.5 次/测量窗,时间充裕。

2.3 主动上报 TX 阻塞时间

rs485_send 是逐字节忙等的:

for (i = 0; i < len; i++) {
    while (R8_UART0_TFC != 0);  // ← 等 TX FIFO 全空 (→ 等上一个字节发完)
    R8_UART0_THR = data[i];     // 写 1 字节到 FIFO
}

UART0 TX FIFO 容量 8 字节,但代码不等 FIFO 有空间就写满 8 字节,而是每写 1 字节就等 FIFO 全空。这意味着每字节都经历完整的 1.04ms 传输等待。

帧类型 字节数 传输时间 @9600 传输时间 @19200 传输时间 @38400
全数据块上报 (FC 0x04) 43B 44.8 ms 22.4 ms 11.2 ms
异常响应 5B 5.2 ms 2.6 ms 1.3 ms
写回显 8B 8.3 ms 4.2 ms 2.1 ms

2.4 主动上报各速率下的 CPU 占用

150ms 活动间隔 (最坏情况):

每 150ms 窗口:
  TX 阻塞        44.8 ms  ← rs485_send(43B)
  主循环正常计算  ~50 ms  ← 150 - 44.8 - 余量
  可用于 BLE/算法 ~55 ms  ← 剩余预算

主循环 CPU 占比: (44.8 + 50) / 150 = 63%
其中 TX 阻塞占比: 44.8 / 150 = 30%

800ms 空闲间隔:

TX 阻塞占比: 44.8 / 800 = 5.6%
主循环 CPU 占比: ~30%

继电器翻转事件 (立即上报):

TX 阻塞 44.8ms,单次冲击。翻转频率低(最多每秒数次进出车),不构成持续负载。

3. 关键风险点

3.1 ⚠️ 主循环阻塞 45ms 期间的影响

rs485_send 阻塞期间,以下主循环任务被暂停:

任务 影响 严重程度
cjq_srv (线圈算法) CAP_OK 积压 ~5 次 (45ms ÷ 8.74ms)。恢复后主循环逐次消化,算法不丢数据,但响应延迟 +45ms 🟡 轻微
opt_input_poll (光耦) 防抖采样暂停 45ms。光耦输入若在此期间变高又变低,可能丢失 <45ms 的短脉冲 🟡 轻微
TMOS_SystemProcess (BLE) BLE 协议栈调度延迟 45ms。连接监控超时通常 ≥2s,不受影响 🟢 安全
modbus_poll (RX) 主机若在 TX 期间发来命令,UART ISR 正常收进缓冲,TX 结束后才处理 → 响应延迟 +45ms 🟡 轻微

3.2 不受影响的部分

机制 原因
继电器输出 TMR1 ISR (5ms) 独立运行,不经过主循环
线圈频率测量 TMR0 捕获 ISR 独立运行
光耦复位 (模式 6) opt_input_poll 中的复位逻辑暂停 45ms,但 400ms 的复位门槛远大于阻塞时间
UART 接收 ISR 独立填充 _rx_buf

3.3 🟢 结论

@9600 波特率,150ms 主动上报可行。 30% TX 阻塞是临界值——主循环仍有 ~55ms/150ms 的余量处理线圈算法和 BLE。不会丢检测事件,不会断蓝牙,继电器输出不受影响。


4. RAM 占用

4.1 新增静态变量 (BSS)

变量 大小 说明
_auto_rpt_enable 1B 主动上报使能标志
_active_threshold 2B 活动阈值
_rpt_last_ms 4B 上次上报时刻
_rpt_active / _rpt_hyst_cnt 2B 速率状态机
_last_relay_off_10ms 4B 继电器释放时刻
_last_relay_on_10ms 4B 继电器吸合时刻
_last_relay_state 1B 继电器边沿检测
_misc_time_type 2B 时间类型
_misc_time_value 4B 时间值 10ms
_relay_engage_cnt 4B 继电器累计次数
合计 28B

4.2 栈峰值

调用链 栈占用
modbus_poll() 局部变量 ~20B
send_full_data() 局部 buf[43] 43B
build_full_data() 局部 buf[38] + 临时变量 ~60B
rs485_send() 局部变量 ~10B
crc16() 局部变量 ~4B
调用链合计 ~140B

加中断嵌套预留 ~200B,栈峰值约 350B。CH591R 默认栈 2KB(可配置),余量充足。

4.3 总体 RAM

项目 大小
新增 BSS 28B
栈峰值增量 ~140B (Modbus 调用链)
CRC16 表 512B (const → Flash,不计 RAM)
RAM 增量 ~170B

CH591R 共 18KB RAM(含 BLE 协议栈 + 应用),Modbus 模块新增 < 1%。


5. Flash 占用

文件 大小
rs485_modbus.c ~8.5 KB
rs485_modbus.h ~2.2 KB
rs485_700bs.c 增量 (去 static) ~0
peripheral_main.c 增量 (分派) ~20B
合计 ~8.5 KB

CH591R Flash: 256KB (应用区 28KB 或 18KB,取决于 OTA 配置)。增量约占应用区 30%28KB 配置)或 47%18KB 配置)。18KB OTA 配置下偏紧


6. 优化建议

6.1 提高波特率 (影响最大)

波特率 TX 阻塞 (43B) 活动态 CPU 占比 改善
9600 44.8 ms 30% 基线
19200 22.4 ms 15% ↓50%
38400 11.2 ms 7.5% ↓75%
115200 3.7 ms 2.5% ↓92%

建议: 开启主动上报时,波特率至少用 19200。CH591R UART0 支持到 6 Mbps,硬件无瓶颈。

6.2 优化 TX FIFO 利用率 (代码级)

当前每字节等 FIFO 全空,改为填充 8 字节后再等:

void rs485_send_fast(const uint8_t *data, uint8_t len) {
    RS485_RE_TX();
    mDelayuS(100);
    uint8_t i = 0;
    while (i < len) {
        uint8_t space = 8 - R8_UART0_TFC;  // FIFO 剩余空间
        uint8_t chunk = (len - i < space) ? (len - i) : space;
        for (uint8_t j = 0; j < chunk; j++)
            R8_UART0_THR = data[i + j];
        i += chunk;
        if (i < len)
            while (R8_UART0_TFC >= 8);  // 等至少 1 字节空间
    }
    while (R8_UART0_TFC != 0);
    mDelayuS(500);
    RS485_RE_RX();
}

效果:不减少总 TX 时间(波特率决定),但减少忙等循环次数 43→6 次,降低指令开销。

6.3 活动上报间隔可调

当前硬编码 150ms/800ms。可考虑通过 HR 寄存器暴露间隔参数,让主机根据场景调优。


7. 总结

维度 评估 说明
实时性 安全 ISR 层不受 TX 阻塞影响;主循环延迟 45ms 可接受
CPU 🟡 @9600 临界 活动态 30% TX 阻塞,主循环仍有 55ms 余量
CPU 🟢 @19200 充裕 活动态 15% TX 阻塞,余量充足
RAM 🟢 充裕 增量 < 170B, < 1% 总 RAM
Flash 🟡 18KB OTA 配置偏紧 增量 ~8.5KB,占应用区 47%
BLE 🟢 安全 45ms 远小于连接超时 (≥2s)
线圈检测 🟢 安全 TMR0/TMR1 ISR 独立,不丢边沿