协议设计 HMI
HMIS 协议:用会话化二进制帧取代 DGUS 串口屏协议
V1.1 版本废弃了 USART1 上的 DGUS 5A A5 变量协议,改为全新的 HMI Session Protocol(HMIS)。这不是简单的帧格式替换——是整个通信模型的升级。
为什么废弃 DGUS
DGUS 变量协议的核心是 VP 地址模型:固件向屏的指定地址(如 0x3000)写数据,屏显示该地址的内容。HMI 上位机通过抓取屏的通信来间接获取设备信息。这个模式存在三个根本问题:
- HMI 维护两套协议栈(USART1 DGUS + USART3 20B 帧)
- 参数地址、HMI 配置、固件参数三处耦合——新增参数要改三处
- 日志、事件共用变量协议语义,扩展成本高
HMIS 帧格式
| SOF(2) | VER(1) | TYPE(1) | SEQ(2) | CMD(1) | FLAGS(1) | LEN(2) | PAYLOAD(N) | CRC16(2) |
| 55 AA | 0x01 | 0x01 | 小端 | 0x30 | 0x00 | 0+.. | 0..128B | Modbus |
SOF: 固定 0x55 0xAA
VER: 协议版本,首版 0x01
TYPE: 0x01=请求 0x02=响应 0x03=事件 0x04=日志 0x05=心跳
SEQ: 会话序号,请求方递增,响应带相同的 SEQ
CMD: 命令码
FLAGS:标志位(bit2=错误)
LEN: Payload 长度(小端)
CRC16:从 VER 到 Payload 末尾
能力声明机制
HMI 连接后,固件通过 DEVICE_INFO 响应返回能力位图——HMI 据此知道固件支持什么功能:
// 能力位图(16 位)
#define HMI_CAP_SESSION_BASE 0x0001 // 基础会话 (HELLO/DEVICE_INFO/HEARTBEAT)
#define HMI_CAP_PARAM_DIRECTORY 0x0002 // 参数目录 (0x10/0x11)
#define HMI_CAP_PARAM_RW 0x0004 // 参数读写 (0x12/0x13)
#define HMI_CAP_PARAM_PERSIST 0x0008 // 参数持久化 (0x14/0x15/0x16)
#define HMI_CAP_STREAM_SUBSCRIBE 0x0010 // 推送订阅 (0x22/0x23)
#define HMI_CAP_EVENT_PUSH 0x0020 // 事件推送 (0x40)
#define HMI_CAP_LOG_PUSH 0x0040 // 日志推送 (0x41)
#define HMI_CAP_STACK_SNAPSHOT 0x0080 // 栈快照推送 (0x42)
#define HMI_CAP_DEVICE_STATUS 0x0100 // 状态查询 (0x20)
#define HMI_CAP_ALARM_STATUS 0x0200 // 报警查询 (0x21)
#define HMI_CAP_PACKER_FLOW 0x2000 // 20B 协议控制/流程 (0x40-0x44)
命令分类
| 范围 | 命令码 | 说明 |
|---|---|---|
| Session | 0x01 HELLO | 连接握手 |
| 0x02 DEVICE_INFO | 设备信息+能力 | |
| 0x03 HEARTBEAT | 心跳(3 秒间隔) | |
| 参数 | 0x10 GET_GROUP_LIST | 参数分组列表 |
| 0x11 GET_PARAM_LIST | 某组参数定义 | |
| 0x12 GET_PARAM_VALUES | 批量读值 | |
| 0x13 SET_PARAM_VALUES | 批量写值 | |
| 0x14 SAVE_PARAMS | 保存到 EEPROM | |
| 0x15 LOAD_PARAMS | 从 EEPROM 加载 | |
| 0x16 LOAD_DEFAULTS | 恢复默认 | |
| 状态 | 0x20 DEVICE_STATUS | 运行状态+阶段码 |
| 0x21 ALARM_STATUS | 报警状态 | |
| 订阅 | 0x22/0x23 | 订阅/取消推送流 |
| 控制 | 0x30 CONTROL_RUN_STATE | 启停 |
| 0x31 TRIGGER_BAG | 出袋 | |
| 0x32 TRIGGER_SEAL | 封口 | |
| 0x33 TRIGGER_DELIVER | 投料 | |
| 0x34 CLEAR_FLAG | 清标志 | |
| 0x35 RESET_FAULT | 故障复位 | |
| 0x36 STEPPER_JOG | 步进点动 | |
| 0x37 DC_MOTOR_JOG | 直流点动 | |
| 推送 | 0x40 EVENT_PUSH | 事件上报 |
| 0x41 LOG_PUSH | 日志推送 | |
| 0x42 STACK_SNAPSHOT | 栈水位快照 |
控制命令(0x30~0x37)在固件内部桥接到 20B 协议,复用已有的协议处理逻辑:
// packer_hmi_proto.c — 控制命令桥接
static void hmi_handle_control_run_state(const uint8_t *payload, uint8_t len) {
app_packer_command_t cmd;
// 构造 20B 协议的内部命令
cmd.func = 0x40; // CONTROL
cmd.arg0 = (len > 0) ? payload[0] : 0;
// 投递到命令网关,与 USART3 协议同一条路径
packer_command_gateway_push(&cmd);
}
日志和事件推送
日志不再封装为 DGUS 0x82 写变量帧,而是通过 HMIS 的 TYPE=0x04 日志帧独立推送:
// 日志推送帧 (TYPE=0x04, CMD=0x41)
| SOF | VER | 0x04 | SEQ | 0x41 | FLAGS | LEN | level(1) | text(N) | CRC16 |
// 事件推送帧 (TYPE=0x03, CMD=0x40)
| SOF | VER | 0x03 | SEQ | 0x40 | FLAGS | LEN | event_code(1) | value0(1) | value1(1) | CRC16 |
// HMI 侧通过订阅机制选择感兴趣的数据流
req: TYPE=0x01, CMD=0x22, payload=[stream_mask]
// stream_mask bit0=事件 bit1=日志 bit2=栈快照
与旧 DGUS 协议的对比
| 维度 | DGUS (废弃) | HMIS (当前) |
|---|---|---|
| 帧头 | 5A A5 | 55 AA |
| 地址模型 | VP 地址空间(0x1000/0x3000) | 命令码 + Payload |
| 参数访问 | HMI 硬编码地址表 | 固件提供参数目录(0x10/0x11) |
| 响应匹配 | 无序号,超时匹配 | SEQ 序号匹配 |
| 日志 | 0x82 写 VP 0x3000 变量帧 | TYPE=0x04 LOG_PUSH 帧 |
| 心跳 | 无 | TYPE=0x05,3 秒间隔 |
| 能力声明 | 无 | DEVICE_INFO 的能力位图 |
| HMI 维护成本 | 两套协议栈 | 同一套会话协议 |
HMIS 的核心思路:让固件成为参数元数据的唯一真源。HMI 不再硬编码参数地址和含义——启动时拉目录,看到什么就显示什么。参数新增/删除/换分组,HMI 侧零改动。
Comments NOTHING