【问题标题】:serial port won't work in delphi串口在delphi中不起作用
【发布时间】:2011-11-01 14:03:14
【问题描述】:

我正在Delphi中创建一个简单的程序,使用2个参数通过COM端口发送字符,第一个参数是端口号,第二个参数是要发送的字符。因此,如果我将其保存为 p.exe,“p.exe 20 A”将通过 COM20 发送“A”。

try
   PhoneNumber := ParamStr(2);

   if(StrToInt(ParamStr(1))>=10)then
   CommPort := '\\.\COM'+ParamStr(1)
   else
   CommPort := 'COM'+ParamStr(1);
   hCommFile := CreateFile(PChar(CommPort),
                          GENERIC_WRITE,
                          0,
                          nil,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          0);
   if hCommFile=INVALID_HANDLE_VALUE then begin
      ShowMessage('Unable to open '+ CommPort);
   end;
  if WriteFile(hCommFile, PChar(PhoneNumber)^, Length(PhoneNumber),NumberWritten, nil)=false then
    showmessage('Unable to send');
  PurgeComm(hCommFile,PURGE_TXCLEAR);
  FlushFileBuffers(hCommFile);
  CloseHandle(hCommFile);
  Application.Terminate;
except
  PurgeComm(hCommFile,PURGE_TXCLEAR);
  FlushFileBuffers(hCommFile);
  Application.Terminate;
end;

我还使用具有相同 COM 号 baudrate=9600, flow_control=none 的超级终端,它给出了相同的结果。角色发送良好。 问题是,每次登录 Windows XP 时,在执行以下步骤之前,我都无法运行我的程序 (p.exe): 通过超级终端连接到指定的 COM, 断开它。 然后我的可执行文件可以运行。否则,就像您在同一个 COM 中运行两个超级终端会话一样,它不会工作。有人对此有提示吗?我是否遗漏了代码中的任何内容?

【问题讨论】:

  • +1 用于使用超级终端进行健全性检查。
  • 所以“不起作用”,您是否收到“无法打开...”错误、“无法发送”或什么?
  • 波特率需要使用 setcommstate。
  • 您的异常处理程序在写入之前读取hCommFile。如果第一个命令行参数不是数字,则清除并刷新无效句柄。此外,如果 CreateFile 失败,您将继续使用 hCommFile,即使它是 Invalid_Handle_Value
  • 您假设将使用什么波特率、奇偶校验和流量控制(硬件/软件/关闭)设置?如果您对串口完全不熟悉,我建议您使用一个组件(TComPort 或 AsyncPro)。

标签: delphi serial-port hyperterminal


【解决方案1】:

我在您的代码中没有看到任何设置内容。因此,也许您依赖运行 HyperTerminal 的副作用来为您“启动”端口。看看这篇文章,他们在其中经历了这些事情:波特、奇偶校验等。

http://www.delphi-central.com/serial.aspx

这似乎是一个完整的工作示例。看看你是否可以让它工作,并用作构建的基础。

【讨论】:

    【解决方案2】:

    您需要使用 setcommstate 来设置波特率和流量控制。

    Function OpenPort( Var fHandle: THandle; fPort: String): Boolean;
    Const
     RxBufferSize       = 32;
     TxBufferSize       = 32;
    Var
     dcb                : TDCB;
     tms                : TCOMMTIMEOUTS;
    Begin
     Result := False;
     Try
      If fHandle <> INVALID_HANDLE_VALUE Then
       CloseHandle( fhandle );
     Except
     End;
     Try
      //fport must be \\.\ URN format
      fhandle := CreateFile( PChar( fPort ), GENERIC_WRITE or GENERIC_READ, FILE_SHARE_WRITE ,
                             Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
      If ( fhandle = INVALID_HANDLE_VALUE ) Then
       Begin
        result := false;
        exit;
       End;
      SetupComm( fhandle, RxBufferSize, TxBufferSize );
    
      If pos( 'LPT', fPort ) > 0 Then
       //
      Else
       Begin
        GetCommState( fhandle, dcb );
        dcb.DCBlength := sizeof( dcb );
        dcb.BaudRate := cbr_9600;
        dcb.Flags := 1;                     // binary...
        if dtr_rts then
        begin
         dcb.flags := dcb.Flags Or $20;      //DTR HANDSHAKE
         dcb.Flags := dcb.Flags Or $1000;    //rts handshake
         dcb.Flags := dcb.Flags Or 4;        //Outx_CtsFlow
         dcb.Flags := dcb.Flags Or 8;        //Outx_DsrFlow
         dcb.Flags := dcb.Flags Or $40;      //DsrSensitivity
         //dcb.Flags := dcb.Flags or $100;//Outx_XonXoffFlow
         //dcb.Flags := dcb.Flags or $200;//Inx_XonXoffFlow
        end;
        dcb.ByteSize := 8;
        dcb.Parity := EVENPARITY;
        dcb.StopBits := ONESTOPBIT;
        SetCommState( fhandle, dcb );
        GetCommTimeouts( fhandle, tms );
        tms.ReadIntervalTimeout := 100;//you can change multipler values with
        tms.ReadTotalTimeoutMultiplier := 100;//your values
        tms.ReadTotalTimeoutConstant := 1;
        SetCommTimeOuts( fhandle, tms );
       End;
      EscapeCommFunction( fhandle, CLRRTS Or CLRDTR Or SETRTS Or SETDTR );//for handshaking
      Result := True;
     Except
      Result := False;
     End;
    End;
    

    用法

    var 
        fporthandle:thandle;
       begin
        if OpenPort(fporthandle,'\\.\com1') then
          try
           writefile(fporthandle,pchar('TEST')...);
          finally
            closehandle(fporthandle);
          end;
    

    【讨论】:

    • 通信设备在创建时接收默认 DCB
    • @Premature:没错,但也许默认的 DCB 波特率、奇偶校验、流量控制等并不是 OP 所需要的。最好明确设置这些内容,并使其对用户可见。当你写完所有关于 com 端口波特率、奇偶校验、流量控制配置的 UI 内容后,你不妨下载并使用TComPortsourceforge.net/projects/comport
    • 抱歉,从头开始创作,我的意思是打开 (CreateFile(OPEN_EXISTING))。 @Warren P,是的,但默认值旨在改为显式使用。 OP 只需要预先配置他的端口。顺便说一句,这个链接对我来说似乎是过度设计的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    相关资源
    最近更新 更多