LOP 厅外呼叫板 · 单片机与上位机交互协议

3 层电梯 LOP 系统:STM32F103 呼叫板(每层一块)与上位机(WPF / 未来 PLC)通过 CAN 250kbps 通信。
本文档完整说明双方如何交互、控制逻辑如何流转,为「用 PLC 代替上位机」提供协议与控制逻辑依据。

CAN 250kbps 标准帧 0x123 / 0x200 / 0x201 STM32F103 PLC 替代参考
输入关键词实时过滤。
快速开始 · 协议速查
三帧核心协议 + 一帧升级协议,全部标准帧,250kbps。
0x123 上位机 → 所有 LOP 板(广播)
轿厢状态帧,500ms 节流周期发送。8 字节:
字节含义值域
data[0]当前楼层1~3
data[1]运行方向0 停止 / 1 上行 / 2 下行
data[2]门状态0 关 / 1 开门中 / 2 开 / 3 关门中
data[3]目标楼层1~3
data[4]故障码低字节0=无故障
data[5]故障码高字节16 位故障码
data[6..7]保留0
0x200 LOP 板 → 上位机(事件触发)
呼梯呼叫帧,按钮按下沿触发发一帧(非周期轮询)。3 字节:
字节含义值域
data[0]本板楼层1~3
data[1]方向0 上行 / 1 下行
data[2]校验固定 0x55
0x201 上位机 → LOP 板(按楼层过滤)
灯控帧,登记状态变化时广播,只发变化的楼层方向。3 字节:
字节含义值域
data[0]楼层1~3
data[1]方向0 上行 / 1 下行
data[2]亮灭1 亮 / 0 灭
0x600 / 0x602 升级命令 / 应答(可选)
CAN Bootloader 升级协议,正常运行时不用,详见技能 stm32-can-bootloader。
系统架构
硬件拓扑与角色分工——先看清谁在总线上、各自负责什么。
硬件拓扑
┌────────────┐ CAN 总线 250kbps 标准帧 ┌────────────┐ │ 上位机 │ ──────────────────────────────→ │ 1F LOP 板 │ STM32F103 + 拨码=1 │ WPF / PLC │ ←────────────────────────────── │ 2F LOP 板 │ STM32F103 + 拨码=2 │ (控制器+显示)│ CANH / CANL(两端 120Ω) │ 3F LOP 板 │ STM32F103 + 拨码=3 └────────────┘ └────────────┘ │ └── 轿内 OLED(显示 0x123 状态,无按钮)
角色分工
LOP 板(单片机)厅外呼叫终端 ×3
:0x200 呼叫帧(按钮按下沿)
:0x123 状态帧(更新 OLED)、0x201 灯控帧(按楼层过滤控制指示灯)
硬件:PB10/PB11 按钮、PB12/PB13 指示灯、OLED(I2C)、PA0~PA3 拨码定义楼层
原则:按钮本地按下立即亮灯(即时反馈),最终熄灭由上位机 0x201 决定
上位机(当前 WPF / 未来 PLC)控制器 + 轿厢状态源
:0x123 状态帧(500ms 周期)、0x201 灯控帧(登记状态变化时)
:0x200 呼叫帧 → 登记呼梯 → 调度电梯 → 服务完成清除登记 → 广播灭灯
职责:电梯运行逻辑(方向/目标/门/故障)+ 灯状态维护 + 轿厢状态广播
协议帧详解 · 0x123 轿厢状态帧
上位机 → 所有 LOP 板广播。500ms 节流发送(SendInterval)。
0x123 标准帧 DLC=8
字节字段编码说明
0CurrentFloor1~3Clamp 到 1..3
1TravelDirection0/1/21=上、-1=下 → 1/2;停=0
2DoorState0~3Opening=1, Open=2, Closing=3, 其他=0
3TargetFloor1~3Clamp 到 1..3
4FaultCode L0~25516 位故障码低字节
5FaultCode H0~25516 位故障码高字节
6..7保留0
单片机校验:IDE=标准、RTR=数据、DLC≥6、data[0]∈1..3、data[1]≤2、data[2]≤3、data[3]∈1..3,任一不满足丢弃。
协议帧详解 · 0x200 呼叫帧
LOP 板 → 上位机。按钮按下沿触发,发一帧即止(事件驱动,不周期上报)。
0x200 标准帧 DLC=3
字节字段编码说明
0楼层1~3本板拨码楼层
1方向0/10 上行 / 1 下行
2校验0x55固定魔数
上位机严格校验(IsValidCallFrame):ID、标准帧、DLC≥3、data[2]==0x55、楼层 1~3、方向≤1,且必须是合法组合:
(1,0) 1F 上行 / (2,0)(2,1) 2F 双向 / (3,1) 3F 下行 —— 非法帧丢弃。
事件触发要点。按钮去抖 20ms 后只在「高→低」按下沿返回 1;按住不放不会重复发帧。CAN 邮箱忙时置 Pending 标志,每 20ms 重试装入邮箱,发成功才清——事件不丢,但绝不周期重发。
协议帧详解 · 0x201 灯控帧
上位机 → LOP 板广播。按楼层过滤:data[0] 必须等于本板楼层才响应。
0x201 标准帧 DLC=3
字节字段编码说明
0楼层1~3目标板楼层(其他板忽略)
1方向0/10 上行灯 / 1 下行灯
2亮灭1/01 亮 / 0 灭
发送规则(上位机):对比上次灯状态,只发变化的楼层方向。全量同步(首次 + 每 2s)只强制刷「亮」;「灭」只能由变化(true→false,服务完成清除)触发,首次灭不广播。
⚠️
灯误灭保护(最容易踩的坑)。如果全量同步无条件广播当前灯状态,会把「未登记的灭」发给单片机,覆盖本地按下的亮灯——表现为按按钮灯亮一下又灭。所以「灭」必须只由服务完成触发。
协议帧详解 · 0x600/0x602 升级帧
CAN Bootloader 升级协议,正常运行时不涉及,供将来批量升级用。详见技能 stm32-can-bootloader。
0x600 上位机 → 板(升级命令) [A5 进 / AA 探测]
data[1]=目标楼层或 0 广播,data[2]=0x55。应用侧只响应 PING(0xAA 回 ACK) 和 ENTER(A5 写 BKP 魔数复位进 Bootloader)。
交互流程 · 呼梯完整链路
从乘客按按钮到电梯服务完成灯熄灭,数据怎么流。
1. 乘客按 2F 上行按钮 2F LOP 板:去抖 20ms → 按下沿 → 本地 PB12 灯亮 + 发 0x200 [2, 0, 0x55] 上位机:RX 线程收到 → IsValidCallFrame 校验 ✓ → CallHall(2, up) → 控制器登记 2F 上行 2. 控制器处理呼梯 ElevatorController.Advance():检测 2F 上行登记 → 置 HallUpLamp[2] 亮 → 选择方向/目标 快照 LampState 变化 → UpdateLamps → 发 0x201 [2, 0, 1] 亮灯(2F 板灯保持亮) 3. 电梯运行与到站 上位机每 500ms 发 0x123 [楼层,方向,门,目标,故障] → 所有 LOP 板 OLED 实时显示 电梯到 2F → 开门 → 乘客进出 4. 服务完成 → 灭灯 控制器清除 2F 上行登记(HallUpLamp[2] true→false)→ 变化触发发 0x201 [2, 0, 0] 2F 板收到 → PB12 灯灭(只在门关到位后,见注意事项)
💡
关键。0x123 是唯一周期帧(500ms);0x200 事件触发;0x201 变化触发 + 每 2s 全量补刷亮。上位机靠这三条闭环,无轮询按钮。
交互流程 · 灯控同步规则
上位机侧 SendLampState 的完整判定逻辑(PLC 移植时照抄)。
SendLampState(floor, up, current, previous, force)
每拍对 4 个灯位调用(1F上 / 2F上 / 2F下 / 3F下):
跳过条件 1:首次(previous==null)且当前为灭 → 不广播(防覆盖本地亮灯)
跳过条件 2:状态无变化,且不是「全量同步强制刷亮」→ 不广播
发送:其余情况(亮变化 / 灭变化 / 全量同步且当前亮)→ 发 0x201
全量同步节奏 LampFullSyncInterval = 2s
首次打开 CAN 时 + 之后每 2s:对当前为亮的灯强制重发 0x201(防丢帧导致板灯与实际不一致);
发送失败时退避 100ms 重试,不更新 lastLamps 以便下轮补发。
交互流程 · 离线检测
LOP 板如何判断通讯未建立。
STATUS_TIMEOUT_MS = 1500ms
LOP 板连续 1.5s 未收到 0x123 → ElevatorStateOnline=0 → OLED 显示 CAN OFFLINE 界面(第 1 行显示 VER V1.3.0 版本号,含诊断统计行 BOFF/RX/OVFL/FLT)。收到任意合法 0x123 立即恢复在线。
⚠️
PLC 替代时注意。PLC 必须周期发 0x123(建议 ≤500ms),否则所有 LOP 板会切到离线界面。停梯但正常的电梯也要持续广播当前状态。
控制逻辑 · 电梯控制器(上位机侧)
当前 WPF 上位机的 ElevatorController 是纯函数状态机(100ms 步进),将来移植 PLC 的逻辑蓝本。
呼梯登记 CallHall(floor, up)
收到 0x200 → 置 HallUp/HallDown 中间点 → 控制器下一拍检测上升沿 → 登记(灯亮)→ 消费复位中间点(等价 PLC 复位中间点)。同一层同向重复呼叫会重新登记,电梯不空闲(真实时序:乘客 A 离开后 B 再呼)。
调度决策 方向/目标/顺路
按当前方向优先顺路响应(距离吸收 150 单位内)、层楼顺序、门开关状态机(TON 定时)推进。
3 层改造后的关键:中间层距顶层仅 1 层(=100 单位),"距离吸收"场景在 3 层不存在——顺路判断要按 3 层重排。
服务完成 → 灯灭
电梯到站开门 → 乘客进出 → 门重新关到位后清除呼梯登记(不是到站就清)→ 灯灭广播 0x201。
轿内选层(COP)无硬件,界面模拟按钮 → SetTarget(floor) 同一登记链路。
控制逻辑 · LOP 板(单片机侧)
统一程序烧 3 块板,拨码定义楼层,角色自动分支。
楼层识别 拨码 PA0~PA3
4 位拨码二进制:1F=0001, 2F=0010, 3F=0011。MAX_FLOOR=3,非法值 OLED 显示 DIP ERROR。
角色规则:1F 仅上行、顶层仅下行、中间层双向,无效方向按钮不响应。
主循环节拍 非中断轮询
按钮扫描 20ms;CAN 轮询每轮最多 8 帧(防饿死按钮/显示);OLED 只在 DisplayDirty 时刷新;
灯控 0x201 按楼层过滤(data[0]==FloorNumber 才响应,方向 data[1]≤1、亮灭 data[2]≤1 校验)。
控制逻辑 · 时序参数汇总
两端所有与交互相关的定时器。
定时参数表
参数位置用途
SendInterval500ms上位机0x123 状态帧节流
LampFullSyncInterval2s上位机灯控全量同步(只刷亮)
发送失败退避100ms上位机Transmit 失败重试间隔
控制器步进100ms上位机ElevatorController Tick
RX 轮询1ms+5ms上位机Receive 阻塞 1ms + Sleep 5ms
STATUS_TIMEOUT_MS1500msLOP 板未收 0x123 → 离线界面
按钮扫描/去抖20msLOP 板扫描周期 = 去抖稳定时间
邮箱重试20msLOP 板0x200 装入失败重试
OLED 掉线恢复500msLOP 板I2C 掉线重试间隔
PLC 替代上位机 · CAN 硬件方案
用 PLC 替换 WPF 上位机时,先解决 CAN 接入。
方案 1 PLC 自带/扩展 CAN
西门子 S7-1200/1500 选配 CAN 模块(如 CM CANopen 经网关),或用第三方 CANopen 主站模块。需确认支持标准帧 + 250kbps + 自定义 ID(本协议非标准 CANopen 对象,是裸 CAN 帧)。
方案 2 USBCAN 网关桥接(推荐过渡)
保留 PC 上的 USBCAN 转接程序(复用现有 ECAN.cs 封装),PC 与 PLC 之间用 Modbus TCP/OPC UA 交换数据。
PLC 程序只写控制逻辑,CAN 收发仍由 PC 网关完成——风险最低,协议帧解析完全复用。
PLC 替代上位机 · 需实现的逻辑
把当前 WPF 上位机三个职责搬进 PLC(或网关+PLC 分工)。
① 收 0x200 → 登记呼梯
CAN 收到 0x200 → 校验(楼层1~3/方向0~1/0x55/合法组合)→ 置位外呼中间点 → 上升沿登记(等价当前 CallHall → 中间点 → 控制器消费)。
② 发 0x201 灯控(登记亮/服务完灭)
登记时发亮;门关到位后清登记发灭。必须遵守:全量同步只刷亮、灭只由变化触发、首次灭不广播——否则按按钮灯会闪灭。
③ 发 0x123 轿厢状态(500ms 周期)
周期广播当前楼层/方向/门/目标/故障。停梯也必须持续广播(否则 LOP 板 1.5s 后离线)。
故障码 16 位:低字节 data[4]、高字节 data[5]。
④ 电梯调度核心逻辑
方向选择(当前方向顺路优先)、目标楼层、门状态机(TON 定时)、故障处理。
现有 ElevatorController 是纯函数状态机(无 async/await,时间基准 ElapsedSeconds),可直接逐行翻译为 SCL(详见技能 plc-sil-verification)。
PLC 替代上位机 · 验收清单
替换后逐项验证,确保行为与 WPF 版一致。
验收测试项
1. 按 1F 上行 → 1F 灯亮 + PLC 登记 → 电梯下行到 1F 开门
2. 服务完成门关后 → 1F 灯灭(不是开门瞬间灭)
3. 按 2F 双向 → 2F 两灯亮 → 电梯响应一个方向后对应灯灭
4. 运行中按同向中间层 → 顺路响应(3 层无距离吸收,直接顺路)
5. 拔掉上位机 CAN → 1.5s 后所有 LOP 板离线界面;恢复 → 在线
6. 长时间运行(≥2s 全量同步窗口)灯状态始终与实际一致
7. 故障置位 → 0x123 故障码正确 → LOP 板 OLED 显示
注意事项
联调实测沉淀的经验与坑。
💡
灯灭时机。PLC 外呼灯在「门重新关到位」后才熄灭(接客等待释放逻辑),不是到站开门时——断言灯灭必须等门关,否则误报。
💡
0x123 是心跳。LOP 板把 0x123 当「通讯存在」信号,不只是显示数据。PLC 必须保证周期发送,哪怕电梯完全停着。
事件 vs 周期。按钮呼叫是事件(按下发一帧);灯控是变化+全量补刷;状态是周期。PLC 实现时别把按钮改成周期扫描上报——总线浪费且时序不一致。
LOP 板本地亮灯是「乐观反馈」。按下即亮,给乘客即时反馈;真正权威状态在上位机/PLC。两者冲突时以 0x201 为准(这就是灯控规则存在的意义)。
⚠️
广播升级(0)危险。升级协议广播会令所有板同时进升级模式,一次失败全擦。多板必须逐块指定楼层升级(详见技能 stm32-can-bootloader)。
⚠️
急停等安全信号不要走 CAN。按电梯安全规范,急停/安全回路必须硬接线直连控制柜,不允许由通信链路承载(见会话讨论)。CAN 只做状态/呼叫/灯控。
LOP 交互协议 · 单片机 ⇄ 上位机(PLC 替代参考) 生成于 2026-08-10 · 依据 External_CAN V1.3.0 + elevator 源码
没有匹配的内容,换个关键词试试。