理论知识来源:
1. https://blog.csdn.net/icewolf13/article/details/8330446?utm_source=blogxgwz8
2. https://www.cnblogs.com/guorongtao/p/12484872.html
做串口通讯的时候,经常用到CRC16校验,不同的设备厂家校验方法略有不同。
看着协议文档,是C++的校验代码,经常出现<< >> ^ &等位运算符号。
在网上查询了下,Delphi与C++位运算符的对应, 学习了下.
(地址是:)
位运算符对应关系如下
| C++ | Delphi | |
| 与 | & | and |
| 或 | | | or |
| 取反 | ~ | not |
| 异或 | ^ | xor |
| 左移 | << | shl |
| 右移 | >> | shr |
接下来是弄明白该符号的具体意思:
| x shl n | x的二进制数向左移n位,尾部补n个零(例子1) |
| x shr n | x的二进制数向右移n位,首部补n个零(例子2) |
| x or n | 二进制(x 、n)相加,同1为1,有1则1 :1+1=1,0+1=1,0+0=0(例子3) |
| x xor n | 二进制(x 、n)相加, 同1为0,有1则1 :1+1=0,0+1=1,0+0=0(例子4) |
| x and n | 二进制(x 、n)相加,同1为1,有0则0 :1+1=1,0+1=0,0+0=0(例子5) |
| not x | 二进制取反(需先指定数据的大小),1为0,0为1(例子6) |
例子1: 255 shl 2
1. 255转化为二进制为: 1111 1111
2. 该二进制数左移2位, 尾部补0,二进制变成: 11 1111 1100,转化十进制为1020
例子2: 255 shr 2
1. 255转化为二进制为: 1111 1111
2. 该二进制数右移2位, 首部补0,二进制变成: 0011 1111,转化十进制为63
例子3: 255 or 36
1. 255转化为二进制为: 1111 1111
36转化为二进制为 : 0010 0100 根据规则同1为1 有1则1 的规则进行转换
转化后的二进制为 : 1111 1111 转化十进制为255
例子4: 255 xor 36
1. 255转化为二进制为: 1111 1111
36转化为二进制为 : 0010 0100 根据规则同1为0 有1则1 的规则进行转换
转化后的二进制为 : 1101 1011 转化十进制为219
例子5: 255 xor 88
1. 255转化为二进制为: 1111 1111
88转化为二进制为 : 0101 1000 根据规则同1为1 有0则0 的规则进行转换
转化后的二进制为 : 0101 1000 转化十进制为88
例子6: not 99
var
iRet: Integer;
iCal: Byte;
begin
//需要指定数据的类型
iCal:= 99;
iRet:= not iCal;
Memo1.Lines.Add(Format('运算结果: %u', [iRet]));
end;
1. 99转化为二进制为: 0110 0011 根据规则1为0 0为1 的规则进行转换
转化后的二进制为 : 1001 1100 转化十进制为156
上面的iCal定义的是Byte类型,范围0..255, 取反为156, 如果定义Word类型, 取反为65436。
所以,取反的值和iCal的定义类型有关。
实战效果:
某公司的校验算法如下:
unsigned short CRC16(const unsigned char *buf, unsigned int len)
{
u16 crc = 0xaa;
while(len--)
{
crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *(unsigned char *)buf++)&0x00FF];
}
return crc;
}
转化为Delphi算法如下(其中crc16tab是个Word数组,就不粘贴了)
Function CRC16(ABuf:Tbytes): word;
var
crc: Word;
aByte: Byte;
i, j: Integer;
begin
crc:= $AA;
for I := 0 to Length(ABuf) - 1 do
begin
crc:= (crc shl 8) xor crc16tab[((crc shr 8) xor Ord(ABuf[I])) and $FF];
end;
Result:= crc;
end;
串口通讯校验通过,通讯正常。

481

被折叠的 条评论
为什么被折叠?



