大家好。我正在尝试创建一个将Modbus设备与我的软件通信的软件。我在CRC16上遇到问题,有时设备有时无法响应。
以下详细信息:
function CRC16(Data: AnsiString): AnsiString;
var
i,j,iSum,f : Integer;
begin
iSum := $FFFF;
for i := 1 to Length(Data) do
begin
iSum := iSum xor Ord(Data[i]);
for j := 1 to 8 do
begin
f := iSum and $0001;
iSum := iSum shr 1;
if f = 1 then iSum := iSum xor $A001;
end;
end;
Result := AnsiChar(Lo(iSum)) + AnsiChar(Hi(iSum));
end;
procedure TForm1.Button1Click(Sender: TObject);
Var
YearVar : String;
AnsiOrig : ansiString;
Ansi : ansiString;
Ansi2 : ansiString;
YearConvert : Integer;
YearUpdater : String;
YearUpdaterCRC : String;
begin
CloseAllConnection;
ComPortUpdate.Open;
if ComPortUpdate.Connected then
Begin
YearConvert := StrToInt(Edit1.Text);
AnsiOrig := IntToHex(YearConvert,4);
Ansi := Copy(AnsiOrig,1,2);
Ansi2 := Copy(AnsiOrig,3,2);
{ShowMessage(AnsiOrig);
ShowMessage(Ansi);
ShowMessage(Ansi2); }
YearUpdater := chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02)+
chr($04) + chr(StrtoInt('$' + Ansi)) + chr(StrtoInt('$' + Ansi2));
YearUpdaterCrc := CRC16(YearUpdater);
//ShowMessage(StringToHex(YearUpdater + YearUpdaterCRC));
ComPortUpdate.WriteStr(YearUpdater + YearUpdaterCRC);
ComPortUpdate.ClearBuffer(True,True);
End
else
begin
ShowMessage('Communication port is not connected');
end;
end;
这有效:
YearUpdater := chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02) + chr($04) +
chr($07) + chr($E0);
但这不起作用:
YearUpdater := chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02) + chr($04) +
chr($07) + chr($DF);
我认为支票号码有误。
请提供帮助,或者发布可用的CRC16功能。预先感谢。
答案 0 :(得分:0)
通常,在RS232通信中,我仅使用字符串或8位字符的长度。尝试将所有变量从字符串更改为ansistring,然后使用Ansichar()代替Chr()。
要更改的行是这样的:
YearUpdater:= chr(StrToInt('$'+ EditAddress.Text))+ chr($ 06)+ chr($ 02)+ chr($ 04)+ chr(StrtoInt('$'+ Ansi))+ chr(StrtoInt('$'+ Ansi2));
YearUpdater必须是Ansistring。
答案 1 :(得分:0)
从我的角度来看,您的CRC-16功能错误。你可以试试吗?
procedure ByteCRC(Data: Byte; var CRC: Word);
var i: Byte;
begin
for i := 1 to 8 do
begin
CRC := CRC shr 1;
if (Data and $01) xor (CRC and $0001) > 0 then
CRC := CRC xor $A001;
Data := Data shr 1;
end;
end;
function CRC16(Data: AnsiString): AnsiString;
var
i: cardinal;
CRC: Word;
begin
CRC := 0;
for i := 1 to length(s) do
ByteCRC(ord(s[i]), CRC);
result := AnsiChar(lo(CRC)) + AnsiChar(hi(CRC));
end;