• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4802
  • Last Modified:

Serial port read/write

I need complete code of writing to serial port.
This is what I need:

I need to send a string of hexa to the serial port and receive another string of hexa from there (and translate it later)
The string I need to send is:
The received data will also be hexa, and I need to append it to a table in specific columns of a table (but that is not a problem for me, so don't bother)
The sending of the data will happen periodically (but that's also my problem to solve, not yours)

Please do not point me to various other links in experts-exchange or links to components... I've been there already. But sadly I have no experience in communicating with the serial port (not even using any third party component to do it).
So please give me working code (perhaps using a specific third party component)

I must give you here a list of freeware components that seem to work just fine with the serial port (but obviously they work for someone that has some experience with serial ports):

  • 13
  • 9
2 Solutions
MerijnBSr. Software EngineerCommented:
What port, baud rate, handshake settings?
calinutzAuthor Commented:
port - COM1,
baudrate - 9600,
FlowControl - XOnXOff,
parity - none
StopBits - 1
ByteSize - 8

I am confused... I have no ideea how to manage this. I happen to have another software (without source) that does this communication but I do not seem to be able to make it work, and to get responses from the other side.

Maybe it's the way I send the data through, or maybe the way I read it... But I think mainly the problem it's my sending the string of hexa...

So another program called ZeitControl Windowed Einzel works like a charm for sending and receiving the hexa information... But I can't seem to get it done.
As I already said... the string to send looks like this:\$f0\$41\$30\$4f\$f7, and I don't even know if the sent text is normal to look like this... Because I don't know what the serial port wants to receive and what transmits forward, what does it look like...

All I know is that when I send this text to the serial port, on the terminal, only the hexa appears without "$" and "\", so:
I send: \$f0\$41\$30\$4f\$f7, and in the terminal appears:F0 41 30 4F F7, and then come the response of the machine on the other side of the serial port... also in hexa...
And I also have an option to see the communication (not hexa) and the response looks more intelligible.

The software I am talking about I believe is made and given by the manufacturer of the hardware, but we do not get any other support to develop our own communication software. So I am stuck here.
This is how it looks like:


I need to be able to do the same in my software. Send a hexa string and receive another hexa string.
As you can see the blue string is the sent string and the rest is the response. Also I need to send all those 6 strings, and receive responses for each one of them, then save them to a database table. All this mus be in a timer. That's all... I should not be so complicated...

Please help.

MerijnBSr. Software EngineerCommented:
So you don't have any documentation on the protocol? Do you know how to parse the result?
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

calinutzAuthor Commented:
Nothing... I just know how the result should look like...
Like you saw there(in the picture) in hexview... I am sending a string of 5 hexa numbers... and I receive 73 hexa numbers.
If I uncheck the hexview, then intelligible information is visible...
I figure... if I know this, I could decode the hexa.
Is there any way of sending 5 hexa chars.... and just read the response? Is it more complicated than that?
If it is then tell me what should I be looking for...
But if it is possible to do the sending and receiving without anything else there... please tell me how can I do that?
I believe there must be a way of reading the response of the serial port... no matter what that would be... The problem is that I could not manage to get a response from the serial port... with any component...
Maybe it's the way I am sending the data to the serial port...? Maybe I do not know how to read from it?

Cand you give me a code that will send the above string to the serial port using any component  (freeware) ?
 And then receive the response from the serial port?
I made a scrrenshot of the Einzel software when sending the same string of hexa... viewed in hexa then viewed not in hexa...:

So it is pretty clear to me that I must send a string of 5 hexa numbers to the serial port...
Then the serial port will reply with another string of hexa numbers. And when I convert the hexa cu ASCII, I will obtain my needed values.
Watch this:
In hex view
Send string:
F0 41 30 4F F7
F0 61 20 30 20 30 2E 30 30 30 20 30 30 30 30 2E 30 30 20 30 30 30 30 30 30 30 31 2E 39 31 20 30 30 30 30 32 37 36 33 2E 34 38 20 2E F7

Conversion to ASCII:
Sent string:
Received string:
ða 0 0.000 0000.00 00000001.91 00002763.48 .

The interesting part is that when I use the zeitcontrol software the "ð" char is replaced with "-". That-s all the difference.

So the zeitcontrol software non-hex terminal display looks like this:
Sent string:
Received string:
-a 0 0.000 0000.00 00000001.91 00002763.48 .,

Basically I converted manually the hexa to ASCII and confronted with the non-hexview of the zeitcontrol software display

So actually I need to take the numbers generated after the conversion and enter them into a database.
But please help me obtain the result hex string, after sending the initial string...

It's like this: on the other side of the serial port there are 6 weighing machines that send back their measurements. So in the initial string that I am sending... there is probably an id of the machine and the command that tells it to reply with the measurements needed. The ID of the machine is probably the third and fourth hexa numbers from the string that I am sending (because only they differ)
Same way... in the result obtained, as you can see (in the translated string)
-a 0 0.000 0000.00 00000001.91 00002763.48 .,
"-a" stays the same, and the next number (in this case 0 ) represents the ID of the weighing machine... because for the other 5 input strings the resulted number will be 1,2,3,4,5

So this is what I discovered.
I am 99.99% sure that the reply from the machines is formated to use the exact same number of hexa numbers to represent their measurements (hence "0000.00").
So can you help me building the code that sends the string of hexa and receive the other string of hexa?
All the rest of the translation and the database is piece of cake.

Thank you so far
calinutzAuthor Commented:
Conversion to ASCII:
Sent string:
Received string:
ða 0 0.000 0000.00 00000001.91 00002763.48 .÷

And the zeitcontrol software replaces 2 ASCII chars:
The "ð" with "-"
and the "÷" with ","

Not that this is important... i just corrected myself so you don't see incomplete information above
MerijnBSr. Software EngineerCommented:
OK, I don't have a complete working example, but some quite useful stuff.

First of all, this is all quite simple, nothing to worry about.

I suggest you use this open source component: https://sourceforge.net/projects/comport/

See below a chunk of code which probably works all the way, but I can't test it (I don't have your device).
Come back with questions if you have any!

unit main;
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, CPort, StdCtrls;
  TForm2 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    { Private declarations }
    fCPort: TComPort;
    procedure OnRxBuf(Sender: TObject; const Buffer; Count: Integer);
    { Public declarations }
  Form2: TForm2;
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
 // write the 'magic string'
procedure TForm2.FormCreate(Sender: TObject);
var s: string;
 // create the comport component
 fCPort := TComPort.Create(Self);
 // configure it
 fCPort.BaudRate := br9600;
 fCPort.Parity.Bits := prNone;
 fCPort.DataBits := dbEight;
 fCPort.StopBits := sbOneStopBit;
 fCPort.FlowControl.XonXoffOut := true;
 fCPort.FlowControl.XonXoffIn := true;
 fCPort.Port := 'com1';
 // set the rx data event handler
 fCPort.OnRxBuf := OnRxBuf;
 // all set, now open the port
procedure TForm2.OnRxBuf(Sender: TObject; const Buffer; Count: Integer);
 // here you receive data, you can check if Count = 73 so you know you're data is all there

Open in new window

calinutzAuthor Commented:
Apparently I wasn't doing the job correctly.
I had to convert the sent string to a Binary Array and convert it to AnsiString before sending it.
Now it works like a charm.
Thank you for your time.
I will ask for deletion of the question and a refund.
calinutzAuthor Commented:
Sorry... I did not see your answer when I posted my comment.
If your code works I'll award you with the points even if I found my solution. I think it's only fair.
But only if your solution works ;)
Thank you again.
MerijnBSr. Software EngineerCommented:
> But only if your solution works ;)

Big guess since I couldn't test it :p
calinutzAuthor Commented:
Any suggestions on reading the result string in the OnRxBuf event?
I would appreciate it.
I cannot test your solution without it. (I really don't know how to convert the serial port response to hexa or ascii)
I solved my problem using another freeware component called serialPortNG... and it returns a string already converted from hexa to ASCII... so all I need to do now is split it into pieces and write it in the database.

I am open to use your solution, or at least award you with the points for your time, but I will need a full solution for sending the input string and receiving the result string.
calinutzAuthor Commented:
Here's my code... very easy (I'm angry with myself for not solving it sooner)
// all the settings of my port are being done in Object inspector since I only need this code to work on a specific port, with specific settings, so I do not setup the components properties in the code.

procedure TForm1.Button1Click(Sender: TObject);
  BinArr: array of Byte;
  SetLength(BinArr, 5);
//240 65 48 79 247 that represent the decimal values of the hexa string

procedure TForm1.SerialPortNG1RxClusterEvent(Sender: TObject);

And this is all... My memo receives the result like this
ða 0 0.000 0000.00 00000001.91 00002763.48 .÷

So it's perfect for me now.
But I repeat... If you give me the code that works with the other component... I will reward you with the points
MerijnBSr. Software EngineerCommented:
Since you already receive a string, so this should do:

procedure TForm2.OnRxBuf(Sender: TObject; const Buffer; Count: Integer);
var Data: string;
 SetLength(Data, Count);
 CopyMemory(@Data[1], @Buffer, Count);

Open in new window

calinutzAuthor Commented:
Your code shows me this error...:

"COM port error. Unable to get async status on COM1."


Actually I had to modify the code a little because it's not working as you wrote it. Here is the code changed:

procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.ComPort1RxBuf(Sender: TObject; const Buffer: PAnsiChar;
  Count: Integer);
var Data: string;
 SetLength(Data, Count);
 CopyMemory(@Data[1], @Buffer, Count);

Open in new window

calinutzAuthor Commented:
Having the component set up on design time...
This is the dfm
object Form1: TForm1
  Left = 366
  Top = 178
  Width = 524
  Height = 398
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 56
    Top = 60
    Width = 457
    Height = 305
    Lines.Strings = (
    TabOrder = 0
  object Button1: TButton
    Left = 56
    Top = 32
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  object ComPort1: TComPort
    BaudRate = br9600
    Port = 'COM1'
    Parity.Bits = prNone
    StopBits = sbOneStopBit
    DataBits = dbEight
    Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full]
    FlowControl.OutCTSFlow = False
    FlowControl.OutDSRFlow = False
    FlowControl.ControlDTR = dtrEnable
    FlowControl.ControlRTS = rtsDisable
    FlowControl.XonXoffOut = True
    FlowControl.XonXoffIn = True
    OnRxBuf = ComPort1RxBuf
    Left = 172
    Top = 8

Open in new window

MerijnBSr. Software EngineerCommented:
Ah, that's probably since I don't use the last version on the website :)
As far as I'm concerned you don't have to continue your search if you already have a working solution, only if you're interested in it yourself...
calinutzAuthor Commented:
If you still want the points I can ask you to help me forward with my code and give you the points for the next help...
That is... I am struggling now with sending and receiving.
So In the end I need to do the following:
STEP1: Send hex string \$f0\$41\$30\$4f\$f7
STEP2: Receive the answer and place it somewhere
STEP3: Send another hex string \$f0\$41\$31\$4e\$f
STEP4: receive the answer and place somewhere
... and so on.
(I have 6 hex strings to send, so I need to obtain 6 results in connection with the sent string)
Basically I have a stringgrid with 2 columns I need to place the input string on first column and the received string on the second column, for each 6 input strings.
I have difficulties (probably setting up the component) with the received string.
I need to wait until a full response has arrived before sending the next string.

Can you help here?
I'll attach the project in a zip file and you-ll get in the zip file a picture of the result of the execution.
Are you interested?

These steps must
MerijnBSr. Software EngineerCommented:
You said you have this working with the other serial component, didn't you?

So it's just a matter of keeping track where you are in the process, or am I mistaken?
calinutzAuthor Commented:
That is my problem actualy. Since I don't seem to know when is the received string complete... I mean when to start the next sending of string.
Can you assist me? I could send you my sourcecode and you could look at it. Especially at the component... there has to be a way to know when the receiving is over.
I even tried to stop the port and start it again for the next string, but I am doing something wrong. Perhaps you have a more rested mind.

The components  use are: KStringGrid and SerialPortNG. I'll include them also in the zip, together with a screenshot of the result. Give me an email address
MerijnBSr. Software EngineerCommented:
It's not really useful to sent me the sources since I can't test anything here (I don't have your device).

But I don't really see the problem though: you know how much data you expect back after each string you sent.
You can simply wait until you receive all 73 bytes before you sent the next command?
calinutzAuthor Commented:
This is exactly where I need your help.
How to wait until I receive all the bytes?
Considering that the component receives the response through this procedure:


Perhaps you can see something I don't...
Maybe your solution could do the work better than my solution.
All you need to do is analyze my code (meybe find something I did not), and maybe suggest something... maybe another approach. Perhaps your component works better than mine, offers more info to work with.
I would attach the code here in a zip file but it does not let me, this is why I was asking for your email address.
I'm waiting... :)
MerijnBSr. Software EngineerCommented:
send it to merijnb@xs4all.nl
calinutzAuthor Commented:
I solved my problem using a timer.
Thank you anyway.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 13
  • 9
Tackle projects and never again get stuck behind a technical roadblock.
Join Now