29 мая 2011 в 13:57

Визуальный компонент-монитор COM-порта

Сегодня мы попробуем создать визуальный компонент для работы с разного рода считывателями, подключаемыми по COM-порту (правильное название интерфейса – RS232). Наша цель — получать последовательность байт, которую отправляет устройство при считывании.

Начнем с создания нового проекта типа Delphi Component:
image
В следующем окне выберем TEdit в качестве родительского компонента.
image
Напоследок, дадим звучное имя нашему будущему компоненту – TRS232Edit и поместим его в набор MyComponents палитры компонентов (RS 232 — наименование стандарта).
image
После нажатия Finish назовем модуль компонента uRS232Edit.pas и сохраним его. Среда разработки автоматически сформирует такой шаблон:

unit uRS232EANEdit;
interface
uses
SysUtils, Classes, Controls, StdCtrls;

type
TRS232Edit = class(TEdit)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('MyComponents', [TRS232Edit]);
end;

end.


Объявим структуру для хранения 20-ти байтов с порта (больше и не надо :))

type
TBuffer = array[0..20] of byte;


Начинаем закладывать функционал. Для начала объявим в секции private класса TRS232Edit переменные, в которых будем хранить параметры соединения с портом.

cComPort : integer;   // номер порта
cBaud : integer;  // скорость передачи (бод)
cParity : integer; // режим проверки четности
cCountBit : integer;  //число бит данных
cStopBit : integer;  //число стоповых бит


Ещё нам понадобятся

CommHandle : integer;  //хэндл COM-порта
DCB : TDCB;  //структура для хранения параметров соединения с портом
Ovr : TOverlapped; //структура для корректности асинхронных процессов
Stat : TComStat;  //  структура для хранения состояния порта
CommThread : THandle;  //хэндл потока, обрабатывающего события порта
function DigitHex(aValue: Integer): Char;
function GetAsHexagonal(aValue: Integer): String;  //преобразование в 16-ричный код
function DecodeBarCode(buf : TBuffer; bufsize : integer) : string;
procedure PortInit;
procedure SetZero;


и в секции public

BarCode : string; //будет выводиться в свойство Text
constructor Create(AOwner:Tcomponent);override;
destructor Free;
procedure Init(comport, baud, parity, countbit, stopbit : integer);


Инициализировать соединение с портом будем вызовом метода Init. В нем присываиваются парамерты внутренним переменным, выставляются начальные значения и вызывается метод непосредственно коннекта.

procedure TRS232EANEdit.Init(comport, baud, parity, countbit, stopbit : integer);
begin
cComPort := comport;
cBaud := baud;
cParity := parity;
cCountBit := countbit;
cStopBit := stopbit;
SetZero;
PortInit;
end;


Наибольший интерес здесь представляет метод PortInit — разберем его детально

procedure TRS232EANEdit.PortInit;
var
ThreadID: dword ;
begin
//открытие порта и получение его хэндла
CommHandle:= CreateFile(cComPort,GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);
//ставим маску - "по пришествии определенного символа"
SetCommMask(CommHandle,EV_RXFLAG);
//получаем текущие настройки соединения в DCB
GetCommState(CommHandle, DCB);
//выставляем наши значения
DCB.BaudRate:=cBaud;
DCB.Parity:=cParity;
DCB.ByteSize:=cCountBit;
DCB.StopBits:=cStopBit;
DCB.EvtChar:=chr(13); // будем ждать прихода байта 0x0D

//применение новых значений
SetCommState(CommHandle,DCB);
/* создаем параллельный поток, где вертеться процедура приема строки. Третий параметр - указатель на класс нашего компонента. BeginThread - обертка вокруг CreateThread. @ReadComm - указатель на функцию приема строки */

CommThread := BeginThread(nil,0,@ReadComm,Self,0,ThreadID);
end;


Прием данных происходит в процедуре ReadComm

procedure ReadComm(s : Pointer);
var
Resive : TBuffer;
a : TRS232EANEdit;
begin
a := s; // s - указатель на объект нашего компонента
while true do
begin
a.TransMask:=0;
WaitCommEvent(a.CommHandle,a.TransMask,@a.Ovr);
if (a.TransMask and EV_RXFLAG)=EV_RXFLAG then //проверяем нужное событие
begin
ClearCommError(a.CommHandle,a.Errs,@a.Stat);
ReadFile(a.CommHandle, Resive, a.Stat.cbInQue, a.Stat.cbInQue, @a.Ovr);//читаем
a.Text := a.DecodeBarCode(Resive, 20);  //в поле появляется штрих-код
Application.ProcessMessages;
end;
end;
end;


Всё. Компилим, устанавливаем. Чтобы считываение запустилось, в тестовом приложении достаточно приписать что-то вроде

RS232Edit1.Init(1, 9600, 0, 8, 1)
Алексей Панин @aspanin
карма
18,0
рейтинг 0,0
Пользователь
Похожие публикации
Самое читаемое Разработка

Комментарии (30)

  • –4
    Вау. А я и не знал, что на Делфи всё ещё кто-то пишет вне ВУЗов с устаревшей на 15 лет программой обучения.
    • +1
      >анимэ на аватарке
      >http://hivemind.me
      Да шо ты говоришь то!
    • +1
      • –4
        Самое забавное, что таблица только подтверждает мною сказанное. Язык ушёл из топа, доля продолжает падать, используется в основном там, где есть тонны legacy-кода, перспективы развития не прослеживаются вообще.
        • +3
          Самое главное, таблица только противоречит Вами сказанному: на Делфи все-таки пишут. Не нравится язык — не пишите.
      • 0
        Ассемблер и Ада имеют кучу зелёных стрелочек.
        Не думаю что этот топ так уж объективен :)
        • 0
          Дайте какой-нибудь другой топ
    • +2
      AIMP, QIP, R&Q, The Bat!, Download Master, Inno Setup написаны на Delphi. Они устарели на 15 лет?
      • +1
        Total Commander самое главное.
        • +2
          ertaquo и Oxide расширили мой кругозор =) Спасибки.
          Насчет 15ти лет — не устарели!!!

          ps Пользуюсь, 4 из 7 представленных программ =)
      • –2
        Не использовал ни одной из них уже много лет. Наверное, потому что эти годы живу без windows.
        • +1
          Игрушка Hedgewars, архиватор Peazip и клон Total Commander — Double Commander написаны на Free Pascal. Более-менее знаменитых программ под линукс назвать не могу, потому что под ним паскаль и его диалекты не особо распространены. Под маками они еще меньше используются, так что для них назвать не могу ни одной.
          Что Delphi, что паскаль вполне живы и до сих пор много где используются. Например, если мне надо что-то на скорую руку и с графическим интерфейсом слепить, я скорее всего возьму Delphi. Как вариант — C#, но его я довольно плохо знаю и он требует .NET. В Delphi довольно легко использовать сторонние компоненты, а написано их немало — на www.torry.net/ больше 10 тысяч всяких полезностей.
      • +1
        Ещё виндовый клиент Skype, KMPlayer, FinalBuilder, PyScripter, BS Player
        • 0
          KMP, имхо, наиболее функциональный плеер
      • 0
        мне очень нравится r&q, но он практически не развивается, и по сравнению с конкурентами выглядит устаревшим :(
    • +2
      На Делфях пишут, пишут и пишут хорошо =)
      • –2
        Я не говорю, что на них нельзя хорошо писать. Писать хорошо можно хоть на брейнфаке. У языка объективно есть тонны проблем, главная из которых — ограниченность одной платформой. Даже софт писаный на Визуальном Основном с успехом компилится и работает на Mac и Linux. Не говоря уже о разных мобилках.
        • 0
          Скоро и на дельфи можно будет компилить программы для Mac и Linux.
          Только, боюсь, как и любое кроссплатформенное, будет выглядеть ненативно, т.е. на мой взгляд, средненький плюс в наличии кроссплатформенности.
          • 0
            Да есть тот же Delphi.NET. Потом эти сборки заставить прожевать Mono — то ещё веселье. А ещё у меня есть сомнения, что борланд (или кто там сейчас владеет) осилит создание нормального компилятора под ARM.
            • +1
              Delphi.NET давно мёртв, ему на смену пришёл Delphi Prism.
              Embarcadero сейчас акцентируются на создании 64-битного компилятора (выйдет в сентябре) и Linux/Mac (может тогда же будет доступен, но сомневаюсь).
              ARM? Думаю ждать пока не стоит, хотя и не уверен что очень надо.
              Опять же, если разбрасываться во все стороны, то ничего не успеешь, не майкрософт, не хватит ресурсов. Хотя последняя дельфи у меня работает на порядок стабильнее студии 2010.
          • 0
            Я связан договором о неразглашении, но выглядеть будет нативно и пиздато. Я уже видел. :)
            • 0
              Супер!
              Я правильно понял, что в новой версии будут полные и стабильные реализации c поддержкой IDE и прочего и 64 битов и Linux/Mac?
              И ещё маленький вопрос: FireMonkey будет заменой VCL или они будут парарельно в дельфи или ещё как? Не получится ли, что понадобится переписывать программы.
              • 0
                Да, 32 и 64 бита, Винда и Мак… Линупса нету в списке. Обезьянка будет не заменой. Обезьянка — это библиотека для построения кроссплатформенных ГУЕв. То есть, если интересует только Винда, оставляем VCL. Если нацелились на все подряд, переделываем через FireMonkey.
        • 0
          Free Pascal и IDE Lazarus. Они вполне кроссплатформенны. FPC поддерживает диалект Delphi. Минус FPC — недостаточная оптимизация, что ведет к увеличению размера программы. Но если писать не демки в 10 килобайт, а какую-нибудь более-менее серьезную программу, не сильно зависящую от ОС (то бишь не использующую специфические функции ОС), то все будет пучком.
          • +2
            Ну вы сравнили делфи с его VCL и фрипаскаль. Код на паскале можно и GCC компилить при желании, VCL от этого там не появится.
            • 0
              В Lazarus есть набор классов, сходный с VCL. Недостающие можно довольно легко портировать или переписать.
              • +1
                К сожалению, Lazarus очень сильно проигрывает любой версии Delphi в плане RTL/VCL: количество ошибок, стабильность в целом, функциональные возможности. Для крупных проектов он просто неюзабелен.
              • 0
                Лазарус до чих пор напоминает какое-то школьное поделие. Напихали рюшек и финтифлюшек, а баги поправить — руки не дошли.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Да, 21))) Спасибо

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.