4、命令集设计:按摩仪常用命令的编码规则
好,这一章我们来聊聊命令集设计。说白了,就是按摩仪上位机和下位机之间,到底怎么「说话」。
我在做第一个按摩仪项目时,犯过一个低级错误——命令编码太随意。启动用0x01,停止用0x02,后来加了个「暂停」功能,编码冲突了。嗯,那场面挺尴尬的。所以今天我把这些经验整理出来,希望能帮你少走弯路。
4.1 命令编码的基本原则
我个人习惯,命令编码要遵循三个原则:
- 唯一性:每个命令对应唯一一个编码,不能有二义性
- 可扩展性:预留一些编码空间,方便后续增加功能
- 简洁性:能用1个字节就别用2个,嵌入式资源很宝贵
重要提醒:命令编码最好按功能分组。比如0x10-0x1F留给模式控制,0x20-0x2F留给力度调节。这样一看编码就知道是干什么的。
4.2 按摩仪常用命令编码表
下面是我在项目中实际用过的编码方案,你可以直接参考:
| 命令名称 | 编码(十六进制) | 数据长度 | 说明 |
|---|---|---|---|
| 启动 | 0x01 | 1字节 | 开始按摩,默认模式 |
| 停止 | 0x02 | 1字节 | 立即停止所有动作 |
| 模式切换 | 0x10 | 2字节 | 第2字节指定模式编号 |
| 力度调节 | 0x20 | 2字节 | 第2字节为力度值1-10 |
| 加热控制 | 0x30 | 2字节 | 第2字节:0关闭,1开启 |
| 查询状态 | 0x40 | 1字节 | 请求当前工作状态 |
我的小技巧:编码从0x01开始,不要用0x00。因为很多单片机初始化后内存默认是0x00,容易误判。我曾经就因为这个排查了半天。
4.3 命令帧结构设计
光有编码还不够,你得把命令「打包」发送。我建议用固定长度的帧结构:
帧头(1字节) + 命令编码(1字节) + 数据(0-2字节) + 校验(1字节) + 帧尾(1字节)
举个例子,发送「力度调节到5」:
0xAA 0x20 0x05 0xCF 0x55
帧头 命令 力度 校验 帧尾
这里校验我用的是累加和校验。0xAA + 0x20 + 0x05 = 0xCF,简单实用。
4.4 各命令的详细设计
4.4.1 启动命令
启动命令最简单,就一个字节0x01。但要注意:
- 如果按摩仪已经在运行,收到启动命令应该忽略还是重启?
- 我建议:如果正在运行,返回一个「忙」状态码,不要直接覆盖
4.4.2 停止命令
停止命令0x02,优先级最高。不管按摩仪在做什么,收到就立即停止。
注意:停止后电机有惯性,不能立即断电。我建议在停止命令后加一个200ms的减速过程,否则用户体验很差。
4.4.3 模式切换命令
模式切换需要两个字节:0x10 + 模式编号。
模式编号定义:
| 模式编号 | 模式名称 | 说明 |
|---|---|---|
| 0x01 | 揉捏模式 | 模拟人手揉捏 |
| 0x02 | 敲击模式 | 有节奏的敲打 |
| 0x03 | 推拿模式 | 线性推压 |
| 0x04 | 组合模式 | 多种模式循环 |
你想想看,如果只用一个字节,0x10既表示「模式切换」又表示「切换到模式1」,那不乱套了?所以必须分开。
4.4.4 力度调节命令
力度调节命令0x20,数据字节范围1-10。1最轻,10最重。
这里有个坑:不同模式下的力度感觉不一样。揉捏模式下的5档,和敲击模式下的5档,用户感觉可能完全不同。我建议在固件里做归一化处理。
4.4.5 加热控制命令
加热控制0x30,数据字节0或1。
我曾经遇到过一个问题:用户连续发送加热开启命令,下位机每次收到都重新初始化加热模块,导致加热片频繁通断。后来我加了一个「状态判断」——如果已经在加热,收到开启命令直接忽略。
4.5 命令响应的设计
上位机发了命令,下位机得回应吧?我习惯用统一的响应格式:
0xAA 0x80 命令编码 状态码 校验 0x55
状态码定义:
- 0x00:成功
- 0x01:命令不支持
- 0x02:参数错误
- 0x03:设备忙
- 0xFF:未知错误
举个例子,上位机发送力度调节到5,下位机成功执行后回复:
0xAA 0x80 0x20 0x00 0xCA 0x55
避坑指南:响应帧里的命令编码一定要原样返回。这样上位机才知道「哦,刚才那个力度调节命令执行成功了」。我曾经省略了这个字段,结果多命令并发时根本分不清哪个成功了。
4.6 实际项目中的经验总结
最后,分享几个我在项目中踩过的坑:
- 命令超时处理:上位机发送命令后,如果500ms内没收到响应,应该重发。最多重发3次。
- 命令队列:不要一次发太多命令。我建议上位机维护一个发送队列,等收到响应后再发下一条。
- 广播命令:如果一台电脑控制多台按摩仪,命令里要带设备地址。我一般用帧头的第2个字节做地址。
- 调试接口:保留一个0xFF作为调试命令,可以读取固件版本、运行日志等。这个在生产环境要关掉。
嗯,命令集设计就讲到这里。下一章我们会聊通信协议的具体实现,包括怎么处理粘包、怎么保证数据完整性。到时候见。