Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
Всем привет.
Столкнулся тут с одной задачкой и не могу ее решить.
Для работы с СОМ портом использую компонент ComPort из библиотеки ComPort Library. Для проверки работы программу - AccessPort.
В порт надо отправить команду AA 02 FF 00 00 A4 0F. ComPort для отправки принимает только значения string переменной. Перевожу команду в строку нарытым кодом:
function TForm1.HexToStr(HexStr : String; const Text : boolean = True): string;
var
  Hex : byte;
  sTemp : string;
  i : integer;
begin
  Result := '';
  HexStr:= StringReplace(HexStr, ' ', '', [rfReplaceAll]);
  if Length(HexStr) mod 2 <> 0 then
    Exit;

  for i := 2 to Length(HexStr) do
    if i mod 2 = 0 then begin
      sTemp := '$' + Copy(HexStr, i - 1, 2);
      Hex := Byte(StrToInt(sTemp));

      if Hex = $00 then begin
        if Text then
          Result := Result + ' '
        else
          Result := Result + #$00;
        Continue;
      end;

      Result := Result + chr(Hex);
    end;
end;

В результате получается строка https://prnt.sc/vdt0sm [url=]https://prnt.sc/vdt0sm[/url]
При выполнении команды
ComPort.WriteStr(Str);
в AccessPort мы видим https://prnt.sc/vdt529, что вместо 00 отправляется 20 (пробел, который образовался при конвертировании).

Подскажите как это можно исправить.
5 ноя 20, 10:18    [22226667]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
x1ca4064
Member

Откуда:
Сообщений: 1210
Hadroran,

Вызывайте HexToStr('AA 02 FF 00 00 A4 0F',false), а еще лучше напишите свой конвертер.

Сообщение было отредактировано: 5 ноя 20, 10:56
5 ноя 20, 11:00    [22226706]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
Hadroran,

а я в библиотеке вижу вот такой метод:
function Write(const Buffer; Count: Integer): Integer;


которым без проблем можно отправить буфер:

var
  Buf : TBytes ;
begin
  Buf := [$AA, $02, $FF, $00, $00, $A4, $0F] ;
  ComPort.Write(Buf[0], Length(Buf)) ;
end;


Сообщение было отредактировано: 5 ноя 20, 11:05
5 ноя 20, 11:04    [22226710]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
Hadroran,

Вы делаете строку с двумя пробелами и удивляетесь что у вас отправляется строка с двумя пробелами?..
function TForm1.HexToStr(HexStr : String; const Text : boolean = True): string;
...
      if Hex = $00 then begin
        if Text then
          Result := Result + ' '
5 ноя 20, 11:12    [22226719]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
defecator,

Ранее я использовал этот метод, но опять со строкой
ComPort.Write(Str[1], Length(Str));

Спасибо за помощь. Тема закрыта.
5 ноя 20, 11:18    [22226730]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
Hadroran
defecator,

Ранее я использовал этот метод, но опять со строкой
ComPort.Write(Str[1], Length(Str));


Спасибо за помощь. Тема закрыта.


зачем тебе строка, если можно двоичный буфер отправлять сразу
5 ноя 20, 11:22    [22226734]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
defecator,

Нет, простите, закрылись, а вопросы остались.
А получить данные теперь то как? Если со строкой все понятно было, то теперь, я так понял, надо изменить свойство
TriggersOnRxChar := false;

и соответственно читать событие
OnRxBuf(Sender: TObject; const Buffer; Count: Integer);

Но как? Есть метод
function Read(var Buffer; Count: Integer): Integer;
но не соображу, как его использовать, т.к. еще и справка запутала.
автор
Example (inside OnRxBuf)

procedure TForm1.ComPort1RxBuf(Sender: TObject; const Buffer; Count: Integer);
begin
// application does not have to read data from input buffer
// data is already in buffer parameter
HandleData(Buffer, Count); // handle data

end;


Помогите, пожалуйста.
5 ноя 20, 12:34    [22226795]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
Hadroran
defecator,

Нет, простите, закрылись, а вопросы остались.
А получить данные теперь то как? Если со строкой все понятно было, то теперь, я так понял, надо изменить свойство
TriggersOnRxChar := false;


и соответственно читать событие
OnRxBuf(Sender: TObject; const Buffer; Count: Integer);
Но как? Есть метод
function Read(var Buffer; Count: Integer): Integer;
но не соображу, как его использовать, т.к. еще и справка запутала.
автор
Example (inside OnRxBuf)

procedure TForm1.ComPort1RxBuf(Sender: TObject; const Buffer; Count: Integer);
begin
// application does not have to read data from input buffer
// data is already in buffer parameter
HandleData(Buffer, Count); // handle data

end;


Помогите, пожалуйста.


а ты вообще демки смотрел ?

procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
var
  Str: String;
begin
  ComPort.ReadStr(Str, Count);
  Memo.Text := Memo.Text + Str;
end;


для обработчика onRxBuf всё аналогично, только метод ComPort.Read:
function Read(var Buffer; Count: Integer): Integer;


соответственно, выделяешь буфер размером Count, и передаёшь его в ComPort.Read

Сообщение было отредактировано: 5 ноя 20, 14:43
5 ноя 20, 14:45    [22226917]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
defecator,

В демках при использовании события ComPortRxChar(Sender: TObject; Count: Integer); при внутренней расшифровке получается, что если в ответе найден байт = $00, все следующее игнорируется и получается, что ответ в строке получается неполный.
А вот с этим
defecator
соответственно, выделяешь буфер размером Count, и передаёшь его в ComPort.Read

что-то не получается ни с одним вариантом.
procedure TForm1.ComPortRxBuf(Sender: TObject; const Buffer; Count: Integer);
var
    ReadBuf: TBytes;
//    ReadBuf: array of byte;
//    ReadBuf: array [1..10] of byte;
begin
  ComPort.Read(ReadBuf, 10);
end;
5 ноя 20, 15:07    [22226932]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
В топике выше читать, что в принципе не имеет особого значения.
ComPort.Read(ReadBuf[0], Length(ReadBuf));


Сообщение было отредактировано: 5 ноя 20, 15:23
5 ноя 20, 15:28    [22226945]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
goldmi45
Member

Откуда:
Сообщений: 1261
Hadroran,

procedure TMainForm.VaComm1RxChar(Sender: TObject; Count: Integer);
var
  aBuffer: array [1..128] of byte;
  m: Byte;
  i: Integer;
  BufRead: String;
begin
  FillChar(aBuffer, SizeOf(aBuffer), 0);
  m := VaComm1.ReadBuf(aBuffer,Count);
  if (m > 0) then
  begin
    BufRead := '';
    for i:=1 to m do
      BufRead := BufRead + IntToHex(aBuffer[i], 2);

    mTxRx.Lines.Add('<- Rx: ' + BufRead); // mTxRx: TMemo
  end;
end;
5 ноя 20, 15:44    [22226960]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
Hadroran
Member

Откуда:
Сообщений: 92
goldmi45
Hadroran,

procedure TMainForm.VaComm1RxChar(Sender: TObject; Count: Integer);
var
  aBuffer: array [1..128] of byte;
  m: Byte;
  i: Integer;
  BufRead: String;
begin
  FillChar(aBuffer, SizeOf(aBuffer), 0);
  m := VaComm1.ReadBuf(aBuffer,Count);
  if (m > 0) then
  begin
    BufRead := '';
    for i:=1 to m do
      BufRead := BufRead + IntToHex(aBuffer[i], 2);

    mTxRx.Lines.Add('<- Rx: ' + BufRead); // mTxRx: TMemo
  end;
end;


Всем Спасибо, то что надо.
5 ноя 20, 16:22    [22226988]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
goldmi45
Hadroran,

procedure TMainForm.VaComm1RxChar(Sender: TObject; Count: Integer);
var
  aBuffer: array [1..128] of byte;
  m: Byte;
  i: Integer;
  BufRead: String;
begin
  FillChar(aBuffer, SizeOf(aBuffer), 0);
  m := VaComm1.ReadBuf(aBuffer,Count);
  if (m > 0) then
  begin
    BufRead := '';
    for i:=1 to m do
      BufRead := BufRead + IntToHex(aBuffer[i], 2);

    mTxRx.Lines.Add('<- Rx: ' + BufRead); // mTxRx: TMemo
  end;
end;


если будет больше 128-ми байт в буфере, получишь проблемы.
Буфер надо выделять размером с Count
procedure TMainForm.VaComm1RxChar(Sender: TObject; Count: Integer);
var
  aBuffer : TBytes ;
  m : byte ;
begin
  SetLength(aBuffer, Count) ;
  { буфер можно и не очищать, но раз уж так сильно хочется...}
  FillChar(aBuffer[0], Length(aBuffer) ;
  { m - число реально принятых байт в буфере }
  m := VaComm1.ReadBuf(aBuffer[0], Count) ;
  { опционально, можно и не переустанавливать размер 
    но тогда надо работать уже не с Count, а с M}
  if m < Count then SetLength(aBuffer, m) ;
  { далее что-то делаем с принятым буфером }
end ;


Сообщение было отредактировано: 5 ноя 20, 18:01
5 ноя 20, 18:04    [22227069]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1246
Странные какие-то примеры чтения из СОМ-порта. А что если порт начнёт выдавать по одному байту (буфер FIFO выключили)? А в норме порт даёт по 15 байт!
5 ноя 20, 19:19    [22227110]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
DmSer
Странные какие-то примеры чтения из СОМ-порта. А что если порт начнёт выдавать по одному байту (буфер FIFO выключили)? А в норме порт даёт по 15 байт!


порт может давать сколько угодно, но софтина работает с портом через его драйвер
а у драйвера могут быть свои виды на размер отдаваемых данных

поэтому функция VaComm1.ReadBuf возвращает число реально принятых байтов.

Сообщение было отредактировано: 5 ноя 20, 19:32
5 ноя 20, 19:32    [22227122]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 26836
DmSer
А в норме порт даёт по 15 байт!

Нет такого правила. Можно настроить таймаут после которого буфер "выплевывается".
И там вполне могут быть все 4096 байт.
5 ноя 20, 21:29    [22227183]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
defecator
Member

Откуда:
Сообщений: 39394
wadman
DmSer
А в норме порт даёт по 15 байт!

Нет такого правила. Можно настроить таймаут после которого буфер "выплевывается".
И там вполне могут быть все 4096 байт.


+100500
Картинка специально для DmSer

К сообщению приложен файл. Размер - 26Kb
6 ноя 20, 09:41    [22227356]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1246
Где гарантия, что обработчик VaComm1RxChar не вызовется в середине принимаемого пакета?
6 ноя 20, 11:10    [22227400]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с переводом 00 в символ для отправки в COM порт  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1246
Хотя если речь о пакете из 7 байт, то приведённых примеров достаточно. Сложно представить ситуацию, когда эти байты не считаются за один вызов обработчика.
Мои замечания относятся к случаю, когда принимается пакет из нескольких десятков / сотен байтов. В этом случае не обойтись без дополнительного буфера, в который придется складывать принятые куски.
6 ноя 20, 11:32    [22227410]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить