1

How can I send multiple hex codes in delphi? for example, the hex codes I need to send to the serial port is 1B and 40. How can I send it to the serial port? I can send hex codes to the serial port already but just one hex code like 1B only, I am having difficulty sending multiple hex codes. Thanks in advance.

my code:

unit uSample;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, Winsoft.Android.ComPort,
  FMX.Edit, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    AComPort1: TAComPort;
    Memo1: TMemo;
    Timer1: TTimer;
    Button1: TButton;
    Edit1: TEdit;
    Open: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure OpenClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
     AComPort1.Active := False;
     AComPort1.DeviceName := Edit1.Text;
     AComPort1.Active := True;

     AComPort1.WriteUtf8(Memo1.Text);
     AComPort1.WriteByte(Byte($0A));
end;

procedure TForm1.OpenClick(Sender: TObject);
begin

end;

procedure TForm1.Timer1Timer(Sender: TObject);
var Text: string;
begin

end;

end.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
dembers
  • 41
  • 8
  • You have to first understand the problem clearly enough to state it. You are sending hex? That's text. A representation of a value in base 16. Or are you sending binary bytes? Do you understand that `16 = $10`? So, are you sending text or binary? And how? Where is your code? – David Heffernan Mar 14 '16 at 07:41
  • 1
    So you aren't trying to send hex, you are trying to send binary. If you can send one byte can't you send multiple. Hard to see what your problem is. – David Heffernan Mar 14 '16 at 08:19
  • I've tried sending it by $1B+$40 and $1B$40 still not working but if it is just one code like $0A, it works. Btw, thanks for the answers. – dembers Mar 14 '16 at 08:38
  • The code in the question sends some text, encoded as UTF8, and then a single byte. It only attempts to send a single byte but you said you wanted to send multiple bytes. Why are you sending text? And where is the code to send multiple bytes? Does the component have a method to send byte arrays? Do you appreciate now that `16 = $10` and that hex is just a representation of the value? – David Heffernan Mar 14 '16 at 08:43
  • @SirRufo `WriteByte($0A)`, removing the pointless cast, appears to deal with a byte and not a char. It's the same as `WriteByte(10)`. To be clear, `$10` is not a char, it's an integer literal. – David Heffernan Mar 14 '16 at 08:45
  • So we might expect the component to have a method, perhaps named `WriteBytes` that accepts a byte array. Either `const Bytes: array of Byte` or `const Bytes: TBytes`. You would then pass your array of bytes to this method. If this component does not have such a method you would call `WriteByte` twice, or indeed more times. However, a library that asked you to write a byte array one byte at a time would be bizarre. So I fully expect there to be a `WriteBytes` method, perhaps with a different name. Maybe `WriteBuffer`, or just `Write`. Do you have documentation for `TComport`? – David Heffernan Mar 14 '16 at 08:56
  • No documentation because what I use is only the trial version. The methods that the component include are: AComPort.Write, AComPort.WriteUtf8, AComPort.WriteLine, AComPort.WriteLineUtf8, AComPort.WriteChar, AComPort.WriteByte, AComPort.WriteWord, AComPort.WriteLongWord. – dembers Mar 14 '16 at 09:06
  • What type parameter(s) does the `Write` method take? You have to be sceptical of a library that has no documentation. Do you understand my point about representations yet? It feels like you are not facing up to that point. Building on weak foundations leads to trouble. You need to get these concepts clear early on. And FWIW, this is really less of a Delphi question and more of a Winsoft TComport question. A point that the question doesn't really get across. – David Heffernan Mar 14 '16 at 09:13
  • Buffer - System.Pointer Count - System.Integer WaitForCompletion - System.Boolean – dembers Mar 14 '16 at 09:21
  • There you go. Pass the address of the first byte, the number of bytes, and, presumably, `True` to indicate a synchronous call. – David Heffernan Mar 14 '16 at 09:25
  • @TomBrunberg You are totally right, I shouldn't post anything before the first coffee :o) – Sir Rufo Mar 14 '16 at 09:26
  • Actually, @TomBrunberg, you've got that syntax mixed up. It's not `$#0A`, that's a syntax error. You mean `#$0A`. – David Heffernan Mar 14 '16 at 09:30
  • Yeah I will try. Thanks for your help. – dembers Mar 14 '16 at 09:33
  • @David I join choirs with SirRufo :) Just that I need a second coffee. – Tom Brunberg Mar 14 '16 at 09:43
  • @TomBrunberg I start with tea .......... ;-) – David Heffernan Mar 14 '16 at 09:50

2 Answers2

6

According to the comments, this component contains a method with the following signature:

procedure Write(Buffer: Pointer; Count: Integer; WaitForCompletion: Boolean);

This presumably is the low level method through which all other write methods pass. You might wrap this up with a high level method that accepted an array of bytes:

procedure TForm1.WriteBytes(const Buffer: array of Byte);
begin
  if Length(Buffer) > 0 then begin
    AComPort1.Write(@Buffer[0], Length(Buffer), True);
  end;
end;

I'm assuming that you would pass True for the final parameter and make the call synchronous.

You could then call the method like this:

WriteBytes([$1B, $40]);

If you are comfortable with class helpers, you might add such a method as a class helper for TComport.

Do note that there was some confusion in the question over what hex really is. You are not attempting to send hex to the device. Hexadecimal is a representation of a value. And these values could equally be represented as decimal. So the code above is equivalent to:

WriteBytes([27, 64]);

Hexadecimal is just one of many ways to write down a number. The underlying value is the same. So, 16 = $0A. You can write the value as decimal, as hexadecimal, or indeed in other representations. You are not sending hex, you are sending bytes. Colloquially, you are sending binary data.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

If you want to interpret string 1B40 as two bytes $1B and $40 and then send it to COM port. First you need to split string '1B40` into individual hex text such as '1B' and '40' for example (Code from this question)

procedure StrToStringList(const aSource: String;
                        const aList: TStrings;
                        const aFixedLen: Integer);
var
  idx: Integer;
  srcLen: Integer;
begin
  aList.Capacity := (Length(aSource) div aFixedLen) + 1;

  idx    := 1;
  srcLen := Length(aSource);

  while idx <= srcLen do
  begin
    aList.Add(Copy(aSource, idx, aFixedLen));
    Inc(idx, aFixedLen);
  end;
end;

Then you call

aHexStrings = TStringList.create();
StrToStringList(Memo1.Text, aHexStrings,2);    

to split string into list of strings, each string consist of 2 character length. For each item in string list, you convert its hex string to its byte representation by using StrToInt() and write it to COM port. Note that StrToInt() will interpret string '$1B' as integer $1B.

for i:=0 to aHexStrings.count-1 do
begin
  AComPort1.writeByte(Byte(StrToInt('$'+aHexStrings[i])));
end;

This code is definitely not so fast because overhead of string split task and write a byte at a time.

If your input string is $1B$40 then you can avoid string concatenation with '$' during writeByte() as in the example above but you need to split string for each 3 character length.

Community
  • 1
  • 1
Zamrony P. Juhara
  • 5,222
  • 2
  • 24
  • 40