一头雾水,请哪位兄弟有用spcomm控件读modbus rtu协议的例程,谢谢!(200)

  • 主题发起人 主题发起人 fjjs
  • 开始时间 开始时间
F

fjjs

Unregistered / Unconfirmed
GUEST, unregistred user!
一头雾水,请哪位兄弟有用spcomm控件读modbus rtu协议的例程,谢谢!对方使用modbus rtu协议广播数据,我想用spcomm接收。
 
modbus rtu协议没弄过,不过用spcomm的时候要把波特率什么的设置好,否则会是乱码
 
使用SPCOMM控件进行串口通信需要处理好两个事件;onReceoveData : procedure (Sender: Tobject;Buff:pointer;BufferLength:Word)of object当输入缓存有数据时将触发该事件,在这里可以对串口收到的数据进行处理。Buffer中是收到的数据,bufferlength是收到的数据长度。OnReceiveError: procedure(Sender: Tobject;EventMask: DWORD)当接受数据时出现错误将触发该事件Modbus RTU协议是一种主从式通信协议,每次由主站发起并期望从从站得到回应,从站接收到一消息,它将建立一定回应格式并返回给发起斩主站,从站返回消息在OnReceiveData事件里处理,根据主站发起的命令字分类比较如下代码jgxGFSY1VCJsyNQseKzfwuzQAy9E-CMS.gif
 
最后编辑:
to de410: 非常感谢您,因为初次接触工控类的通讯,感觉问题较多,方便用QQ或MSN直接联系吗?QQ:181351136MSN:yangh2000@msn.com
 
不好意思,我们不让上QQ,MSN~~,skype 还可以~~另:本人水平也不高,这些是我之前收藏的文摘~供你参考http://www.delphibbs.com/keylife/iblog_show.asp?xid=22016
 
非常感谢de410,我先看下。
 
发个测试例子:但是需要装,CNpack组件包unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, CnClasses, CnRS232, StdCtrls, ExtCtrls;type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; CnRS2321: TCnRS232; Button2: TButton; Timer1: TTimer; Timer2: TTimer; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Edit4: TEdit; Edit5: TEdit; Edit6: TEdit; Edit7: TEdit; Edit8: TEdit; Edit9: TEdit; Edit10: TEdit; Edit11: TEdit; Edit12: TEdit; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure CnRS2321ReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word); procedure Timer1Timer(Sender: TObject); procedure Timer2Timer(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); private { Private declarations } public { Public declarations } end; TCRC=Record CrcH:byte; CrcL:byte; CHKok:boolean; End; type TArrayByte=array[0..3] of byte;var Form1: TForm1; Function Crc16Check(Inbyte:array of byte):TCRC; Function GetSingleFromByte(Byte0,Byte1,Byte2,Byte3:Byte;Var ValStr:string):Single; Function ChangeSingleToByte(Asingle:single):TArrayByte;implementation{$R *.dfm}Function Crc16Check(InByte:array of byte):TCRC; Const CrcConst=$A001; var Len,i,j:integer; Crc16Buf:Word; Crc16h,Crc16L:byte;begin Len:=High(Inbyte); Crc16Buf:=$FFFF; for I := 0 to (len-2) do begin Crc16Buf:=Crc16Buf Xor InByte ; for j := 1 to 8 do begin if (crc16Buf and $0001)=$0001 then crc16Buf:=(Crc16Buf SHR 1) XOR CrcConst else crc16Buf:=(Crc16Buf SHR 1); end; end; crc16h:=LO(crc16Buf); crc16l:=HI(crc16Buf); Result.CHKok:=(crc16h=InByte[Len-1]) and (crc16L=InByte[Len]); Result.CrcH:=crc16h; Result.CrcL:=crc16L;end;Function GetSingleFromByte(Byte0,Byte1,Byte2,Byte3:Byte;Var ValStr:string):Single; //485 S710分析仪{*注意:浮点数内存中排列如下:Byte3,Byte2,Byte1,Byte0*}Var AByte:array[0..3] of byte; PS:^Single; begin AByte[0]:=Byte1; AByte[1]:=Byte0; AByte[2]:=Byte3; AByte[3]:=Byte2; PS:=@Abyte[0]; Result:=PS^; ValStr:=Format('%6.4f' ,[PS^]);end;Function ChangeSingleToByte(Asingle:single):TArrayByte; var Pa:^TArrayByte;begin Pa:=@Asingle; Result[0]:=Pa^[1]; Result[1]:=Pa^[0]; //高低字节交换 Result[2]:=Pa^[3]; Result[3]:=Pa^[2]; //高低字节交换 end;procedure TForm1.Button1Click(Sender: TObject);var Crc:Tcrc; SND:array of byte; Wlen:integer;begin Setlength(SND,8);// FillChar(SND,8,0); SND[0]:=1; // Abakus Address SND[1]:=3; // Function Code 3,4,6,16.... SND[2]:=0; // Register Addr High SND[3]:=4; // Register Addr Low SND[4]:=0; // Read Quantity High SND[5]:=2; // Read Quantity Low Crc:=Crc16Check(SND); SND[6]:=Crc.CrcH; SND[7]:=Crc.CrcL; Wlen:=High(SND)+1; cnRs2321.WriteCommData(@SND[0],Wlen);// Timer1.Enabled:=true;// Timer2.Enabled:=true;end;procedure TForm1.Button2Click(Sender: TObject);begin if Not cnRs2321.Connected then cnRs2321.StartComm;end;procedure TForm1.Button3Click(Sender: TObject); var SingPV:Single; StrVal:String;begin SingPV:=GetSingleFromByte(20,5,61,234,StrVal);end;procedure TForm1.Button4Click(Sender: TObject);Var AByt:TArrayByte;begin AByt:=ChangeSingleToByte(0.11429599673);end;procedure TForm1.CnRS2321ReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word); var RcvData:Array of byte; ChkStr:string; RetCrc:Tcrc;begin RcvData:=Buffer; SetLength(RcvData, BufferLength); RetCrc:=Crc16Check(RcvData); Timer1.Enabled:=False; if RetCrc.CHKok then begin Edit1.Text:=IntTostr(RcvData[3]*256 +RcvData[4]); Edit2.Text:=IntTostr(RcvData[5]*256 +RcvData[6]); Edit3.Text:=IntTostr(RcvData[7]*256 +RcvData[8]); Edit4.Text:=IntTostr(RcvData[9]*256 +RcvData[10]); Edit5.Text:=IntTostr(RcvData[11]*256 +RcvData[12]); Edit6.Text:=IntTostr(RcvData[13]*256 +RcvData[14]); Edit7.Text:=IntTostr(RcvData[15]*256 +RcvData[16]); Edit8.Text:=IntTostr(RcvData[17]*256 +RcvData[18]); Edit9.Text:=IntTostr(RcvData[19]*256 +RcvData[20]); Edit10.Text:=IntTostr(RcvData[21]*256 +RcvData[22]); Edit11.Text:=IntTostr(RcvData[23]*256 +RcvData[24]); Edit12.Text:=IntTostr(RcvData[25]*256 +RcvData[26]); end;end;procedure TForm1.Timer1Timer(Sender: TObject);begin Showmessage('通讯超时!');end;procedure TForm1.Timer2Timer(Sender: TObject);begin Button1Click(Sender);end;end.
 
to dorry:非常感谢您,我先试下。有问题再向您请教。
 
to dorry:你好,非常感谢您对我的帮助,但我现在遇到的问题似乎和你给的例子不同。我现在是想用串口控件个从站,来接收主站写过来的数据(32位float)并显示它,您给的例子似乎是主站向从站通讯的,所以无法和实际的设备通讯。问题的难点在:1、对主站的响应以建立连接。2、对写过来的报文解析。3、将对应地址的值转换成32位float并显示。望您能进一步针对性的指导,再次表示感谢!QQ:181351136MSN:yangh2000@msn.com
 
我正在做rs232通信,用的是spcomm控件,pc与plc通讯的,正在调试过程中关注呵呵
 
做过主站程序,从站还真没做过,不过我想是这样的:主站轮询命令,从站解析,从站发送相应,主站发报文数据,从站解析,不知是不是这个过程?;或者,主站轮询命令中就有报文数据,那就简单多了,直接进行CRC效验,按协议解就行了。关注
 
to pgfzhy你的思路应该是正确的,但具体用spcomm触发接收、解码、效验、进制转换没有搞过就无法下手了。
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部