速度控制协议一共八个字节
地址码 + 功能码 + 数据 + CRC校验码
CRC校验码的填写:
生成的校验码CA43
填入协议为43 CA
速度为 5 r / s
对应的十六进制为 05H
01 06 20 01 00 50 xx xx
速度为 25 r / s
对应的十六进制为 19H
01 06 20 01 01 90 xx xx
速度为 100 r / s
对应的十六进制为 64H
01 06 20 01 06 40 xx xx
速度为 3000 r / s
对应的十六进制为 BB8H
01 06 20 01 0B B8 xx xx
地址码:第一字节
0x00 广播地址, 广播时从机无回复,适用于多个台群控
0x01 - 0xF7 从机地址
0xF8 - 0xFF 系统保留,不能使用
功能码:第二字节
0x03 读寄存器操作
0x06 写单个寄存器操作
0x10 写多个寄存器操作
数据: 第三字节到第六字节
不同的数据有不同的数据格式
校验码: 第七字节,第八字节
CRC校验对象:地址码 + 功能码 + 数据
即对一二三四五六字节进行校验
CRC校验算法 :MODBUS(x16 + x15 + x2 +1)
CRC校验算法的C++实现如下:
#include <stdio.h>
/**
**************************************************************************************************
* @Brief Single byte data inversion
* @Param
* @DesBuf: destination buffer
* @SrcBuf: source buffer
* @RetVal None
* @Note (MSB)0101_0101 ---> 1010_1010(LSB)
**************************************************************************************************
*/
void InvertUint8(unsigned char* DesBuf, unsigned char* SrcBuf)
{
int i;
unsigned char temp = 0;
for (i = 0; i < 8; i++)
{
if (SrcBuf[0] & (1 << i))
{
temp |= 1 << (7 - i);
}
}
DesBuf[0] = temp;
}
/**
**************************************************************************************************
* @Brief double byte data inversion
* @Param
* @DesBuf: destination buffer
* @SrcBuf: source buffer
* @RetVal None
* @Note (MSB)0101_0101_1010_1010 ---> 0101_0101_1010_1010(LSB)
**************************************************************************************************
*/
void InvertUint16(unsigned short* DesBuf, unsigned short* SrcBuf)
{
int i;
unsigned short temp = 0;
for (i = 0; i < 16; i++)
{
if (SrcBuf[0] & (1 << i))
{
temp |= 1 << (15 - i);
}
}
DesBuf[0] = temp;
}
unsigned short CRC16_CCITT(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0x0000;
unsigned short wCPoly = 0x1021;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin);
}
unsigned short CRC16_CCITT_FALSE(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0xFFFF;
unsigned short wCPoly = 0x1021;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
return (wCRCin);
}
unsigned short CRC16_XMODEM(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0x0000;
unsigned short wCPoly = 0x1021;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
return (wCRCin);
}
unsigned short CRC16_X25(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0xFFFF;
unsigned short wCPoly = 0x1021;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin ^ 0xFFFF);
}
unsigned short CRC16_MODBUS(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0xFFFF;
unsigned short wCPoly = 0x8005;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin);
}
unsigned short CRC16_IBM(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0x0000;
unsigned short wCPoly = 0x8005;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin);
}
unsigned short CRC16_MAXIM(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0x0000;
unsigned short wCPoly = 0x8005;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin ^ 0xFFFF);
}
unsigned short CRC16_USB(unsigned char* puchMsg, unsigned int usDataLen)
{
unsigned short wCRCin = 0xFFFF;
unsigned short wCPoly = 0x8005;
unsigned char wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
InvertUint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
{
wCRCin = (wCRCin << 1) ^ wCPoly;
}
else
{
wCRCin = wCRCin << 1;
}
}
}
InvertUint16(&wCRCin, &wCRCin);
return (wCRCin ^ 0xFFFF);
}
int main()
{
unsigned int usDataLen = 6;
unsigned char puchMsg3000[] = { 0x01, 0x06, 0x20, 0x01, 0x0B, 0xB8 };
unsigned char puchMsg100[] = { 0x01, 0x06, 0x20, 0x01, 0x06, 0x40 };
unsigned char puchMsg5[] = { 0x01, 0x06, 0x20, 0x01, 0x00, 0x50 };
unsigned char puchMsg10[] = { 0x01, 0x06, 0x20, 0x01, 0x00, 0xA0 };
unsigned char puchMsg20[] = { 0x01, 0x06, 0x20, 0x01, 0x01, 0x40 };
unsigned char puchMsg50[] = { 0x01, 0x06, 0x20, 0x01, 0x03, 0x20 };
unsigned char puchMsg900[] = { 0x01, 0x06, 0x20, 0x01, 0x03, 0x84 };
unsigned short x = CRC16_MODBUS(puchMsg900, usDataLen);
return 0;
}