在与PLC通讯时,反馈的信息出现时好时坏的现象(乱码),已头痛了半个月多了,帮助!

解决方案 »

  1.   

    补充:利用线程连接一快PLC时,一切正常,连接两快PLC时,就会出现此现象!
      

  2.   

    用的是什么TCP组件,可能是线程间的通记讯处理不好。
      

  3.   

    我一种用的是TcpClient控件,一种用的是WINSOCK动态连接库,有相同的情况!用的是线程数组,应该也是分开独立的吧?如果我把线程数组分开而用两个独立的线程运行就没问题!可是整个系统改动就大了
      

  4.   

    现场设备情况那?
    用线情况,设备距离,拓扑结构,延时和设备号的协议设置都有关系有可能时上位机端误读 也有可能是PLC端分时抢用错误具体情况 具体分析贴点错误信息和源代码上来看看。
      

  5.   

    读:   s_recstr:='';
       proc_initcom(ps_crn_ip);
       s_crnhead := #0+#0+#0+#0+#0+#6+#$FF+#3+#0+#$A+#0+#$1E;
       Send(sk,pointer(s_crnhead)^,Length(s_crnhead),0);
       n:=recv(sk,Buf,209,0);
       for i:=1 to 30  do
       begin
          m:=i;
          num:=256*ord(buf[i*2 + 8]) + ord(buf[i*2 + 9]);
          dev_sts[m]:=num;      s_recstr:=s_recstr+inttostr(num);
       end;
       Closesocket(sk);
       sleep(ci_CRNtimeInterval);写:procedure TMXCraneThread1.proc_SetCrn_ID(i_type1,i_srow1,i_sbay1,i_slev1,i_drow1,i_dbay1,i_dlev1 : integer);
    var s_crnhead,s_chksum,s_SendString : String;
        s_RecStr : String;
        i_nRetry : integer;
        b_OK : Boolean;
        s_mess,s_type,s_srow,s_sbay,s_slev,s_drow,s_dbay,s_dlev,add:string;
        bte :array [1..14] of byte;
        bte1:array [1..2] of byte;
    begin
       i_nRetry := 1;
       b_OK := False;
       repeat
         s_type :=inttohex(i_type1,4);
         bte[1] :=hextodec(copy(s_type,1,2));
         bte[2] :=hextodec(copy(s_type,3,2));     s_srow :=inttohex(i_srow1,4);
         bte[3] :=hextodec(copy(s_srow,1,2));
         bte[4] :=hextodec(copy(s_srow,3,2));     s_sbay :=inttohex(i_sbay1,4);
         bte[5] :=hextodec(copy(s_sbay,1,2));
         bte[6] :=hextodec(copy(s_sbay,3,2));     s_slev :=inttohex(i_slev1,4);
         bte[7] :=hextodec(copy(s_slev,1,2));
         bte[8] :=hextodec(copy(s_slev,3,2));     s_drow :=inttohex(i_drow1,4);
         bte[9] :=hextodec(copy(s_drow,1,2));
         bte[10]:=hextodec(copy(s_drow,3,2));     s_dbay :=inttohex(i_dbay1,4);
         bte[11]:=hextodec(copy(s_dbay,1,2));
         bte[12]:=hextodec(copy(s_dbay,3,2));     s_dlev :=inttohex(i_dlev1,4);
         bte[13]:=hextodec(copy(s_dlev,1,2));
         bte[14]:=hextodec(copy(s_dlev,3,2));     add :=inttohex(100,4);
         bte1[1]:=hextodec(copy(add,1,2));
         bte1[2]:=hextodec(copy(add,3,2));     proc_initcom(ps_crn_ip);
         s_crnhead := #0+#1+#0+#0+#0+#$15+#$FF+#$10+chr(bte1[1])+chr(bte1[2])+#0+#$7+#$E+chr(bte[1])+chr(bte[2])+chr(bte[3])+chr(bte[4])+chr(bte[5])+chr(bte[6])+chr(bte[7])+chr(bte[8])+chr(bte[9])+chr(bte[10])+chr(bte[11])+chr(bte[12])+chr(bte[13])+chr(bte[14]);
         Send(sk,pointer(s_crnhead)^,Length(s_crnhead),0);     ps_crnthr_mess_sendtocrn :='01000$15$FF$1010007$E'+s_type+s_srow+s_sbay+s_slev+s_drow+s_dbay+s_dlev;
         Synchronize(proc_Update_ptmemo_crnthr_mess_send);
         Sleep(ci_CRNtimeInterval);
         Closesocket(sk);      Inc(i_nRetry);
              if i_nRetry=3 then
                begin
                   b_OK := True;
               end;
        until (b_OK=TRUE);
    end;
      

  6.   

    上面是用WINSOCK=================================================
    这是用TCP/IP控件(都有相同的问题):读:
       s_crnhead := #0+#0+#0+#0+#0+#6+#$FF+#3+#0+#$A+#0+#$1E;
       ps_crnthr_mess_sendtocrn :='000006$FF30$A0$1E';
       Synchronize(proc_Update_ptmemo_crnthr_mess_send);   p_TcpClient_crn.Active:=true;
       p_TcpClient_crn.Sendln(s_crnhead)  ;
       pi_return:=p_TcpClient_crn.ReceiveFrom(buf,209,p_TcpClient_crn.GetSocketAddr(p_TcpClient_crn.RemoteHost,p_TcpClient_crn.RemotePort),n,0);   if pi_return>0 then
         begin
         recstr:='';
         for i:=1 to 30  do
         begin
           m:=i+99;
           num:=256*ord(buf[i*2 + 8]) + ord(buf[i*2 + 9]);
           dev_sts[i]:=num;
           recstr:=recstr+inttostr(num);
         end;     ps_crnthr_mess_response := recstr;     proc_Show_crn_response_MSG;
       end;   Sleep(ci_CRNtimeInterval);
         p_TcpClient_crn.Disconnect;
         p_TcpClient_crn.Active:=false;   proc_Add_crn_Seqcount;
       if Trim(ps_crnthr_mess_response)<>'' then
       begin
            proc_crnstatus(ps_crnthr_mess_response);
       end;写:   i_nRetry := 1;
       b_OK := False;     s_type :=inttohex(i_type1,4);
         bte[1] :=hextodec(copy(s_type,1,2));
         bte[2] :=hextodec(copy(s_type,3,2));     s_srow :=inttohex(i_srow1,4);
         bte[3] :=hextodec(copy(s_srow,1,2));
         bte[4] :=hextodec(copy(s_srow,3,2));     s_sbay :=inttohex(i_sbay1,4);
         bte[5] :=hextodec(copy(s_sbay,1,2));
         bte[6] :=hextodec(copy(s_sbay,3,2));     s_slev :=inttohex(i_slev1,4);
         bte[7] :=hextodec(copy(s_slev,1,2));
         bte[8] :=hextodec(copy(s_slev,3,2));     s_drow :=inttohex(i_drow1,4);
         bte[9] :=hextodec(copy(s_drow,1,2));
         bte[10]:=hextodec(copy(s_drow,3,2));     s_dbay :=inttohex(i_dbay1,4);
         bte[11]:=hextodec(copy(s_dbay,1,2));
         bte[12]:=hextodec(copy(s_dbay,3,2));     s_dlev :=inttohex(i_dlev1,4);
         bte[13]:=hextodec(copy(s_dlev,1,2));
         bte[14]:=hextodec(copy(s_dlev,3,2));     add :=inttohex(100,4);
         bte1[1]:=hextodec(copy(add,1,2));
         bte1[2]:=hextodec(copy(add,3,2));
         s_crnhead := #0+#1+#0+#0+#0+#$15+#$FF+#$10+chr(bte1[1])+chr(bte1[2])+#0+#$7+#$E+chr(bte[1])+chr(bte[2])+chr(bte[3])+chr(bte[4])+chr(bte[5])+chr(bte[6])+chr(bte[7])+chr(bte[8])+chr(bte[9])+chr(bte[10])+chr(bte[11])+chr(bte[12])+chr(bte[13])+chr(bte[14]);     ps_crnthr_mess_sendtocrn :='01000$15$FF$1010007$E'+s_type+s_srow+s_sbay+s_slev+s_drow+s_dbay+s_dlev;
         Synchronize(proc_Update_ptmemo_crnthr_mess_send);
         p_TcpClient_crn.Active:=true;
         p_TcpClient_crn.Sendln(s_crnhead)  ;
         Sleep(ci_CRNtimeInterval);
         p_TcpClient_crn.Disconnect;
         p_TcpClient_crn.Active:=false;     Inc(i_nRetry);
         if i_nRetry=3 then
           begin
             b_OK := True;
           end;
      

  7.   

    延时的问题 你把每台仪表请求发送的间隔再加长
    因为我们用的是TCP/IP协议 但是底层协议的物理电气层协议的本质还是串口所以如果用我们和服务器交流的概念和PLC交流 
    可能PLC的速度不能满足你的软件设置速度误差累计到了一段时间 就可能造成缓冲区接收池溢出
    重新启动 等于清空了缓冲区 试着改变延时试试
      

  8.   

    能不能给我一段正确的TcpClient 读、写的语句?各位,帮忙了!
      

  9.   

    "1个PLC用1个线程+接收缓冲"但是串口寄存器还是只有一个的
    现在设备故障不在于软件的缓冲区的问题
    而是因为底层的串口硬件的缓存区问题
    所以增加线程不能根本解决误差问题
    用2个串口还差不多
      

  10.   

    请问 用TCP/IP和PLC通讯,应该是点对点的通讯,而不是一对多的情况,那么,楼主开辟2个线程,会不会造成数据
    的叠加呢?
    我刚刚从事这方面,也是做上位TCP/IP机和PLC通讯的,用的是三菱的产品,在搜集资料中,请多多指教。
      

  11.   

    没搞过和PLC通信,不过如果是TCP/IP的话应该都是一样的。先定义一个客户端类,在用户登陆时创建并且保存在TClientList中
    TClient=class
      Socket:TSocket;
      SocketBuf:Array of Byte;
      SocketBufIndex:Integer;
    end;
    //保存所有客户端的列表
    TClientList=class
      FList:TList;end;
    //SOCKET对象收到数据
    procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      obj:TClient;
    begin
      先通过SOCKET查找到对应的客户端对象
      obj:=TClientList.FindClient(Socket);
      Socket.ReceiveBuf(obj.SocketBuf,数据长度);//这里是关键,将所客户端发来的数据保存在客户端对象
       各自的缓冲区中
      obj.SocketBufIndex:=obj.SocketBufIndex+这次收到的数据长度;
    end;现在每个客户端自己的数据都保存在自己对应的缓冲区了。每个客户端的缓冲区可以设置成10K
    如果数据满了则在扩大。
    在另外搞一个线程,检查TClientList中的每个客户端的缓冲区,如果有数据就将数据业务处理,然后
    SocketBufIndex也相应该的缩短要注意的是如果向缓冲区写数据和处理数据不是一个对象的话,要进行线程保护。