最近接觸到一個項目,是運行在組態王軟件中的儀表設備,使用modbus協議通訊。
原以為modbus是一套完整的協議,從網上下載了粗略看了一下。后來拿到競品的樣品,安裝了組態王,連接運行了一下,才發現與之前理解有些不同。modbus可以說是一個協議的規范,具體數字代表的意義,是由設備廠商自定的。廠商將這些自定的協議做成驅動(dll),放在組態王的驅動包里,並選擇相應的設備名,這樣串口的modbus協議經過翻譯,成為組態王的標准接口。
modbus協議的框架為:
PC->設備 <Head><Cmd><Address><Data><CRC>
設備->PC <Head><Cmd><Len><Data...><CRC>
<Head> 命令頭,默認是0x3b, 也可以自定義,本協議中是0x60.
<Cmd> 0x03-讀寄存器;0x06-寫單個寄存器;其余的也可自定義;
<Address> 寄存器地址,雙字節,如[00 03]=3
<Data> 雙字節。當Cmd為讀寄存器時,表示連續讀取的個數;當Cmd為寫時,表示寫入的數據;
<CRC> 雙字節校驗;
<Len> 數據區字節個數,單字節;
舉例說明
PC->主設備,讀取從01開始,連續2個寄存器的值:60 03 [00 01] [00 02] [9D BA]
主設備->PC,回復4個字節數據00: 60 03 [04] [00 00] [00 00] [8A F5]
順便貼一段crc校驗的代碼
ushort crcTlb[] = {0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400};
ushort CalcCRC16(byte[] pBuf, int len)
{
byte i = 0, ch = 0;
ushort crc = 0xFFFF;
for (i = 0; i < len; i++)
{
ch = pBuf[i];
crc = (ushort)(crcTlb[(ch ^ crc) & 0x0F] ^ (crc >> 4));
crc = (ushort)(crcTlb[((ch >> 4) ^ crc) & 0x0F] ^ (crc >> 4));
}
crc = (ushort)((crc & 0xFF) << 8 | (crc >> 8));
return crc;
}
另外還遇到一個組態王的討厭問題。把原來項目文件換了一個電腦,USB轉串口的端口從COM7變成了COM5,但從工程里始終無法修改,提示“不支持預定義的接口”。后來終於在工程文件device.dat的最后一段找到了,把其中的二進制COM7直接改成了COM5,打開軟件后跑起來了:)
