2. SECS-I 协议详解:RS-232 物理层、数据帧格式、块传输协议、超时与重传机制

SECS-I 是 SECS/GEM 协议栈的最底层。说白了,它就是规定数据怎么通过一根串口线,从一台设备传到另一台设备。很多人觉得这层太老、太简单,直接跳过。但我个人习惯是,越是底层的东西,越要啃透。你想想看,上层协议跑得再花哨,物理层一掉线,全是白搭。

我在早期项目里就吃过这个亏。当时设备通讯老是断断续续,查了三天应用层代码,最后发现是 RS-232 的接地线没焊好。嗯,从那以后,我再也不敢小看 SECS-I 了。

2.1 RS-232 物理层:那根 25 针的线

SECS-I 的物理层基于 RS-232-C 标准。接口用的是 DB-25 连接器,但实际项目中,绝大多数只用 9 根信号线。

DB-25 引脚 信号名 方向 说明
2 TX 设备 → 主机 发送数据
3 RX 主机 → 设备 接收数据
4 RTS 设备 → 主机 请求发送
5 CTS 主机 → 设备 允许发送
7 GND — 信号地(必须接)
⚠️ 避坑指南: 我曾经遇到一个现场,设备商把 TX 和 RX 接反了,结果主机发指令设备永远收不到。记住:DB-25 的 2 脚是设备发,3 脚是设备收。交叉连接时,主机的 2 脚要接设备的 3 脚,主机的 3 脚接设备的 2 脚。

波特率方面,SECS-I 标准支持 9600、19200、38400 bps。我个人建议新项目直接上 38400,老设备兼容性不好就降到 19200。数据格式固定为:8 数据位、1 停止位、无校验。

2.2 数据帧格式:10 字节的“信封”

SECS-I 的数据帧,我习惯叫它“信封”。每个信封最多装 254 字节的有效数据。帧结构如下:

字节偏移 字段名 长度 说明
0 Length Byte 1 后续数据总长度(含 SMB 和 Data)
1 Device ID / Control 1 高 7 位为设备 ID,最低位为控制位
2 Block Number 1 块号,从 0 开始递增
3 System Bytes 2 系统字节,用于匹配请求与响应
5 Data 0–254 实际消息内容

这里有个关键点:Length Byte 不包括它自己。也就是说,如果 Length Byte = 10,那么从 Device ID 开始到 Data 结束,总共 10 个字节。

💡 我的经验: 调试时最容易出错的就是 Length Byte 算错。我写驱动时习惯先发一个固定长度的测试帧,比如 Length=5,然后在接收端打印原始字节流,逐字节比对。这样一次就能把帧解析逻辑调通。

2.3 块传输协议:大消息怎么拆?

SECS-I 规定单帧最多 254 字节数据。那如果我要传一个 1000 字节的配方文件怎么办?答案是:拆成多个块(Block)。

块传输协议的核心规则:

  • 每个块独立发送,独立确认。
  • 块号从 0 开始,依次递增。
  • 最后一个块的 Length Byte 的 bit 7 必须置 1,表示“这是最后一块”。
  • 接收方收到所有块后,按块号顺序重组。

举个例子,传一个 300 字节的消息:

  • 块 0:Length=254,块号=0,bit7=0
  • 块 1:Length=46,块号=1,bit7=1(最后一块)
🔧 实用技巧: 我建议块大小不要卡 254 字节上限。留 2-3 字节余量,比如每块只发 250 字节。为什么?因为有些老设备的缓冲区有对齐问题,满 254 字节时可能触发硬件 bug。我在一个 2005 年的设备上就踩过这个坑。

2.4 超时与重传机制:别让设备“死等”

SECS-I 定义了三个超时定时器。这三个值调不好,通讯就会频繁中断。

定时器 默认值 触发条件 动作
T1 1 秒 发送完一个字节后,等待下一个字节 重传整个块
T2 10 秒 发送完一个块后,等待确认 重传该块
T3 45 秒 发送完一条消息后,等待回复 重传整条消息

重传策略很简单:最多重传 3 次。3 次都失败,就报通讯错误。

为什么会这样设计?你想想看,半导体设备的环境里,电磁干扰很常见。偶尔丢一个字节是常态。如果丢一个字节就断连,那产线根本跑不起来。所以 SECS-I 用超时重传来容忍这些偶发错误。

⚠️ 避坑指南: 我曾经在一个项目中把 T1 设成了 500ms,结果设备频繁重传。后来发现是串口线太长(超过 15 米),信号衰减导致字节间隔变长。换了一根屏蔽线,T1 改回 1 秒,问题解决。记住:T1 不要小于 800ms,除非你确定线缆质量极好。

2.5 知识结构总览

下面这张图把 SECS-I 的核心逻辑串起来了。从物理层到块传输,再到超时重传,一条线走到底。

SECS-I 协议栈知识结构 RS-232 物理层 DB-25 / 9600-38400 bps 数据帧格式 Length + Device ID + Block + Data 块传输协议 拆块 / 重组 / 最后块标记 超时与重传机制 T1 / T2 / T3 · 最多重传 3 次 核心设计思想 • 物理层:用最成熟的串口标准,保证硬件兼容性 • 数据帧:固定 10 字节头部,解析简单,适合嵌入式实现 • 块传输:大消息拆小包,避免单帧过长导致缓冲区溢出 • 超时重传:容忍物理层偶发错误,保证产线连续运行

2.6 小结:SECS-I 的“三要三不要”

最后,我总结几条实战经验,你直接拿去用:

  • 要把 GND 接好。RS-232 是单端信号,地线是参考电平。地线没接好,数据全是乱码。
  • 要在驱动层做字节超时(T1)检测。很多商用串口库不暴露这个,你得自己用定时器实现。
  • 要在接收端做块号连续性检查。如果收到块号 0 后直接收到块号 2,说明中间丢了一块,必须要求重传。
  • 不要把 T3 设得太短。45 秒是标准值,设备处理复杂指令可能需要几十秒。
  • 不要在块传输时发其他消息。SECS-I 是半双工,发完一个块必须等确认才能发下一个。
  • 不要假设串口线是完美的。我见过太多现场因为线缆过长、屏蔽层破损导致通讯异常。备一根短屏蔽线,调试时直接换上,能省一半排查时间。

SECS-I 虽然老,但它稳定、可靠、可预测。搞懂了这层,上层 SECS-II 的消息格式和 HSMS 的 TCP 传输,你学起来会快很多。