十、字节顺序与跨平台问题
10.1 Modbus 标准字节序
Modbus标准:大端序(Big Endian,网络字节序)
16位值
0x1234→ 发送0x12(高字节)0x34(低字节)
10.2 常见设备的小端序问题
部分PLC使用小端序(Little Endian):
| 厂商/设备 | 字节序 | 说明 |
|---|---|---|
| Schneider Electric | 大端 | 遵循标准 |
| Siemens S7 | 小端 | 需配置或转换 |
| Allen-Bradley (Rockwell) | 小端 | 需转换 |
| Mitsubishi | 大端 | 遵循标准 |
| Omron | 大端 | 遵循标准 |
| 国产设备 | 不定 | 需测试确认 |
10.3 字节序转换方法
10.3.1 C语言转换
// 单寄存器转换 uint16_t swap_endian_16(uint16_t val) { return (val << 8) | (val >> 8); } // 寄存器数组转换(就地) void swap_endian_array(uint16_t *data, int count) { for (int i = 0; i < count; i++) { data[i] = (data[i] << 8) | (data[i] >> 8); } }10.3.2 Python转换
def swap_endian_16(value): return ((value & 0xFF) << 8) | ((value >> 8) & 0xFF) def swap_endian_array(data): return [swap_endian_16(v) for v in data] # 使用struct处理字节序 import struct data = b'\x12\x34\x56\x78' regs = struct.unpack('>HH', data) # 大端: (0x1234, 0x5678) regs = struct.unpack('<HH', data) # 小端: (0x3412, 0x7856)10.4 32位浮点数处理
Modbus协议不直接支持浮点,通常用2个连续寄存器存储32位浮点数(IEEE 754):
def uint16_to_float(reg_high, reg_low, little_endian=False): """将两个寄存器合并为浮点数""" if little_endian: # 小端: 低寄存器在前 bytes_data = struct.pack('<HH', reg_low, reg_high) else: # 大端: 高寄存器在前(标准) bytes_data = struct.pack('>HH', reg_high, reg_low) return struct.unpack('>f', bytes_data)[0] # 或 '<f' 根据格式 # 示例:IEEE 754 浮点数 3.14 = 0x4048F5C3 # 寄存器0x0000=0x4048,0x0001=0xF5C3(大端) value = uint16_to_float(0x4048, 0xF5C3, little_endian=False) # =3.14