Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.05.2015, 13:58   #1
CHEburaschka
 
Регистрация: 02.04.2015
Сообщений: 9
Вопрос Чтение данных с COM-порта и вывод их в memo

Здравствуйте.

Аналогичные проблемы множество раз уже обсуждались и не только тут, поэтому прошу прощения если повторяюсь. Старался использовать решения в старых постах, но к сожалению полностью решить стоящую передо мной задачу пока так и не смог.

Имеется устройство работающее по COM-порту.
На данный момент удаётся подключаться к этому девайсу и включать/выключать передачу данных с него на компьютер.
Данные передаются в HEX формате и представляют из себя набор из 18 чисел, которые при каждой итерации обновляются. Необходимо считывать данные с этого устройства и заполнять ими memo.

Вот с этим возникли сложности. Проблемный участок кода находится в самом конце. Хотел считать данные в массив и из него уже постить их в мемо. Однако вылетает ошибка.

[DCC Error] Unit1.pas(136): E2033 Types of actual and formal var parameters must be identical
[DCC Error] Unit1.pas(137): E2250 There is no overloaded version of 'IntToStr' that can be called with these arguments

Вероятно потому, что ComPort.Read возвращает string.



Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, ExtCtrls, UnComPort;


type
  TForm1 = class(TForm)
    Panel1: TPanel;
    ComboBox1: TComboBox;
    Button1: TButton;
    Panel2: TPanel;
    Memo1: TMemo;
    Button2: TButton;
    Button3: TButton;
    CheckBox1: TCheckBox;
    Timer1: TTimer;
    Memo2: TMemo;
    Button4: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var

  Form1: TForm1;
  COM: integer;
  COMEd: boolean = False;
  ComPort:TComPort;
  str: string;


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);


begin

  if (ComboBox1.ItemIndex>=0) and (COMEd=False) then
  begin
    COM:=StrToInt(ComboBox1.Items.Strings[ComboBox1.ItemIndex]);
    Memo1.Lines.Add('Подключение к: COM'+IntToStr(COM));

    ComPort := TComPort.Create;
    ComPort.Number := COM; // какой COM порт открывать
    ComPort.Speed := cps9600; // ну и остальные параметры тоже настроить
    ComPort.ByteSize := 8;
    TComPort.Create.Open;
    //ComPort.StopBits(1);

    if not ComPort.Open() then
    begin
       Memo1.Lines.Add('Подключиться к: COM'+IntToStr(COM)+' не удалось');
    end else
    begin
      Memo1.Lines.Add('COM'+IntToStr(COM)+' успешно открыт');
      COMEd:=True;
    end;
  end else
    Memo1.Lines.Add('Выберите порт и убедитесь, что вы уже не подключены к нему');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if COMEd=true then
begin
  if ComboBox1.ItemIndex>=0 then Memo1.Lines.Add('COM'+IntToStr(COM)+' отключён');
      ComPort.Close;
      ComPort.Free;
      COMEd:=False;
end else
  Memo1.Lines.Add('Порт уже закрыт');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if COMEd=true then
  begin
    Memo1.Lines.Add('Получение данных из COM'+IntToStr(COM)+' начато');
    ComPort.Write(chr($B));
  end
else
  Memo1.Lines.Add('Подключитесь к порту');
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
if COMEd=true then
begin
      Memo1.Lines.Add('Получение данных из COM'+IntToStr(COM)+' завершено');
      ComPort.Write(chr($63));
end
else
  Memo1.Lines.Add('Подключитесь к порту');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ComPort.Close;
  ComPort.Free;
  COMEd:=False;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
  for I := 1 to 255 do
  ComboBox1.Items.Add(IntToStr(i));
end;


procedure TForm1.Timer1Timer(Sender: TObject);

var Resive :array [0..18] of byte;

begin
  if COMEd=true then
  begin
        ComPort.Read(Resive,18);
        Memo2.Lines.Add(IntToStr(Resive));
  end;

end.
Спасибо.
CHEburaschka вне форума Ответить с цитированием
Старый 18.05.2015, 14:09   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

var Resive :array [0..18] of byte;
...
IntToStr(Resive) -- ???
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 18.05.2015, 14:26   #3
CHEburaschka
 
Регистрация: 02.04.2015
Сообщений: 9
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
var Resive :array [0..18] of byte;
...
IntToStr(Resive) -- ???
Спасибо за скорый ответ! Пытался использовать следующий пример в своей программе, но поскольку давно не работал с дельфи, видимо написал что-то не то.

Код:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
P_in:array[1..15] of byte;
i:integer;
begin
ComPort1.Read(P_in,15);
For i:=1 to 15 do Memo1.Lines.Add(IntToStr(P_in[i]));
end;
CHEburaschka вне форума Ответить с цитированием
Старый 20.05.2015, 10:12   #4
CHEburaschka
 
Регистрация: 02.04.2015
Сообщений: 9
Сообщение

И так, удалось реализовать вывод данных в мемо (последняя процедура).

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Memo1: TMemo;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
    Form1: TForm1;
    f: THandle;
    ct: TCommTimeouts;
    dcb: TDCB;
    result1: boolean;
    result2: cardinal;
    result3: integer;
    result4: integer;
    i: cardinal;
    p: char;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject); //открыть порт

begin
  f := Windows.CreateFile(PChar('COM4'), GENERIC_READ or
                              GENERIC_WRITE,
                              FILE_SHARE_READ or FILE_SHARE_WRITE,
                              nil, OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL, 0);
  if (f < 0) or not Windows.SetupComm(f, 2048, 2048)or not
      Windows.GetCommState(f, dcb) then exit; //init error

  dcb.BaudRate := 9600;
  //dcb.StopBits := стоп-биты;
  //dcb.Parity := четность;
  dcb.ByteSize := 8;
  if not Windows.SetCommState(f, dcb)
  or not Windows.GetCommTimeouts(f, ct) then exit; //error
  ct.ReadTotalTimeoutConstant := 50;
  ct.ReadIntervalTimeout := 50;
  ct.ReadTotalTimeoutMultiplier := 1;
  ct.WriteTotalTimeoutMultiplier := 0;
  ct.WriteTotalTimeoutConstant := 10;
  if not Windows.SetCommTimeouts(f, ct)
  or not Windows.SetCommMask(f, EV_RING + EV_RXCHAR + EV_RXFLAG + EV_TXEMPTY)
then exit; //error
  result1 := true;
end;

procedure TForm1.Button2Click(Sender: TObject);   //закpыть поpт
begin
Windows.CloseHandle(f);
end;

procedure TForm1.Button3Click(Sender: TObject); //включение передачи данных с устройства
begin
  p := chr($B);
  WriteFile(f, p, 1, i, nil);
end;


procedure TForm1.Button4Click(Sender: TObject); //выключение передачи данных с устройства
begin
  p := chr($63);
  WriteFile(f, p, 1, i, nil);
end;

procedure TForm1.Timer1Timer(Sender: TObject); //вывод данных в memo1
var
  MyBuff: array[0..255] of Char; //буфер для чтения данных
  ByteReaded: cardinal; //количество считанных байт
  Str: string; //вспомогательная строка
  Status: DWord; //статус устройства
begin {QueryPort}
  //получим статус COM-порта устройства
  if not GetCommModemStatus(f, Status) then
  begin {ошибка при получении статуса устройства}
    //ошибка, все выключаем и выходим
    SysErrorMessage(GetLastError);
    Exit;
  end; {ошибка при получении статуса устройства}
  //читаем буфер из Com-порта
  FillChar(MyBuff, SizeOf(MyBuff), #0);
  if not ReadFile(f, MyBuff, SizeOf(MyBuff), ByteReaded, nil) then
  begin {ошибка при чтении данных}
    //ошибка, все закрываем и уходим
    SysErrorMessage(GetLastError);
    Exit;
  end; {ошибка при чтении данных}
  //данные пришли
  if ByteReaded > 0 then
  begin {Печать в memo1}
    //построчная печать в memo
    SetLength(Str, Length(MyBuff));
    Move(MyBuff[0], Str[1], Length(MyBuff)*SizeOf(Char));
    Memo1.Lines.Add(Str);
  end; {Печать в memo1}
end; {QueryPort}

end.
Есть несколько проблем, которые пока не удалось решить.

Информация в мемо представляется в виде следующих крякозябликов:
Ϳႀ퉿橿

ㅿ⑿຀텿婿
큿屿
晾ހ큿橿

Хочется, чтобы данные отображались корректно. Если верить монитору СОМ-порта, то после того, как устройство получает команду на передачу данных, на порт начинает поступать информация, имеющая вид 18 числовых значений в HEX виде, которые (кроме первых двух значений) изменяются с каждой итерацией.

Выглядит это всё примерно так:
00 00 FF FF 75 EF 7E 26 7E 4C 7F FA 75 1C 7F A7 7E 95 00 00 FF FF 78 03 7E E9 7E 8C 7F FB 76 D4 7F A9 7E 7D и т.д.

Соответственно в идеале, хотелось бы, чтобы данные в memo выводились по 18 HEX значений на строку:

00 00 FF FF 75 EF 7E 26 7E 4C 7F FA 75 1C 7F A7 7E 95
00 00 FF FF 78 03 7E E9 7E 8C 7F FB 76 D4 7F A9 7E 7D
И т.д.
CHEburaschka вне форума Ответить с цитированием
Старый 20.05.2015, 10:23   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
Соответственно в идеале, хотелось бы, чтобы данные в memo выводились по 18 HEX значений на строку:
Что мешает так сделать? Каждый принятый байт преобразовать с помощью IntToHex
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 20.05.2015, 10:48   #6
CHEburaschka
 
Регистрация: 02.04.2015
Сообщений: 9
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Что мешает так сделать? Каждый принятый байт преобразовать с помощью IntToHex
Благодарю за скорый ответ. Мешает в первую очередь плохое знание Дельфи Вы меня заранее извините, если далее будут глупые вопросы.
Мне не очень понятно как именно мне поможет IntToHex, если массив у меня Char. Или нужно переделать массив из char в byte?
Но опять же, будет ли работать с byte функция IntToHex?
И последний этап, мне нужно будет вывести данные в memo, где формат string.
CHEburaschka вне форума Ответить с цитированием
Старый 20.05.2015, 11:04   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Можно переделать, а можно и так IntToHex(Ord(MyBuff[i]),2)
Цитата:
будет ли работать с byte функция IntToHex
byte integer-совместимый тип данных
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 20.05.2015 в 11:13.
Аватар вне форума Ответить с цитированием
Старый 20.05.2015, 11:18   #8
northener
ПШП
Участник клуба
 
Регистрация: 15.07.2013
Сообщений: 1,867
По умолчанию

Цитата:
на порт начинает поступать информация, имеющая вид 18 числовых значений в HEX виде
На порт поступает 18 байт информации. И никаких HEX-видов нет пока ты не захочешь вывести их в визуальный компонент типа Мемо.
northener вне форума Ответить с цитированием
Старый 20.05.2015, 11:34   #9
CHEburaschka
 
Регистрация: 02.04.2015
Сообщений: 9
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Можно переделать, а можно и так IntToHex(Ord(MyBuff[i]),2)
byte integer-совместимый тип данных
ОГРОМНОЕ Вам спасибо! Вместо крякозябликов теперь отображается, что-то больше похожее на правду)) Правда данные как-то странно побиты и как будто много пропусков. У Вас нет мыслей почему могло получиться подобное? Может из-за того, что я использую таймер, а нужно считывать данные в постоянном режиме или по событию?


Так это выглядит сейчас:

FFFF
380
00
467F
387F
897E
E17F
01
01
FFFF
FD7F
00
3C7F
357F
657E
DF7F
01
01
FFFF
F57F
00
407F
2E7F
7C7E
E17F

А вот так должно выглядеть:

00 00 FF FF 75 EF 7E 26 7E 4C 7F FA 75 1C 7F A7 7E 95
00 00 FF FF 78 03 7E E9 7E 8C 7F FB 76 D4 7F A9 7E 7D

Код:
procedure TForm1.Timer1Timer(Sender: TObject); //вывод данных в memo1
var
  MyBuff: array[0..255] of Char; //буфер для чтения данных
  ByteReaded: cardinal; //количество считанных байт
  Str: string; //вспомогательная строка
  Status: DWord; //статус устройства
begin {QueryPort}
  //получим статус COM-порта устройства
  if not GetCommModemStatus(f, Status) then
  begin {ошибка при получении статуса устройства}
    //ошибка, все выключаем и выходим
    SysErrorMessage(GetLastError);
    Exit;
  end; {ошибка при получении статуса устройства}
  //читаем буфер из Com-порта
  FillChar(MyBuff, SizeOf(MyBuff), #0);
  if not ReadFile(f, MyBuff, SizeOf(MyBuff), ByteReaded, nil) then
  begin {ошибка при чтении данных}
    //ошибка, все закрываем и уходим
    SysErrorMessage(GetLastError);
    Exit;
  end; {ошибка при чтении данных}
  //данные пришли
  if ByteReaded > 0 then
  begin {Печать в memo1}
    //отправим строку на просмотр
    Str := IntToHex(Ord(MyBuff[i]),2);
    Memo1.Lines.Add(Str);
  end; {Печать в memo1}
end; {QueryPort}

end.
CHEburaschka вне форума Ответить с цитированием
Старый 20.05.2015, 11:47   #10
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Байты-то из буфера нужно в цикле выбирать, а не огульно с непонятным значением i. По поводу таймера не скажу, нет опыта работы с периферией через com
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Мгновенное чтение и вывод данных Parallelogram JavaScript, Ajax 2 08.04.2014 10:03
Дикий тупняк - чтение данных с com порта. GMX Компоненты Delphi 8 26.03.2014 15:39
Delphi.Чтение файла в Memo, вычисление, добавление строк в Memo antonio_sk Помощь студентам 0 26.04.2013 18:01
Вывод и чтение данных Joker_vad Общие вопросы Delphi 3 30.03.2013 16:03
Чтение данных с COM порта 232 Dimitr_88 Общие вопросы C/C++ 10 03.09.2010 10:39