一串口通讯程序在WIN98及WINME下工作正常,但WIN2K和XP下不行。
调试时,总是发现取回的校验值不对。
怎么办?

解决方案 »

  1.   

    to:sailer_shi(笨笨虫) 
    要怎么办呢?
    我把发送的程序贴上来吧:
    1:计算机通过查询式方式和单片机通讯。(计算机发送读命令,单片机返回状态数据)
    2:发送的命令格式是:机号+命令+CRC
    3:发送机号时,RTS为高电平,发送命令和CRC时,RTS为低电平
    4:单片机收到数据时,首先返回55H,然后再返回状态数据。
    经过跟踪调试,发现在2000及XP下根本收不到55H,所以,就什么数据都收不到了。
    程序是用API与的,在98及ME下,工作很正常。
    代码:
       LenOfSbuf:=length(sssbuf); //-----取数据帧长度。
    //------------------------------  准备工作  ----------------------------//
    //??? setupcomm(hcom,4096,4096);//---------input buff and output buff is 4096 bytes.
     getcommstate(hcom,lpdcb);
     lpdcb.BaudRate:=CBR_1200;//----------BautRate is 1200 bps.
     lpdcb.StopBits:=OneStopBit;
     lpdcb.ByteSize:=8;
     lpdcb.Parity:=3;  //----------------恒为1,传号校验。
     setcommstate(hcom,lpdcb);
    /////////-------------------------^^^^^^^^^^^^
       ResetEvent(post_event);
       PurgeComm(hCom,PURGE_TXCLEAR);//---清发送缓冲
       PurgeComm(hCom,PURGE_RXCLEAR);//---清接收缓冲。
       EscapeCommFunction(hcom,CLRRTS);//--------改RTS为高电平,发送模式。
       sleep(10);
    //--------------------------送机号地址----------------------------------//
       writefile(hcom,sssbuf[1],1,snum,lpol);//---送机地址。
    //   waitforsingleobject(POST_EVENT,infinite);
       GetOverlappedResult(hcom,lpol^,snum,true);
       resetevent(post_event);
       if snum<1 then
       begin
    //      form11.myshowmessage('发送错误!');
          exit ;
       end;
       sleep(10);
    //------------------------- 送数据 -------------------------------------//
     getcommstate(hcom,lpdcb);
     lpdcb.BaudRate:=CBR_1200;//----------BautRate is 1200 bps.
     lpdcb.StopBits:=OneStopBit;
     lpdcb.ByteSize:=8;
     lpdcb.Parity:=4; //----------------------恒为0,空号校验。
     setcommstate(hcom,lpdcb);
     EscapeCommFunction(hcom,CLRRTS);//--------保持RTS为高电平,发送模式。
     sleep(10);  for i:=2 to LenOfSbuf do
       begin
        writefile(hcom,sssbuf[i],1,snum,lpol);//--发送数据到串口。
    //    waitforsingleobject(POST_EVENT,infinite);
        GetOverlappedResult(hcom,lpol^,snum,true);
        resetevent(post_event);
        if snum<1 then
        begin
    //      form11.myshowmessage('发送错误!');
          exit ;
        end;
        sleep(10);
      end;///!!!    writefile(hcom,sbuf[2],Lenofsbuf-1,snum,lpol);//--发送数据到串口。
     //------------------------- 送数据完毕,进行接收返回信息----------------//   while true do
       begin
         clear:=clearcommerror(hcom,lperrors,@coms);
         if clear  then
         begin
            cbNum:=coms.cbOutQue;
            if cbnum<1 then break;
         end;
       end;   EscapeCommFunction(hcom,SETRTS); //------改RTS为低电平,进入接收模式。
    //   sleep(1);   PurgeComm(hCom,PURGE_TXCLEAR);//---清发送缓冲
       PurgeComm(hCom,PURGE_RXCLEAR);//---清接收缓冲。
      

  2.   

    delphi中常用串口控件简介:
    mscomm:微软的东西,是VB中带的一个ActiveX控件,使用简单,性能一般,由于是ActivX控件,打包时需要注册好多信息,在Delphi中使用,建议使用VCL控件,编译程序时直接编入程序中,再不需任何其它处理。
    spcomm:比较好的vcl控件,算是比较专业的,解剖了一下,功能比较完善。
    TurboPower:公认的专业通讯vcl控件。可以到其站点下载,开放源码了。
    我在制作串口通讯软件时三种都用过,最终全部使用TurboPower!所以也推荐大家使用它。
    写了个例子,基本的串口通讯都可以实现,可提供参考:
    下载基地-》文件名称:串口通讯控制器
    版权声明:以下本文只允许在本站观看,不得以任何媒体方式进行传播。
    发表意见请到留言版。TurboPower串口通讯实际应用:
    在串口通讯时有字符和十六进制两种数据传输方式,不论使用哪种方式,只要能正确收到数据就是目的,至于收到数据后如何处理,就要根据具体的情况来定了。1.接收数据的方法:
    轮询和中断(利用windows消息激发事件)。
    1)轮询:每间隔一定的时间查询一下串口接收缓存中有无数据,有就读出来。这种方法是很毫资源的,即没事找事。
    2)中断:在控件中有OnTrigger事件,当串口收到数据后,即触发此事件,无数据时什么都不做,在这个事件中接收数据就比较科学了。
    所以,提倡使用控件中的OnTrigger事件接收数据。2.通讯协议的制定:
    接收数据的一般处理方法,最基本的思路就是通过协议进行分析,所以协议的制定是至关重要的:
    1)首先要确定指令的起始点,从大量的数据流中将指令分离出来,没有起始标志的话,结果就可想而知了,一串无效的费数据!
    2)然后就是指令结束识别点,可以利用指令的长度(如果长度一定或有表示长度的数据)或结束标志来确定,当然还可以利用下一条指令的指令头。
    3)既然头尾都明确了,指令的截取想来不是什么问题了吧!但还有一种情况就是数据错误是的容错,如何容错呢,最简单的办法:发现不符合格式的指令,就将其抛掉或特殊处理(如要求重发)一下!
    4)有效数据中如果增加一些校验,通讯将会更加可靠!
    例:#(指令头)**(指令功能)0123456789(有效数据)**(有效数据校验和)%(指令尾)
    注:**代表变动值。3.接收数据的分析技巧:
    通讯协议制定好后,一切将以通讯协议为中心。一套协议中的所有指令可能长度都是统一的,也有可能是长短不同的,并且在OnTrigger事件中实际反应速度及快,可能一条指令数据还没有完全收齐就已经触发了此事件,即收到了半截指令,并且有可能继续收取的数据中除了下半截指令外,还有下一条指令的前半截,如何处理?
    我在做这种处理时是利用全局变量,将串口收到的所有数据都收到该串中,然后按指令格式进行截取,发现不合法指令做一下特殊处理(如要求重发)或抛弃。
    如收到的数据串为:
    #**0000012000**%#**0000000343#**000000540560**%#**0002200000**%
    分段截为:
    #**0000012000**%
    #**0000000343
    #**000000540560**%
    #**0002200000**%
    四条指令,其中:#**0000000343不完整,检测到后进行抛弃处理。调试技巧篇:
    对于已了解协议的支持串口产品,要想进行编程控制,可以使用“串口通讯控制器”进行调试,以摸清具体实现数据,可按如下步骤进行:
    1.确定硬件连接无误,这是首要条件,如果错误将没有成功的可能;
    连线必须正确,必要时可以使用计算机自带的多个端口相互进行测试,已保证硬件的连接无误。串口通讯线有9针和25针,多用9针,其中最重要的是2(RXD)、3(TXD)、5(GND)线,对应关系如下:
    9针 25针
    2 -- 3
    3 -- 2
    5 -- 72.确定通讯参数正确,如:波特率、奇偶校验位、数据位、停止位等,以及收发的是十六进制还是字符串:3.以上确保正确,则使用“串口通讯控制器”,按协议输入数据进行收发控制了。
    注意:有的仪器需要进行初始化,即先发一段激活指令,然后才能进入工作状态,这种设置主要是为了实现利用硬件为软件加密,即类似加密狗,需要有激活方法才行,不过该类方法使用较少。原创作者:JPYC,望业界专家多多指正!控件及例程源码请到:http://www.kaer.cn/default.aspx->软件基地
      

  3.   

    你的问题,我估计主要是因为通讯参数方面,使用了什么非标参数(也可能是你的设备的波特率不标准),如波特率使用了4009等不在:1200/2400/4800/9600/192000等之内。解决的方法是:比如你用的是标准的 1200 ,调整一下他的范围,找到上下限,去中间值。通常我们做的串口设备选择标准拨特率来实现,如果采用了非标,将来有很多问题,如有些模拟串口设备不能良好的支持非标(USB转COMM)。
      

  4.   

    简单一点,现在你的重新写一个程序,很简单,只需要一个Edit就可以了
    让你的单片机给你发送指令,你用这个程序去接收一下,看看能不能受到55H的数据
    如果能收到的话,那么就是你的程序出现了问题,如果还是收不到的话,那我估计就是你系统的毛病了
      

  5.   

    jpyc(九品御厨-进军嵌入式) 说的对,因为不同的操作系统的实时性不同呀!
      

  6.   

    在xp及2k系统下,将你的时间因子设成大于等于10,如果还出现意外,往大加,在98下不管设成多小,最小单位为55,这是因为98系统的时钟是以54.9ms为单位工作的,而xp及nt系统是以10ms为单位工作的,最小可以设到5ms,不是系统也是程序的问题,是因为对系统不熟悉。
      

  7.   

    刚才帮你请教了一个高手,他的意思是98底下写的串口程序在2000地下可以正常的用,因为塔已经写了很多了,你是不是可以把程序放到2000底下进行编译,或者跟踪一下程序,看看到底那里出错了,还有如果你的程序不大的话直接用控件把,不要用Api函数了,你可以到网上去当一个接受串口的程序,让他来接收传回来的信息,如果他能收到的话,那就是你的程序出错了,如果还是不能的话,那么就是你的系统出了毛病
      

  8.   

    to:ffwin
    我把时间因子从1设到了156,都没有成功呀。to:sailer_shi(笨笨虫) 
    源程序在在XP下编译,运行的。但就是收不到。
    我之前也是想用SPCOMM,但我看这里有现成的(以前公司的同事写的),就没有用控件了大家帮我看一下这个接收的程序是否有问题呢?
    //////接收第一个BYTE ,是否  55H
    function  tfjyjcomm.Receive55h(mno:integer):boolean;
    var
      flag:boolean;
      counttime:Integer;
      rnum:cardinal;
      bcdmno:byte;
    begin
      bcdmno:=asc1tobcd1(mno);
      rbuffer:='';
      counttime:=0;
      flag:=True; while true do
      begin
         counttime:=counttime+1;
         if counttime>6 then  ///原来为  10   ;changed on 12.11 ;
         begin
           flag:=False;
           break;
         end;
         readfile(hcom,ch,1,rnum,lpol);
         waitforsingleobject(POST_EVENT,infinite);
         GetOverlappedResult(hcom,lpol^,rnum,true);
         if rnum<>1 then
            begin
              flag:=False;
            end
         else
          if ((ch=chr($55)) or (ch=chr(bcdmno))) then
             begin
               flag:=True;//---------------接收到帧头,已经成功。
               rbuffer:=rbuffer+(ch);
               head:=ord(ch);
               break;
          end
         else
                 ;
      end;
      Result:=flag;
    end;