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

解决方案 »

  1.   

    //读数据
    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;
      

  2.   

    对于传输帧,我现在有点疑惑:
    我传向下位机请求和从下位机得到数据都是以上面我和下位机开发人员定义的格式传输并不象下面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
      

  3.   

    //发送命令
          //测试屏蔽
          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的长度
      

  4.   

    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;
      

  5.   

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