一、背景
- 什么是Modbus
Modbus是在1970年末為可編程邏輯控制器通信開發(fā)的,Modbus是一種串行通信協(xié)議,目的是用于與PLC設(shè)備進(jìn)行串口通訊,在需要對PLC設(shè)備進(jìn)行數(shù)據(jù)通訊的時候進(jìn)行使用。 - 為什么要使用Modbus
為什么要使用Modbus協(xié)議,因為Modbus協(xié)議是modicon公司于1979年為使用PLC通訊發(fā)表的,Modbus已經(jīng)成為工業(yè)領(lǐng)域通信協(xié)議的業(yè)界標(biāo)準(zhǔn)。
二、描述
在工作項目中遇到了需要用的ModBus協(xié)議的情況,所以這里記錄一下我對ModBus協(xié)議的一些理解,首先這里采用實際例子進(jìn)行解釋,自我感覺只有代入實際項目才理解的更快。
1、使用場景:用于與PLC設(shè)備進(jìn)行數(shù)據(jù)通訊
2、設(shè)備名稱: IM1281B電能計量模塊,也可用JSY-MK-149 電能測量儀
3、硬件通訊協(xié)議:RS-485
4、軟件通訊協(xié)議:Modbus-RTU協(xié)議
三、Modbus協(xié)議實例
1. 示例
首先Modbus協(xié)議一共包括ASCII、RTU、TCP等,此協(xié)議定義了控制器能夠認(rèn)識和使用的消息結(jié)構(gòu),而不管它們是經(jīng)過何種網(wǎng)絡(luò)進(jìn)行通信的。
下圖是RTU方式的傳輸格式:
發(fā)送數(shù)據(jù):01 03 00 48 00 08 C4 1A (抄0048H到004FH共8寄存器)
返回數(shù)據(jù):01 03 20 00 23 18 60 00 00 05 9D 00 02 FD A0 00 00 00 1E 00 00 02 59 00 00 00 1D 00 00 0C 1C 00 00 13 88 40 3C
解析后得到的結(jié)果是:
注:命令的下發(fā)可使用串口通訊工具或者使用透傳的方式進(jìn)行命令的下發(fā)。
2. 發(fā)送與返回的數(shù)據(jù)解析
1.發(fā)送解析
上面已經(jīng)是一個正常的Modbus-RTU通訊應(yīng)答,現(xiàn)在開始分析這個發(fā)送和接受數(shù)據(jù)是如何進(jìn)行的。第一步:
根據(jù)廠商提供的文檔,找到我們需要采集的數(shù)據(jù)都在哪些寄存器中,如下圖所示,我們要的電量數(shù)據(jù)是存儲在寄存器地址 0048H - 004FH這個范圍里的,一共8個寄存器。
第二步:
開始拼接發(fā)送數(shù)據(jù),首先我們要知道,
1 Modbus的模式是主從模式,主機(jī)發(fā)送命令給從機(jī),從機(jī)不能主動發(fā)送數(shù)據(jù)給主機(jī)。
2 每個從機(jī)設(shè)備都是自己的設(shè)備地址號,這個設(shè)備地址號是用于傳輸時來尋找設(shè)備用的,默認(rèn)地址是1,可以進(jìn)行修改地址號以區(qū)分不同的設(shè)備
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-5AraxoeH-1680103701984)(https:upload-images.jianshu.io/upload_images/2650372-a7e2cd3a454c2a64.png?imageMogr2/auto-orient/strip|imageView2/2/w/581/format/webp)]
看上圖,首先這段命令是一個查詢命令,結(jié)構(gòu)是:
//這邊使用的是Netty進(jìn)行命令下發(fā)
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//請求當(dāng)前設(shè)備的設(shè)備ID
byte[] deviceIdResult = new byte[]{0x00, 0x03, 0x00, 0x04, 0x00, 0x01, (byte) 0xC4, 0x1A};
ctx.writeAndFlush(Unpooled.wrappedBuffer(deviceIdResult)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
ctx.flush();
}
2.返回結(jié)果解析
01 03 20 00 23 18 60 00 00 05 9D 00 02 FD A0 00 00 00 1E 00 00 02 59 00 00 00 1D 00 00 0C 1C 00 00 13 88 40 3C
上圖是從機(jī)返回的數(shù)據(jù),數(shù)據(jù)段中的數(shù)據(jù)太多就省略了。
- 地址碼同上
- 功能碼同上
- 數(shù)據(jù)段的字節(jié)數(shù)量:這個是數(shù)據(jù)段的總字節(jié)個數(shù)
- 數(shù)據(jù)段:數(shù)據(jù)段中的數(shù)據(jù)就是我們想要采集的數(shù)據(jù)了,只要把這個數(shù)據(jù)段數(shù)據(jù)解析后就能得到我們想要的電壓,電流等數(shù)據(jù)了,這邊舉例解析一個字段,數(shù)據(jù)的里取4個字節(jié)進(jìn)行解析,取幾個字節(jié)具體根據(jù)廠家文檔說明。
從返回數(shù)據(jù)中取出 00 23 18 60 這四個字節(jié),調(diào)用16進(jìn)制轉(zhuǎn)10進(jìn)制方法對字節(jié)進(jìn)行轉(zhuǎn)換,得到結(jié)果后根據(jù)文檔要求剩以0.0001得到電壓的值,就按這個順序解析其他的值就可以了,代碼如下。
float valtage = (float) hex2decimal("00231860");
System.out.println("電壓" + valtage * 0.0001);
結(jié)果:電壓230.0
// 16進(jìn)制轉(zhuǎn)換10進(jìn)制
public static int hex2decimal(String hex) {
return Integer.parseInt(hex, 16);
}
- CRC校驗:同上
3、校驗代碼
1. 計算CRC校驗碼,把校驗碼之前的數(shù)據(jù)放入進(jìn)去,數(shù)值前加0x
byte[] crcByte = new byte[]{0x01, 0x03, 0x00, 0x48, 0x00, 0x08};
System.out.println(getCRC3(crcByte));
結(jié)果:C41A
public static String getCRC3(byte[] data) {
byte[] crc16_h = {
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40
};
byte[] crc16_l = {
(byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04,
(byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8,
(byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC,
(byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10,
(byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4,
(byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38,
(byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C,
(byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7, (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0,
(byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4,
(byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68,
(byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C,
(byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0,
(byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54,
(byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98,
(byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D, (byte) 0x4C, (byte) 0x8C,
(byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40
};
int crc = 0x0000ffff;
int ucCRCHi = 0x00ff;
int ucCRCLo = 0x00ff;
int iIndex;
for (int i = 0; i < data.length; ++i) {
iIndex = (ucCRCLo ^ data[i]) & 0x00ff;
ucCRCLo = ucCRCHi ^ crc16_h[iIndex];
ucCRCHi = crc16_l[iIndex];
}
crc = ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
//高低位互換,輸出符合相關(guān)工具對Modbus CRC16的運算
crc = ((crc & 0xFF00) >> 8) | ((crc & 0x00FF) << 8);
return String.format("%04X", crc);
}
2. CS校驗碼(如:標(biāo)準(zhǔn)188協(xié)議校驗方式)
public byte getCS(byte[] Abyte) {
byte result;
try {
int num = 0;
for (int i = 0; i < Abyte.length; i++) {
num = (num + Abyte[i]) % 256;
}
result = (byte) num;
} catch (Exception e) {
result = 0;
}
return result;
}
2. CRC16校驗
/// <summary>
/// CRC16校驗函數(shù) (一)
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
private static byte[] CRC16(byte[] x)
{
byte[] temdata = new byte[2];
int len = x.Length;
UInt16 crc = 0;
byte da;
int i = 0;
UInt16[] yu = { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef };
while (len-- != 0)
{
da = (byte)(((byte)(crc / 256)) / 16);
crc <<= 4;
crc ^= yu[da ^ x[i] / 16];
da = (byte)(((byte)(crc / 256)) / 16);
crc <<= 4;
crc ^= yu[da ^ x[i] & 0x0f];
i++;
}
temdata[1] = (byte)(crc & 0xFF);
temdata[0] = (byte)(crc >> 8);
return temdata;
}
/// <summary>
/// CRC16校驗類 (二)
/// </summary>
public static class Crc16
{
const ushort polynomial = 0xA001;
static readonly ushort[] table = new ushort[256];
/// <summary>
/// 獲得校驗字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string ComputeChecksum(byte[] bytes)
{
ushort crc = 0;
for (int i = 0; i < bytes.Length; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc.ToString("X4");
}
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < table.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
3. CRC32校驗
private static UInt32[] crcTable = {
0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
/// <summary>
/// 獲取CRC32校驗字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns>4字節(jié)16進(jìn)制碼</returns>
public static string GetCRC32(byte[] bytes)
{
int iCount = bytes.Length;
UInt32 crc = 0xFFFFFFFF;
for (int i = 0; i < iCount; i++)
{
crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];
}
UInt32 temp = crc ^ 0xFFFFFFFF;
return temp.ToString("X8");
}
4. BCC異或校驗
/// <summary>
/// BCC異或取反校驗
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string getBCC(byte[] data)
{
String ret = "";
byte[] BCC = new byte[1];
for (int i = 0; i < data.Length; i++)
{
BCC[0] = (byte)(BCC[0] ^ data[i]);
}
String hex = ((~ BCC[0]) & 0xFF).ToString("X");//取反操作
if (hex.Length == 1)
{
hex = '0' + hex;
}
ret += hex.ToUpper();
return ret;
}
四、學(xué)習(xí)鏈接
MODBUS通訊視頻教程文章來源:http://www.zghlxwxcb.cn/news/detail-485787.html
常見幾種校驗方法(CS和校驗、CRC16、CRC32、BCC異或校驗)文章來源地址http://www.zghlxwxcb.cn/news/detail-485787.html
到了這里,關(guān)于ModBus通訊協(xié)議(Java代碼實例)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!