TwinCAT 3中MODBUS TCP读取Word数组:合并为DWORD并转Float/Real及字节交换
在TwinCAT 3中合并Word数组为Float/Real的实现方法
方法1:指针强制转换(最直接)
如果Word数组中连续两个元素对应一个Float的高低16位,可通过指针地址映射直接转换,无需手动拼接:
VAR arrModbusWords: ARRAY[0..1] OF WORD; // MODBUS读取到的Word数组 ptrDword: POINTER TO DWORD; ptrReal: POINTER TO REAL; finalFloat: REAL; END_VAR // 指向数组第一个Word的地址 ptrDword := ADR(arrModbusWords[0]); // 强制转换指针类型为REAL指针 ptrReal := ptrDword; // 读取转换后的浮点值 finalFloat := ptrReal^;
方法2:结构体联合映射(更直观)
定义包含Word成员和REAL成员的联合结构体,利用地址重叠实现自动转换:
// 先定义自定义类型 TYPE ST_FloatConverter : STRUCT WordLow: WORD; // 低16位 WordHigh: WORD; // 高16位 FloatValue: REAL __AT(0); // 从地址0开始,与上面两个Word重叠 END_STRUCT END_TYPE // 程序中使用 VAR arrModbusWords: ARRAY[0..1] OF WORD; floatConverter: ST_FloatConverter; finalFloat: REAL; END_VAR // 把MODBUS读取的Word赋值给结构体成员 floatConverter.WordLow := arrModbusWords[0]; floatConverter.WordHigh := arrModbusWords[1]; // 直接获取浮点值 finalFloat := floatConverter.FloatValue;
何时需要做字节交换?
字节交换的核心原因是MODBUS默认大端字节序和TwinCAT(x86架构)小端字节序的差异,触发场景如下:
- 读取的浮点值与预期不符(比如设了10.0却读出异常值),大概率需要字节交换
- 从站设备是大端架构(如嵌入式仪表、部分PLC),其寄存器存储浮点时遵循大端规则:高字节在前、低字节在后
- 两种常见交换场景:
- 交换两个Word的顺序:如果从站把Float的高16位存在低地址寄存器,低16位存在高地址寄存器,合并时需先交换两个Word的位置再转换
- 交换单个Word的高低字节:如果从站每个Word内部的字节顺序是大端(比如Word值0x4140在从站中存储为0x41、0x40,而TwinCAT中是0x40、0x41),需要用
SWAP指令交换每个Word的字节
字节交换示例(交换Word顺序)
VAR arrModbusWords: ARRAY[0..1] OF WORD := 16#4140, 16#0000; // 模拟大端从站返回的10.0 dwTemp: DWORD; finalFloat: REAL; END_VAR // 交换两个Word的位置,合并成DWORD dwTemp := (WORD_TO_DWORD(arrModbusWords[1]) SHL 16) OR arrModbusWords[0]; // 转换为Float finalFloat := DWORD_TO_REAL(dwTemp);
单个Word字节交换示例
VAR arrModbusWords: ARRAY[0..1] OF WORD; dwTemp: DWORD; finalFloat: REAL; END_VAR // 交换每个Word的高低字节 arrModbusWords[0] := SWAP(arrModbusWords[0]); arrModbusWords[1] := SWAP(arrModbusWords[1]); // 合并并转换 dwTemp := (WORD_TO_DWORD(arrModbusWords[1]) SHL 16) OR arrModbusWords[0]; finalFloat := DWORD_TO_REAL(dwTemp);
内容的提问来源于stack exchange,提问作者Alok Nath
相关产品推荐
相关产品推荐

