你好,请问各位高手们,我现在使用DELPHI+SPCOMM想开发一个对下位机设备的串口通讯程序,但是使用过程中遇到这样的问题,还想大家指教指教。比如MOBUS RTU 的协议我使用了3号命读取下位机的两段寄存器,(比如读取的寄存器是0200H~023FH,和0280H~02BFH)两段寄存器都是有64个的,
我用发送的命令分别是:03   03   02   00   00   40   44   60
                 :03   03   02    80   00   40   45   88 
                  地址 3号命令 起始位置   读取长度    CRC校验接收的格式是:地址 命令号 数据长度 数据1 数据2........CRC校验
             (两者返回数据开头都是:03 03 80 xx xx .........,返回长度也一样)对于以上的情况,就是发送的起始地址不同,但是读取长度是相同的,两个命令返回的数据都是131个字节,在SPCOMM的Comm1ReceiveData方法中要判断的话,要怎样判断啊?我是直接定义了一个定时器定时发送以上两个发送命令的,是不是能够设定我发送第一个命令后,一定要等接收了数据,判断后,再发送第二个命令这样啊?不是很懂, 不知一般是用长度来区分还是怎样做才好,迷茫中,请高手们指教指教还有一个问题就是,如果我发送的命令比较多,是不是都要在一个Comm1ReceiveData方法里面判断啊?如果程序较大,是不是能够单独出来一个单元直接用来发送接收的,再传给其他单元使用啊?????不知具体是用全局变量还是怎样做,还请高手指导一下,最好能详细一点,小弟不胜感激,谢谢谢谢
                  

解决方案 »

  1.   

    1 Comm1ReceiveData事件中bufferlength可以得到数据的长度
    2 spcomm组件有个readintervaltimeout属性用来设置,Comm1ReceiveData事件的时间,简单的说如果Comm1ReceiveData=100,那么在一百ms的时间中的数据有200个那么bufferlength就是200
      

  2.   

    你好,下位机是固定的使用MOBUS RTU协议的,不能更改啊?继续请教......
      

  3.   

    其實也可以用CreateFile,ReadFile來操作.
      

  4.   

    1. 发一条后等待,返回后再发另外一条, 若超时,重发或丢弃。
    2,这只是程序结构上的问题,这个随便你了,你可以在commentsreceivedata里先根据命令号先做一次区分,在调用不同的函数来解析。
      至于是否用 全局变量也是看你通讯的数据了,如果非常固定,你可以使用了。这个东西没什么太多建议,主要是和你具体的工作相关。
      

  5.   

    你好,那样请问具体在spcomm上是如何来使用啊?谢谢
      

  6.   


    const
      sendarr1: array[0..7] of byte=(03,03,02,00,00,40,44,60);
      sendarr2: array[0..7] of byte=(03,03,02,80,00,40,45,88);var
      sendflag: integer;
      rdat1,rdat2: array[0..130] of byte;procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
    var
      rbuf:   array of byte;
      i:      integer;
    begin
      setLength(rbuf, BufferLength);
      move(Buffer^, PChar(rbuf)^, BufferLength);
      if (bufferlength=131) and (sendflag=1) then
      begin
        // rdat1<-rbuf
      end;
      if (bufferlength=131) and (sendflag=2) then
      begin
        //rdat2<-rbuf
      end;
    end;procedure TForm1.send(sbuf: array of byte);
    begin
      for i:=0 to length(sbuf)-1 do
        comm1.WriteCommData(sbuf,length(sbuf));
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      sendflag:=1;
      send(sendarr1);
      sleep(100);
      sendflag:=2;
      send(sendarr2);end;
      

  7.   

    你好,谢谢yuqianyi1974的回答,那么如果我发送的命令很多,是不是都要堆在Comm1ReceiveData里面去判断和提取啊?如果我要做成一个单元可以么?具体要怎样做呢?再请教请教,谢谢
      

  8.   

    继续求教,刚才试了yuqianyi1974 的方法,但是还是不行啊,如果我吧edit.txt:=inttostr(sendflag);放在Comm1ReceiveData里面来看,那个sendflag的值一直都是2啊,没有出现过1的情况啊,即使我把发送的sleep改到了1000,都还是一直显示2啊,只有第二个命令的回复可以接收啊,为什么啊?求教中,谢谢
      

  9.   

    纠正一下procedure TForm1.send(sbuf: array of byte); 
    begin 
    for i:=0 to length(sbuf)-1 do 
    begin 
    comm1.WriteCommData(sbuf[i],1); 
    //这儿是否需要考虑延时 
    end; 
    end;
      

  10.   

    不知道在你发送命令后,下位机每次上传的长度多少?(有发送一个命令后,下位机分多批数据上传数据)还要根据Com口波特率设置相应延时。我印象中我在做双核Cpu的情况下,总是会不定时的出现Com口假死现象,不知道你们有没有遇见过这种情况?
      

  11.   

    串行通讯访问MODBUS从站,我做过小项目,从站是几台秤,它的控制器采用MODBUS/RTU协议从站,
    我用MSCOOM32.OCX轮询同步方式访问(非事件),应答很快;
    很简单!你给它发MODBUS串,发完后就在规定的时间内(否则超时处理)接收应答.
      

  12.   

    Modbus是轮询的,你发1个命令后必须等待命令返回或者超时候才能发第2个。SPCOMM会性缓冲所有接收到的串口数据后才会触发Comm1ReceiveData消息,所以这个消息触发的时候,你已经收到了全部数据,可以调用函数做处理了。
      

  13.   

    你好,谢谢你们的回答,我刚才测试了下yuqianyi1974告诉的方法,就是在发送函数哪里延迟,但是这样做的话整个程序不知道为什么就会莫名奇妙的很慢啊,我比如我设置了比较大sleep(2000),整个程序几乎不会东啊,我好像发现每次接收都是两组数据差不多同事过来的啊,不能做到发送一个,接收,等待一下,再发送,再接收,现在的情况是:发送一个命令,等待SLEEP,再发送一个命令(用time定时发送),但是接收的时候都会是两个同时上来啊(用memo看),不知怎样才能做到发送后,接收,判断,再发送,接收这样啊?这个sleep()使用起来怎么会好像整个程序都会拖慢了么?谢谢
      

  14.   

    如果下位机接收没有问题,你这样发送一组数据就行,不用sleep
    procedure TForm1.send(sbuf: array of byte); 
    begin 
      comm1.WriteCommData(sbuf,length(sbuf)); 
    end; 
      

  15.   

    最好的方法还是建议楼主研究下SPCOMM组件,然后改进它再用:
    //1、将MODEM通讯用的参数去除,不受0x11和0X13限制
    //2、简化串口参数设置过程
    //3、提高发送数据接收目标窗体效率
    //4、注意:目标窗体接收过程和发送速度1定要匹配呵呵,注意组件中是用POSTMESSAGE的,上位机接收速度跟不上会丢包的。
    学习组件前,建议楼主学下:
    1、事件、信号在线程控制中的作用;
    2、用消息传递数据(为了封装读的事件,记得这里好象有个缓冲复制过程,影响效率);
    3、重叠结构异步读写的作用。
    学习透彻了应该比较收益的。
      

  16.   

    谢谢大家爱的回答啊,提供了很多以后学习的宝贵意见,就是现在目前我想了解的就是,为什么我发送的时候,明明已经在每个命令之间用sleep延时了,但是接收还是基本上同步的上来啊,好像没有延时读上来的感觉啊?(而且sleep的时候如果时间太长了,整个程序都不能动啊,为什么?)是不是SPCOMM里本身就是这样啊?谢谢