последовательный порт не будет работать в delphi

#delphi #serial-port #hyperterminal

#delphi #последовательный порт #hyperterminal

Вопрос:

Я создаю простую программу на Delphi для отправки символа через COM-порт, используя 2 параметра, первый параметр — это номер порта, а второй параметр — это символ, который нужно отправить. Итак, если я сохраню его как p.exe , «p.exe 20 A» отправит «A» через COM20.

 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;
 

И я также использую hyperterminal с тем же номером COM baudrate= 9600, flow_control= none, и это дает тот же результат. Символ отправлен правильно.
Проблема в том, что я не могу запустить свою программу (p.exe ), прежде чем я буду выполнять следующие действия каждый раз при входе в свою Windows XP:
Подключитесь через hyperterminal к указанному COM,
отключите его.
тогда мой исполняемый файл может быть запущен. В противном случае, точно так же, как вы запускаете два сеанса hyperterminal в одном и том же COM, это не сработает. У кого-нибудь есть намек на это? Я что-то пропустил в своем коде?

Комментарии:

1. 1 за проверку работоспособности с помощью Hyperterminal.

2. Итак, «не работает», вы получаете сообщение об ошибке «невозможно открыть …», «невозможно отправить» или что?

3. вам нужно использовать setcommstate для скорости передачи данных в бодах.

4. Ваш обработчик исключений считывается hCommFile до того, как он обязательно был записан. Если первый параметр командной строки не числовой, вы очищаете и удаляете недопустимый дескриптор. Кроме того, в случае CreateFile сбоя вы продолжаете использовать hCommFile , даже если это Invalid_Handle_Value .

5. Какие настройки скорости передачи, четности и управления потоком (аппаратные / программные / выключенные), по вашему мнению, будут использоваться? Если вы новичок в последовательных портах, могу я предложить вам использовать компонент (TComPort или AsyncPro).

Ответ №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;
 

Комментарии:

1. устройства связи получают DCB по умолчанию при создании

2. @Преждевременный: Точно, но, возможно, скорость передачи данных DCB в бодах по умолчанию, четность, управление потоком и т.д. — это не совсем то, что нужно операционной системе. Лучше всего явно установить этот материал и сделать его видимым для пользователя. Когда вы закончите писать все материалы пользовательского интерфейса для com-порта, четности, конфигурации управления потоком, вы можете просто скачать и использовать TComPort . sourceforge.net/projects/comport

3. тьфу, извините, создание с нуля, я имел в виду открытие ( CreateFile(OPEN_EXISTING) ). @Warren P, да, но defaults предназначен для использования вместо explicit . OP просто нужно предварительно настроить его порт. Кстати, эта ссылка кажется мне чрезмерно сложной.