遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题

遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题 Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiNetwork/html/delphi_20061129164355231.html
Usb芯片:Ch375  
  协议:Modbus  
  上位机开发软件:delphi  
  传输格式(RTU):  
  帧定义:  
  头|命令|长度|数据(高)       ----           数据(低)|CRC  
                            C0C1C2   S0S1S2   T10T11   T20T21   P0P1  
  01     02       0C     000000   000000     0000       0000     0000     XX  
   
  第一次做这种软件,还没有在下位机上测试,先贴出部分源码,请大家帮忙改正。  
  还有对于从下位机取出来的数据(已从16进制转换成10进制)有几个疑问:  
  1。是不是就代表了真实的值,是否还需要再转换;  
  2。如何处理浮点型数据。  
  下面是部分源码:

//读数据  
  function   ReadData(iIndex:Integer;var   oBuffer:PChar;var   ioLength:Integer):Boolean;  
      stdcall;   external   DllFile   name   'CH375ReadData';  
   
  function   TPublicFun.GetData:Integer;  
  var  
      Buff_HAdd     :   Byte;//帧:头地址  
      Buff_Cmd       :   Byte;//帧:命令  
      Buff_Len       :   Byte;//帧:长度  
   
      Buff_DatLC   :   array[1..3]   of   Byte;//帧:LC数据  
      Buff_DatLS   :   array[1..3]   of   Byte;//帧:LS数据  
   
      Buff_DatT1   :   array[1..2]   of   Byte;//帧:T1数据  
      Buff_DatT2   :   array[1..2]   of   Byte;//帧:T2数据  
      Buff_DatP     :   array[1..2]   of   Byte;//帧:P数据  
       
      Buff_Send     :   array   of   Byte;//用于存放各个域合成的总的串  
      I,BuffLen,TempLen     :   Integer;//传输的实际数据长度  
      TempStr,CSort         :   string;//用于存放string类型的测试传输帧  
      Rtl                 :   Boolean;  
      PChar_Send   :   PChar;  
  begin  
      Result           :=   -1;  
   
      //测试用,假设Usb设备已打开  
      Usb_Opened   :=   True;  
   
      if   Usb_Opened   then  
          begin  
              //设置头地址  
              Buff_HAdd     :=   HeadCode;  
              //设置命令  
              Buff_Cmd       :=   StatusCode;  
   
              //设置长度  
              Buff_Len       :=   strtohex1(IntToHex(17,2),2);  
              TempLen         :=   17;  
   
                  //初始化LC,LS  
                  for   I:=1   to   3   do  
                      begin  
                          Buff_DatLC[I]   :=   $00;  
                          Buff_DatLS[I]   :=   $00;  
                      end;  
                  //初始化T,P  
                  for   I:=1   to   2   do  
                      begin  
                          Buff_DatT1[I]   :=   $00;  
                          Buff_DatT2[I]   :=   $00;  
                          Buff_DatP[I]     :=   $00;  
                      end;  
   
              SetLength(Buff_Send,TempLen);  
              //设置总串  
              Buff_Send[1]   :=   Buff_HAdd;  
              Buff_Send[2]   :=   Buff_Cmd;  
              Buff_Send[3]   :=   Buff_Len;  
   
              Buff_Send[4]   :=   Buff_DatLC[1];  
              Buff_Send[5]   :=   Buff_DatLC[2];  
              Buff_Send[6]   :=   Buff_DatLC[3];  
   
              Buff_Send[7]   :=   Buff_DatLS[1];  
              Buff_Send[8]   :=   Buff_DatLS[2];  
              Buff_Send[9]   :=   Buff_DatLS[3];  
   
              Buff_Send[10]   :=   Buff_DatT1[1];  
              Buff_Send[11]   :=   Buff_DatT1[2];  
   
              Buff_Send[12]   :=   Buff_DatT2[1];  
              Buff_Send[13]   :=   Buff_DatT2[2];  
   
              Buff_Send[14]   :=   Buff_DatP[1];  
              Buff_Send[15]   :=   Buff_DatP[2];  
   
                      //CRC校验:即校验域前的几个域的集合  
                      I   :=   CRC(Buff_Send[1],15);  
                      Buff_Send[16]   :=   I   div   256;  
                      Buff_Send[17]   :=   I   mod   256;  
   
              //获得string类型的测试传输帧  
              TempStr   :=   '';  
              for   I:=   1   to   TempLen   do  
                  TempStr   :=   TempStr   +   inttohex(Buff_Send[i],2);  
   
              BuffLen         :=   TempLen   *   2;  
              PChar_Send   :=   PChar(TempStr);  
   
              //发送命令  
              //测试屏蔽  
              Rtl   :=   ReadData(Usb_Index,PChar_Send,BuffLen);  
   
              if   Rtl   then  
                  begin  
                      //读取返回串  
                      for   I:=   0   to   TempLen-1   do  
                          Buff_rev[I+1]   :=   strtohex1(copy(PChar_Send,I*2+1,2),2);  
   
                      //CRC校验  
                      if   CRC_Check=1   then  
                          begin  
                              TempStr   :=   '';  
                              //校验成功,读出数据  
                              //TempStr   :=   TempStr   +   inttohex(Buff_rev[i+4],2);  
                              for   I:=   0   to   2   do  
                                  begin  
                                      Buff_DatLC[I+1]   :=   Buff_rev[I+4];  
                                      Buff_DatLS[I+1]   :=   Buff_rev[I+7];  
                                  end;  
                              for   I:=   0   to   1   do  
                                  begin  
                                      Buff_DatT1[I+1]   :=   Buff_rev[I+10];  
                                      Buff_DatT2[I+1]   :=   Buff_rev[I+12];  
                                      Buff_DatP[I+1]     :=   Buff_rev[I+14];  
                                  end;  
   
                              //数据处理  
   
                               
                              Result     :=   1;  
                              //初始化接受串  
                              for   I:=1   to   Maxlen   do   Buff_rev[I]:=0;  
                          end;  
                  end  
              else  
                  begin  
                      ShowMessage('数据传输出错,无法得到正确的值!','提示');  
                  end;  
          end  
      else  
          begin  
              ShowMessage('没有发现可用的Usb设备!','提示');  
          end;  
  end;

对于传输帧,我现在有点疑惑:  
  我传向下位机请求和从下位机得到数据都是以上面我和下位机开发人员定义的格式传输并不象下面Modbus中的例子,不知可行否?  
  因为我定义的帧中要获取5个参数的值:LC由C0C1C2构成(高-低)、LS由S0S1S2构成、T1由T10T11构成、T2由T20T21构成、P由P0P1构成。  
  下面是Modbus   RTU中一个例子:  
  主机请求:  
  地址     功能码     第一个寄存器的高位地址     第一个寄存器的低位地址     寄存器的数量的高位     寄存器的数量的低位   错误校验    
  01   03     00                                             38                                   00   01     XX    
   
  从机应答:    
  地址   功能码   字节数   数据高字节   数据低字节   错误校验    
  01   03     2       41                             24                           XX    
   
  数据:16进制=4124,转换成十进制=16676

//发送命令  
              //测试屏蔽  
              Rtl   :=   ReadData(Usb_Index,PChar_Send,BuffLen);  
   
  ReadData应该是读吧?  
   
  你的例子:  
  请求:  
  0103   00380001XX  
  01=>hdr  
  03=>cmd  
  00=>len  
  38=>crc  
  即无数据,后面的数据就错了  
   
  按协议,好像是这样写的  
  PRTUData   =   ^TRTUData;  
  TRTUData   =   packed   record  
      hdr:   Byte;  
      cmd:   Byte;  
      len:   Byte;  
      data:   array   [0..0]   of   Byte;  
      crc:   Byte;  
  end;  
   
  data取决于len的长度

var  
      P:   PByte;  
      rtuLen:   Byte;  
      rtu:   PRTUData;  
  begin  
      rtuLen   :=   SizeOf(TRTUData)   +   DataLen   -   1;  
      rtu   :=   allocMem(rtuLen);  
      rtu.hdr   :=   $01;  
      rtu.cmd   :=   $02;  
      rtu.len   :=   DataLen;  
      P   :=   @rtu.data[0];  
      for   I   :=   0   to   DataLen   -   1   do  
      beg  
          P^   :=   $XX;  
          inc(P);  
      end;  
      P^   :=   crc(xxx);       //   P   ==>   crc  
      WriteData(...,   rtu,   rtuLen)  
  end;

先谢谢ERR0RC0DE()    
  我知道了,你是先发送命令,WriteData(...,   rtu,   rtuLen),然后在通过ReadData(Usb_Index,PChar_Send,BuffLen);读取数据,是吧?  
   
 

看不懂,^_^  
   
   
  顶下!

有兴趣的朋友欢迎继续讨论阿

posted on 2009-03-02 11:28  delphi2007  阅读(640)  评论(0编辑  收藏  举报