Board index » delphi » Accessing serial ports with Delphi 3???

Accessing serial ports with Delphi 3???

Hi all!!

Is there a way to gain access to the serial ports under Delphi 3 ?

I need to write an application which reads data from and writes to e.g.
COM1. I've not found any predefined components, nor were there informations
in the Delphi online-help.

I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
because i don't have the time to check the newsgroups frequently.

Thanks in advance

Patrick Echterbruch

 

Re:Accessing serial ports with Delphi 3???


Quote
>Is there a way to gain access to the serial ports under Delphi 3 ?

>I need to write an application which reads data from and writes to e.g.
>COM1. I've not found any predefined components, nor were there informations
>in the Delphi online-help.

>I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
>because i don't have the time to check the newsgroups frequently.

Check Delphi Super Page. There is a component (shareware) TSerial. I used it
with Delphi 1, in connection with a electronic weigh. I think, I have seen
this component for a D3 also.

The second, much better and also much more expensive solutions is Async from
Turbo Power. It is what I am using now, and it really is excelent.

brane

Re:Accessing serial ports with Delphi 3???


In article <Rwcz1.182$0k6.6334...@news.siol.net>, Brane
<branko.safa...@siol.net> writes
Quote
>>Is there a way to gain access to the serial ports under Delphi 3 ?

>>I need to write an application which reads data from and writes to e.g.
>>COM1. I've not found any predefined components, nor were there informations
>>in the Delphi online-help.

>>I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
>>because i don't have the time to check the newsgroups frequently.

>Check Delphi Super Page. There is a component (shareware) TSerial. I used it
>with Delphi 1, in connection with a electronic weigh. I think, I have seen
>this component for a D3 also.

>The second, much better and also much more expensive solutions is Async from
>Turbo Power. It is what I am using now, and it really is excelent.

>brane

If you've got access to (yeuch) VB controls, you can add the MSCOMM
control to the Delphi toolbar. Delphi puts its own VCL wrapper around
the COM interface and you can use it as is.

I agree Asynch is good too - and it's not MS!!
--
J A Baker

Re:Accessing serial ports with Delphi 3???


Hi.
I've started trying to do the same thing here. I have to control an electronic
measuring device (For which I have a small turbo pascal program on a dos box [A
Spectraradiometer controller actually] that acknowledges the requests and will
return data to my NT box via a 9600 baud rs-232) and then acquire the data for
manipulation.  I am trying Visual Basic's MsComm Active X component as a
kludge, but so far I'm not really impressed.  Consequently I want to find a
native Delphi Communications Port Object.

It would appear that the data I am getting can simply be passed to a TString (
I'm using a memo box) and then parsed with Memo.Lines[].  Then when
transmission is completed, I want the next instruction to execute.
Unfortunately the com port is so slow that I lose characters as program
execution just seems to continue. And for some reason I can't seem to get the
End of File sniffer to do anything.  I am trying to avoid timers.  So far this
has worked for a demo, but even as a newbie programmer, I can see all kinds of
problems with that.  I think that I could use the intermediate steps of polling
1 character at a time and doing tests on each character.  But I don't know how
exactly.
I'm sure others have walked this line before, so I pray that someone can step
forward and guide me in the right direction
Thanks for reading,
Dave
73 de va3ae

Quote
Patrick Echterbruch wrote:
> Hi all!!

> Is there a way to gain access to the serial ports under Delphi 3 ?

> I need to write an application which reads data from and writes to e.g.
> COM1. I've not found any predefined components, nor were there informations
> in the Delphi online-help.

> I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
> because i don't have the time to check the newsgroups frequently.

> Thanks in advance

> Patrick Echterbruch

Re:Accessing serial ports with Delphi 3???


Hi.
I've started trying to do a similar thing here. I have to control an electronic

measuring device (For which I have a small turbo pascal program on a dos box [A

Spectraradiometer controller actually] that acknowledges the requests and will
return data to my NT box via a 9600 baud rs-232) and then acquire the data for
manipulation.  I am trying Visual Basic's MsComm Active X component as a
kludge, but so far I'm not really impressed.  Consequently I want to find a
native Delphi Communications Port Object.

It would appear that the data I am getting can simply be passed to a TString (
I'm using a memo box) and then parsed with Memo.Lines[].  Then when
transmission is completed, I want the next instruction to execute.
Unfortunately the com port is so slow that I lose characters as program
execution just seems to continue. And for some reason I can't seem to get the
End of File sniffer to do anything.  I am trying to avoid timers.  So far this
has worked for a demo, but even as a newbie programmer, I can see all kinds of
problems with that.  I think that I could use the intermediate steps of polling

1 character at a time and doing tests on each character.  But I don't know how
exactly.
I'm sure others have walked this line before, so I pray that someone can step
forward and guide me in the right direction
Thanks for reading,
Dave
73 de va3ae
(Pull the obvious NO SPAM from the address if you wanna reply directly)

Quote
Patrick Echterbruch wrote:
> Hi all!!

> Is there a way to gain access to the serial ports under Delphi 3 ?

> I need to write an application which reads data from and writes to e.g.
> COM1. I've not found any predefined components, nor were there informations
> in the Delphi online-help.

> I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
> because i don't have the time to check the newsgroups frequently.

> Thanks in advance

> Patrick Echterbruch

Re:Accessing serial ports with Delphi 3???


Quote
In article <35D1DC4D.5B788...@nrc.ca>, David Scobie <daNO_vid.scSPAM_o...@nrc.ca> wrote:
>Hi.
>I've started trying to do a similar thing here. I have to control an electronic
>measuring device (For which I have a small turbo pascal program on a dos box [A
>Spectraradiometer controller actually] that acknowledges the requests and will
..
>It would appear that the data I am getting can simply be passed to a TString (
>I'm using a memo box) and then parsed with Memo.Lines[].  Then when
>transmission is completed, I want the next instruction to execute.
>Unfortunately the com port is so slow that I lose characters as program
>execution just seems to continue. And for some reason I can't seem to get the
>End of File sniffer to do anything.  

Having walked this road before, i can give this small peice
of advice...Forget the end of file markers! if you are dealing with comms.

You need to establish your own set of protocol ( ususally Chrs ) that will
serve as end of file marker. ASCII has it built in, and some
machines actually use it.

I dont think the com ports slow. It can take 115kbps so 9600
is nothing. Somethings amiss here.

I still have not found out what makes the world go round...

Re:Accessing serial ports with Delphi 3???


Quote
Patrick Echterbruch wrote:

> Hi all!!

> Is there a way to gain access to the serial ports under Delphi 3 ?

> I need to write an application which reads data from and writes to e.g.
> COM1. I've not found any predefined components, nor were there informations
> in the Delphi online-help.

> I'd appreciate you sending me a Mail directly to Echterbr...@td-service.de,
> because i don't have the time to check the newsgroups frequently.

> Thanks in advance

> Patrick Echterbruch

Patrick,

I've recently written a simple Delphi project which makes extensive use
of serial communications. The customer was unwilling to pay and thus the
following code was rotting away in my garbage can until I came across
your post. The comments are in German but I don't think you will have
any problem with that! :)

This program was written for and ran successfully under D1. It
(probably) uses the 16 bit comms API, but ran successfully under NT 4.0
and would probably run under W95 and W98. Also, I am guessing these APIs
are still supported under D2/D3/D4.

Essentially, Delphi is making C-like calls to the Windows API, which
offers a number of functions for sending characters, checking the number
of input characters available and reading those characters. The program
does not do much else, so for simplicity the input here is polled. An
interrupt driven implementation would be more CPU efficient but more
complicated.

The following is not demo code but an actual running program (minus the
form). I've forgotten how it works, so please try to figure it out for
yourself. If you have questions remaining, contact me at
   'ca...@ipf.de'
and I can try to help you further.

re's,

Carl

---------- snip here -----------
unit DeusMain;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, Buttons, Gauges, ExtCtrls, IniFiles,
  DeusImg;

type
  TfrmMain = class(TForm)
    pnlMain: TPanel;
    Balken: TGauge;
    txtData1: TLabel;
    txtData4: TLabel;
    txtData2: TLabel;
    txtData5: TLabel;
    Timer1: TTimer;
    txtData3: TLabel;
    txtData6: TLabel;
    pnlStatus: TPanel;
    pnlStatusLabel: TPanel;
    pnlStatusText: TPanel;
    lblStatusText: TLabel;
    pbxLed: TPaintBox;
    lblTaktText: TLabel;
    lblHeaderLinks: TLabel;
    lblHeaderRechts: TLabel;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure pbxLedPaint(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.DFM}

const
  CR = #13;

{ *** FEHLER *** }
const
  FehlerAllesOK = 0;
  FehlerTafelTimeout = 1;
  FehlerTafelKaputt = 2;
  FehlerHostTimeout = 4;

type
  TFehler = class(TObject)
  private
    FStatus: Integer;
  public
    constructor Create;
    procedure displayStatus;
    procedure setTafelTimeout;
    procedure setTafelKaputt;
    procedure setTafelOK;
    procedure setHostTimeout;
    procedure setHostOK;
    property Status: Integer read FStatus;
  end;

{ *** HOST *** }
type
  THostStatus = (HostOK, OpenFehler, HostTimeout);
  THost = class(TObject)
  private
    FStatus: THostStatus;
    procedure setStatus(st: THostStatus);
  public
    property Status: THostStatus read FStatus write setStatus;
  end;

{ *** TAFEL *** }
type
  TTafelStatus = (Gepollt, TafelTimeout, TafelOK, Tafelkaputt);
  TTafel = class(TObject)
  private
    FStatus: TTafelStatus;
    procedure setStatus(st: TTafelStatus);
  public
    Spalte1, Spalte2: String[12];
    property Status: TTafelStatus read FStatus write setStatus;
    procedure setActive(active: Boolean);
    procedure setText(Sp1, Sp2: String);
  end;

var
  Host: THost;
  Tafel: TTafel;
  Fehler: TFehler;

  SettingPort: Integer;     { COMn }
  SettingSpeed: LongInt;    { Baud }
  SettingInterval: Integer; { Sekunden }
  SettingDateiname: String; { Eingabedateiname }
  SettingStation: Byte;     { Tafel-Stationsadresse }

  Takt: Integer;

  Zeit: Integer;
  CommDCB: TDCB;
  CommOffen: Boolean;

procedure SeriellZeichenAusgeben(Zeichen: char); forward;

{ --------------------------------------------------------
  Allgemeine Routinen
  -------------------------------------------------------- }

{ Das Verzeichnis des EXE-Files zurckgeben }
function ExeDir: String;
begin
  ExeDir := ExtractFilePath(Application.ExeName);
end;

{ Daten umwandeln und auf COM-Port ausgeben }
procedure GibDatenAus(var Data1, Data2: String);
var
  GewandelteDaten: String;
  j: Integer;
begin
  GewandelteDaten := Data1 + Data2;
  for j := 1 to Length(GewandelteDaten) do
    SeriellZeichenAusgeben(GewandelteDaten[j]);
end;

{ Die Daten einlesen }
procedure LiesVomHost;
label 1, 2, 3;
var
  Datei: Text;
  VollerDateiName: String;
  OK: Boolean;
  Zeile1, Zeile2: String;
begin
  OK := false;
  VollerDateiName := ExeDir + SettingDateiName;
  if not FileExists(VollerDateiName) then goto 1;
  {$I-}
  AssignFile(Datei, VollerDateiName);
  if IOResult <> 0 then goto 1;
  Reset(Datei);
  if IOResult <> 0 then goto 3;
  if Eof(Datei) then goto 1;
  Readln(Datei, Zeile1);
  if IOResult <> 0 then goto 1;
  if Eof(Datei) then goto 1;
  Readln(Datei, Zeile2);
  if IOResult <> 0 then goto 1;
  { Hier alles OK }
  OK := true;
3: { Fehler-Recovery mit Close und Delete }
  CloseFile(Datei);
  if IOResult <> 0 then goto 2;
2: { Fehler-Recovery mit Delete }
  DeleteFile(VollerDateiName);
  if IOResult <> 0 then goto 1;
1: { Fehler-Recovery ohne Close oder Delete }
  {$I+}
  if not OK then begin
    if Host.Status = HostOK then
      Host.Status := OpenFehler
    else
      Host.Status := HostTimeout;
  end else begin
    { Daten sind OK - jetzt fuer die Tafel aufbereiten }
    Tafel.setText(Zeile1, Zeile2);
    Host.Status := HostOK;
  end;
end;

{ Ein Telegramm vom seriellen Port einlesen }
function SeriellEinlesen: String;
var
  Stat: TComStat;
  NChars: Word;
  Buf: Array[0..200] of Char;
  j: Integer;
  InputStr: String;
begin
  { Versuche, Text vom Port zu bekommen }
  InputStr := '';
  GetCommError(CommDCB.ID, Stat);
  NChars := Stat.cbInQue;
  if NChars > 0 then begin
    NChars := ReadComm(CommDCB.ID, Buf, 200);
    if NChars > 0 then begin
      for j := 1 to NChars do
        InputStr := InputStr + Buf[j-1];
    end; { if }
  end; { if }
  Result := InputStr;
end;

{ Die serielle Schnittstelle oeffnen }
function SeriellOeffnen: Boolean;
const                    { from DOC\WINTYPES.INT        }
  ie_BadID    = (-1);    { Invalid or unsupported id    }
  ie_Open     = (-2);    { Device Already Open          }
  ie_NoPen    = (-3);    { Device Not Open              }
  ie_Memory   = (-4);    { Unable to allocate queues    }
  ie_Default  = (-5);    { Error in default parameters  }
  ie_Hardware = (-10);   { Hardware Not Present         }
  ie_ByteSize = (-11);   { Illegal Byte Size            }
  ie_BaudRate = (-12);   { Unsupported BaudRate         }
var
  CommStat: Integer;
  PortName:  Array[1..20] of char;  { 'COM1' + #0; }
  CommParms: Array[1..50] of char;  { 'COM1:2400,N,8,1' + #0; }
begin
  StrPCopy(@PortName, Format('COM%d', [SettingPort]));
  StrPCopy(@CommParms, Format('COM%d:%d,N,8,1', [SettingPort,
SettingSpeed]));
  { Open COM port }
  CommStat := OpenComm(@PortName, 1024, 1024);
  if CommStat < 0 then begin
    MessageDlg(
      Format('Der Port %s konnte nicht ge?ffnet werden. ' +
             '(Fehlerstatus: %d)' + CR + CR +
             'Bitte w?hlen Sie  einen anderen Port oder ' +
             'beheben Sie ggfs. das Hardware-Problem!',
             [StrPas(@PortName), CommStat]),
      mtError, [mbOK], 0);
    Result := False;
  end else begin
    CommStat := BuildCommDCB(@CommParms, CommDCB);
    if CommStat < 0 then begin
      MessageDlg(
        Format('BuildCommDCB Error; String = "%s"', [CommParms]),
        mtError, [mbOK], 0);
      Result := False;
    end;
    CommStat := SetCommState(CommDCB);
    if CommStat < 0 then begin
      MessageDlg(
        Format('SetCommState Error %d', [CommStat]),
        mtError, [mbOK], 0);
      Result := False;
    end else begin
      CommOffen := True;
      Result := True;
    end;
  end;
end; { SeriellOeffnen }

{ Schnittstelle dicht }
procedure SeriellSchliessen;
begin
  if CommDCB.ID <> $FF then
    CloseComm(CommDCB.ID);
end;

{ Ein Zeichen aufs serielle Port ausgeben }
procedure SeriellZeichenAusgeben(Zeichen: char);
var
  Stat: TComStat;
  Buf: Array[0..0] of Char;
begin
  GetCommError(CommDCB.ID, Stat);
  Buf[0] := Zeichen;
  WriteComm(CommDCB.ID, @Buf[0], 1);
end;

{ Takt 0:
  Ggw. Status auf Display ausgeben, Tafel pollen. }
procedure Takt0;
begin
  Fehler.displaystatus;
  Zeit := Zeit + 1;
  if Zeit > SettingInterval then
    Zeit := 0;
  frmMain.Balken.Progress := Zeit;
  { Pollen = Stationsadresse ausgeben mit High Bit }
  SeriellZeichenAusgeben(Char($80 + SettingStation));
  Tafel.Status := Gepollt;
end;

{ Takt 1:
  Lies Daten von der Tafel ein.
  Entweder Kurztelegramm (= OK)
  oder Fehlertelegramm
  oder nix }
procedure Takt1;
var
  Telegramm: String;
begin
  Telegramm := SeriellEinlesen;
  if Telegramm = '' then begin
    Tafel.Status := TafelTimeout;
    Fehler.setTafelTimeout;
  end else if Length(Telegramm) = 1 then begin
    (* Kurztelegramm *)
    Tafel.Status := TafelOK;
    Fehler.setTafelOK;
  end else begin
    (* Fehlertelegramm auswerten *)
    Tafel.Status := TafelKaputt;
    Fehler.setTafelKaputt;
  end;
end;

{ Takt 2:
  1. Versuch, Daten vom Host zu lesen.
  Dies passiert nur, wenn das Intervall genau fertig ist. }
procedure Takt2;
begin
  if Zeit = SettingInterval then
    LiesVomHost;
end;

{ Takt 3:
  2. Versuch, Daten vom Host zu lesen.
  Nur, wenn der 1. Versuch gescheitert war. }
procedure Takt3;
begin
  if (Zeit = SettingInterval) and (Host.Status = OpenFehler) then
    LiesVomHost;
end;

{ Takt 4:
  Dummy-Read of
...

read more »

Other Threads