部分代码如下:
type
  TRS485 = class(Tcomponent)
     // 通讯串口
     Timer1: TTimer;            //引用Timer控件
     constructor create(AWoner:Tcomponent);override;
     destructor destroy; override;
     //初始化串口通讯
     procedure comminitialize;
     procedure Timer1Timer(Sender: TObject);//定时器
implementation
constructor TRS485.create;
begin
  Timer1 := TTimer.Create(nil);
  Timer1.Interval := 200; //每200秒就触发事件
  Timer1.OnTimer := Timer1Timer;
end;
procedure TRS485.comminitialize;                     // 串 行 口 初 始 化
Begin
    //Timer1.interval := 200; //每200秒就触发事件
  Timer1.Enabled := false;
end;
procedure TRS485.Timer1Timer(Sender: TObject);//定时器 每200MS触发一次事件
begin
  CurCommandState := stOverTime;
end;
Procedure TRS485.FSM;
begin
  CurCommandState := stSndCmd;
  while true do
  begin
    case CurCommandState of
      stSndCmd:
      begin
        SndTimes := SndTimes + 1;
        //OverTimeFlag := 0 ;
        SndCommand;
        CurCommandState := stWaitAck ;
        Timer1.Enabled := true;//启动定时器
      end;
      .........
     end;
end;
现在问题是我在TRS485.FSM;这个过程中 Timer1.Enabled := true就已经设为启动了,但是现在问题是每隔200MS这个事件不能启动啊(也就是不能触发Timer1Timer(Sender: TObject)这个过程啊,帮我解决,谢谢!。很急,在线等,谢谢

解决方案 »

  1.   

    进入死loop肯定是程序出了问题!!
    我喜欢用时钟控件去触发一个命令按钮的事件,而在界面上我会将那个命令按钮delete.
    你的程序运行完了就将Timer1.Enabled := false就好了
      

  2.   

    Procedure TRS485.FSM;
    begin
      CurCommandState := stSndCmd;
      while true do
      begin
        case CurCommandState of
          stSndCmd:
          begin
            SndTimes := SndTimes + 1;
            //OverTimeFlag := 0 ;
            SndCommand;
            CurCommandState := stWaitAck ;
            Timer1.Enabled := true;//启动定时器
          end;
    这段代码有问题
      

  3.   

    但是我在每隔200MS时候触发Timer1Timer(Sender: TObject)这个过程啊,从这里退出来啊,但是现在问题是我的Timer1Timer(Sender: TObject)这个过程事件不能触发啊,有谁知道什么原因啊?谢谢拉
      

  4.   

    Mrkang(代奥肥):谢谢,是什么问题?可以说的明白点吗?谢谢
      

  5.   

    上面的while一开始我就是要他进入死循环,因为当串口没有读到数据的时候我让他继续读,直到200MS的时候就触发定时器,在这个事件里写状态是否退出死循环,但是现在的问题是这个定时器的事件不能触发啊,谢谢各位大哥的帮忙啊,很急的,谢谢拉!
      

  6.   

    你使用while死循环占用的内存太大了系统根本不可能会去响应OnTimer
    你不能把读串口的过程也放到OnTimer里面做吗?
      

  7.   

    master_jt(master):谢谢您,是的,我在另个工程里测试了,好象就是你所说的问题,是while循环的问题,你说在ontimer事件中读,我开始也想这样做,但是我想了最后还是要进入死循环的,程序思想是:因为我给他200MS的响应时间,在200MS之内如没有读到串口的内容要让他继续不断的读串口,当超过200MS的时候,响应OnTimer事件触发:作用是要对方的PC重新发命令,并判断是否发送命令超过三次,如超过了,那么就回到超时状态进行退出。
    如放在ontimer里做的话,一样也要一开始进入死循环啊,你说呢?
      

  8.   

    代码如下:各位大虾帮我看下,谢谢!帮我解决谢谢!
    unit uRS485;
    interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs,  StdCtrls, ExtCtrls,QExtCtrls, CPort, CPortCtl;
    type
       TCommand = class
        // 命令状态
        State: integer;
        // 命令类型
        Kind: integer;
        CommandStr: String;
        private
         {private declaration}
        public
          {public declaration}
       end;   TRS485 = class(Tcomponent)
         // 通讯串口
         ComPort: TComPort;         //
         constructor create(AWoner:Tcomponent);override;
         destructor destroy; override;
         //初始化串口通讯
         procedure comminitialize;
         procedure commclose;
         procedure Timer1Timer(Sender: TObject);//定时器
         procedure SendData;//发送数据
         procedure FSM;//有限状态机
         // 发送命令种类
         procedure SndCommandCategory(kind:Integer);
         // 发送命令
         procedure SndCommand;
         // 接受回答
         procedure ComPortRxChar(Sender: TObject; Count: Integer);//接受命令
         private
         {private declaration}
         Timer1: TTimer;
         CurCommand: TCommand;
         // 当前命令状态
         CurCommandState: integer;
         RepeatTimes: integer;
         SndTimes: integer;
         SndShakeHandstring : string;//存发送握手命令的字符
         RcvShakeHandstring : String;//存接受握手命令的字符
         SndStr : String;//存发送命令的字符
         RcvStr : String;//存接受命令的字符
         i : Integer;
         rbuf : array [1..6] of byte;
         sbuf : array [1..6] of byte;
         hcom,Post_Event:Thandle;//设置串行口变量
         public
          {public declaration}
          //Constructor create(AWoner:Tcomponent);override;
       end;
    const
      { Command Kind 命令类型 }
      stSndCmd = 1;      // 发送状态
      stWaitAck = 2;     // 等待状态
      stRcvAck = 3;      //接受到数据状态
      stOverTime = 4;    // 超时状态
      stEnd = 5;         //结束状态
      { 485状态 }
    implementation
    constructor TRS485.create;
    begin
      ComPort := TComPort.Create(Self);
      Timer1 := TTimer.Create(nil);
      Timer1.Enabled := false;
      Timer1.Interval := 200;//每200秒就触发事件
      Timer1.OnTimer := Timer1Timer;
      ComPort.OnRxChar := ComPortRxChar;
    end;destructor TRS485.destroy ;
    begin
      inherited destroy;
    end;procedure TRS485.comminitialize;                     // 串 行 口 初 始 化
    Begin
      if ComPort.Connected then
        ComPort.Close
      else
        ComPort.Open;
      ComPort.Port := 'com1';
      ComPort.BaudRate := br9600;
      ComPort.DataBits := dbEight;
      ComPort.StopBits := sbOneStopBit;
      ComPort.Parity.Bits  := prEven;
      //Timer1.interval := 200; //每200秒就触发事件
      //Timer1.Enabled := false;
    end;procedure TRS485.Timer1Timer(Sender: TObject);//定时器 每200MS触发一次事件
    begin
      CurCommandState := stOverTime;
    end;procedure TRS485.SendData;
    var
      i : integer;
    begin
      SndStr := '' ;
      for i:= 1 to 5 do
      begin
        SndStr := SndStr + inttohex(sbuf[i],2)  + '' ;
      end;
      ComPort.WriteStr(SndStr);
    end;procedure TRS485.SndCommand;
    var
      Kind:Integer;
    begin
      //SndShakeHandCommand; //在发送每条命令前都要建立一次握手
      SndCommandCategory(0);
    end;Procedure TRS485.FSM;
    begin
      CurCommandState := stSndCmd;
      while true do
      begin
        case CurCommandState of
          stSndCmd:
          begin
            SndTimes := SndTimes + 1;
            SndCommand;
            CurCommandState := stWaitAck ;
            Timer1.Enabled := true;//启动定时器
          end;
          stWaitAck:
          begin
            ComPortRxChar(self,20);//读端口方法
            if RcvStr = '' then
            begin
            end
            else
            begin
              CurCommandState := stEnd;
            end;
            //CurCommandState := stRcvAck;
          end;
          stOverTime:
          begin
            if SndTimes > 3 then
            begin
              CurCommandState := stEnd;
            end
            else
            begin
              SndTimes := SndTimes + 1; //继续发送
              CurCommandState := stSndCmd;
            end
          end;
          stEnd:
          begin
            //break;
            Timer1.Enabled := False;
            exit;
          end;
          else
          begin
          end;
        end;
      end;
    end;procedure TRS485.SndCommandCategory(Kind:Integer);//发送命令的类别
    begin
      case Kind of
        0:   //结束命令
        begin
          sbuf[1] := byte($A5);
          sbuf[2] := byte($FF);
          sbuf[3] := byte($FF);
          sbuf[4] := byte($FF);
          sbuf[5] := byte($01);
          SendData;
        end;
      end;
    end;procedure TRS485.ComPortRxChar(Sender: TObject; Count: Integer);  //读端口
    Var
      Temp_receive : array of byte;
      I,rec_len : byte;
      Calculate_crc,rec_crc,reg,reg_value : word;
    Begin
      RcvStr := '';
      ComPort.ReadStr(RcvStr, Count);
    end;procedure TRS485.commclose;
    begin
      ComPort.Close;
    end;
    end.