4. SECS-II 数据类型:List、Binary、Boolean、ASCII、UINT、FLOAT 等格式与编码规则

SECS-II 是 SEMI 标准 E5 定义的消息层协议,它规定了在 HSMS 或 RS-232 连接上传输的所有消息的数据结构。SECS-II 的核心是 数据项(Data Item),每个数据项由 数据长度(Length)、格式字节(Format Byte) 和 数据体(Body) 三部分组成。理解这些数据类型的编码规则,是解析和构造 SECS 消息的基础。

核心概念: SECS-II 采用 TLV(Type-Length-Value)编码结构。格式字节(Format Byte)的高 4 位表示数据类型,低 4 位表示数据长度占用的字节数(通常为 1 或 2 字节)。

4.1 格式字节(Format Byte)结构

格式字节是 SECS-II 数据项的第一个字节,它决定了后续数据的解析方式。其结构如下:

  • 高 4 位(Bit 7-4): 数据类型编码(Format Code)。
  • 低 4 位(Bit 3-0): 长度字节数(Length Bytes)。通常为 0x01(1 字节长度)或 0x02(2 字节长度)。

例如,格式字节 0x41:高 4 位 0x4 表示 ASCII 类型,低 4 位 0x1 表示长度字段占用 1 个字节。

格式码(高4位) 数据类型 缩写 长度字节数(低4位) 数据体编码
0x0 List L 1 或 2 子数据项序列
0x1 Binary B 1 或 2 原始字节
0x2 Boolean BOOLEAN 1 或 2 0x00 (False) / 0x01 (True)
0x4 ASCII A 1 或 2 ASCII 字符字节
0x5 8 字节有符号整数 I8 1 或 2 大端 8 字节
0x6 1 字节有符号整数 I1 1 或 2 大端 1 字节
0x7 2 字节有符号整数 I2 1 或 2 大端 2 字节
0x8 4 字节有符号整数 I4 1 或 2 大端 4 字节
0x9 8 字节无符号整数 U8 1 或 2 大端 8 字节
0xA 1 字节无符号整数 U1 1 或 2 大端 1 字节
0xB 2 字节无符号整数 U2 1 或 2 大端 2 字节
0xC 4 字节无符号整数 U4 1 或 2 大端 4 字节
0xE 4 字节浮点数 F4 1 或 2 IEEE 754 大端
0xF 8 字节浮点数 F8 1 或 2 IEEE 754 大端
编码技巧: 格式字节的低 4 位决定了长度字段的大小。如果数据体长度 < 256 字节,通常使用 1 字节长度(低4位=0x1);如果长度 ≥ 256 字节,则必须使用 2 字节长度(低4位=0x2)。

4.2 核心数据类型详解

4.2.1 List(列表)

List 是 SECS-II 中唯一的复合类型,用于包含多个子数据项。格式码为 0x0。List 的数据体不是原始数据,而是由多个子数据项(Item)串联而成。List 的长度字段表示其包含的子数据项个数。

// 示例:一个包含 3 个元素的 List
// 格式字节: 0x01 (List, 1字节长度)
// 长度: 0x03 (3个子项)
// 子项1: [格式字节][长度][数据]
// 子项2: [格式字节][长度][数据]
// 子项3: [格式字节][长度][数据]

4.2.2 Binary(二进制)

Binary 类型用于传输原始字节流,格式码为 0x1。数据体直接是字节序列,不做任何编码转换。常用于传输状态字、标志位或自定义协议数据。

// 示例:传输 4 个字节的二进制数据 0x01 0x02 0x03 0x04
// 格式字节: 0x11 (Binary, 1字节长度)
// 长度: 0x04
// 数据体: 0x01 0x02 0x03 0x04

4.2.3 Boolean(布尔)

Boolean 类型格式码为 0x2。数据体固定为 1 个字节:0x00 表示 False,0x01 表示 True。虽然数据体只有 1 字节,但长度字段仍然存在。

// 示例:传输 True
// 格式字节: 0x21 (Boolean, 1字节长度)
// 长度: 0x01
// 数据体: 0x01

4.2.4 ASCII(字符串)

ASCII 类型格式码为 0x4。数据体为 ASCII 字符的字节序列。注意:SECS-II 标准要求使用 7 位 ASCII 码,高位(Bit 7)必须为 0。

// 示例:传输字符串 "OK"
// 格式字节: 0x41 (ASCII, 1字节长度)
// 长度: 0x02
// 数据体: 0x4F 0x4B  ('O' 'K')

4.2.5 UINT(无符号整数)

UINT 系列包括 U1、U2、U4、U8,格式码分别为 0xA、0xB、0xC、0x9。所有整数类型均采用 大端序(Big-Endian) 编码,即高位字节在前。

// 示例:传输无符号整数 1024 (0x0400),使用 U2 类型
// 格式字节: 0xB1 (U2, 1字节长度)
// 长度: 0x02
// 数据体: 0x04 0x00

4.2.6 FLOAT(浮点数)

FLOAT 系列包括 F4(单精度)和 F8(双精度),格式码分别为 0xE 和 0xF。编码遵循 IEEE 754 标准,采用大端序。

// 示例:传输浮点数 3.14,使用 F4 类型
// 3.14 的 IEEE 754 单精度表示为: 0x4048F5C3
// 格式字节: 0xE1 (F4, 1字节长度)
// 长度: 0x04
// 数据体: 0x40 0x48 0xF5 0xC3

4.3 编码规则与字节序

SECS-II 的编码规则可以总结为以下三点:

  1. TLV 结构: 每个数据项由 Type(格式字节)、Length(长度字段)、Value(数据体)三部分组成。
  2. 大端字节序: 所有多字节数值(整数、浮点数、长度字段)均使用大端序(网络字节序)传输。
  3. 长度字段可变: 格式字节的低 4 位决定了长度字段占用的字节数(1 或 2 字节),从而支持不同大小的数据体。
常见错误: 初学者容易混淆格式字节的低 4 位含义。低 4 位表示的是“长度字段占用的字节数”,而不是“数据体的长度”。数据体的实际长度需要从长度字段中读取。

4.4 数据项编码示例

下面通过一个完整的示例,展示如何编码一个包含多种数据类型的 SECS-II 消息体。

// 假设我们要编码一个 List,包含 3 个元素:
// 元素1: ASCII "ABC"
// 元素2: U2 数值 100
// 元素3: Boolean True

// 编码结果(十六进制):
// 0x01 0x03          // List, 3个子项
//   0x41 0x03 0x41 0x42 0x43  // ASCII "ABC"
//   0xB1 0x02 0x00 0x64       // U2 100 (0x0064)
//   0x21 0x01 0x01            // Boolean True

// 逐字节解释:
// 0x01: 格式字节,List类型,1字节长度
// 0x03: 长度字段,表示有3个子项
// 0x41: 格式字节,ASCII类型,1字节长度
// 0x03: 长度字段,表示有3个字符
// 0x41 0x42 0x43: 'A' 'B' 'C'
// 0xB1: 格式字节,U2类型,1字节长度
// 0x02: 长度字段,表示2字节数据
// 0x00 0x64: 大端序数值100
// 0x21: 格式字节,Boolean类型,1字节长度
// 0x01: 长度字段,表示1字节数据
// 0x01: True

4.5 数据类型选择策略

在实际的 SECS/GEM 通信中,选择合适的数据类型可以优化传输效率和解析性能:

应用场景 推荐类型 原因
设备状态标志 Boolean 或 Binary 占用空间小,解析简单
计数器、ID 编号 U4 或 U2 无符号,范围明确
测量值(温度、压力) F4 或 F8 支持小数,精度可控
文本消息、配方名称 ASCII 人类可读,调试方便
复杂数据结构 List 支持嵌套,灵活组合

4.6 SECS-II 数据项编码流程

下面的 SVG 图展示了从原始数据到 SECS-II 编码字节流的完整流程:

SECS-II 数据项编码流程 原始数据 选择数据类型 构造格式字节 计算长度字段 编码数据体 输出字节流 编码规则说明 1. 原始数据:待传输的数值、字符串或布尔值 2. 选择数据类型:根据数据特征选择 L/B/A/U/F 等 3. 构造格式字节:高4位=类型码,低4位=长度字节数 4. 计算长度字段:数据体实际字节数 5. 编码数据体:按大端序/IEEE754 编码 6. 输出字节流:格式字节 + 长度字段 + 数据体 示例:编码 U2 数值 1024 格式字节: 0xB1 (U2 + 1字节长度) 长度字段: 0x02 数据体: 0x04 0x00 (大端序) 最终字节: 0xB1 0x02 0x04 0x00

4.7 常见问题与避坑指南

调试建议: 使用 Wireshark 或 SECS 模拟器抓包时,重点关注格式字节的值。如果解析出的数据与预期不符,首先检查格式字节的高 4 位是否匹配数据类型,低 4 位是否正确指示了长度字段的字节数。
  • 长度字段溢出: 当数据体长度超过 255 字节时,必须使用 2 字节长度(格式字节低4位=0x2),否则接收方会截断数据。
  • 字节序错误: 所有多字节数据必须使用大端序。如果使用小端序编码,数值会被错误解析(例如 0x0102 会被解析为 0x0201)。
  • ASCII 高位问题: 某些系统可能发送 8 位扩展 ASCII,但 SECS-II 标准要求 7 位 ASCII。高位为 1 的字节可能导致解析异常。
  • List 嵌套深度: 虽然标准未限制嵌套深度,但实际设备通常限制在 10 层以内。过深的嵌套可能导致栈溢出。
实战要点: 在编写 SECS/GEM 驱动程序时,建议封装一个通用的数据项编码/解码函数,自动处理格式字节的构造和长度字段的读写。这样可以减少手动编码错误,提高代码复用性。