与Modbus设备交换32位数据
基于Modbus的设备在发送多字节数据时,遵循以寄存器为单位的小端模式。
对接收到的数据0xAABBCCDD而言,在小端模式的桌面应用下,如果用2个uint16结构体接收并解析此数据流,结果如下:
struct Foo
{
uint16 r1;
uint16 r2;
};
char buffer[] = {0xCC, 0xDD, 0xAA, 0xBB};
struct Foo fo = *(struct Foo*)(buffer);
assert(fo.r1 = 0xDDCC);
assert(fo.r2 = 0xBBAA);
而如果用uint32接收,因为低位地址在前,结果如下:
uint32 r = *(uint32*)(buffer)
assert(r == 0xBBAADDCC);
显然这两种方式都没有获得正确的结果,要得到原数,就需要调节字节顺序。
// 将由Modbus转换而来的32位数,转换到本机表示。
inline uint32 SwapByteInt32(uint32 v)
{
// BBAADDCC => AABBCCDD
return ((v & 0xFF000000) >> 8) |
((v & 0x00FF0000) << 8) |
((v & 0x0000FF00) >> 8) |
((v & 0x000000FF) << 8);
}
同样,如果要向写入一个32位值给Modbus设置,也要合适的整理数据(这里值写入一个缓冲区):
void writeInt32(uint32 v)
{
// AABBCCDD => [CC DD AA BB]
buf[0] = (uint8)((v & 0x0000FF00) >> 8);
buf[1] = (uint8)((v & 0x000000FF));
buf[2] = (uint8)((v & 0xFF000000) >> 24);
buf[3] = (uint8)((v & 0x00FF0000) >> 16);
}