Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

COM порт [D7, Win95/98]


Страницы:   1 2

msd ©   (2005-05-25 11:28:00) 

нужно сделать так, чтоб прога запускала процедуру, как только в COM-порт поступает число (от штрих-код сканера). что-то типа "OnCOMPortChange". прога под Win95. вариант просмотра порта каждые 55msec (вроде это мин. для win95) - как-то глупо, тем более нет гарантии, что один и тот же товар не будет сканиться несколько раз подряд.
и что надо учесть при программировании проги в d7 для win95?
Спасибо большое!


msd   (2005-05-27 17:52:00) [21]

Кстати, а win95 будет корректно с int64 работать?


Fredericco   (2005-05-26 16:53:00) [22]

1) TComPortDriver

2) Есть такое понятие как очередь и стартовые и стоповые биты в посылке. Даже если за 55 мсек товар просканируют 10 раз (при том что и два раза нереально), то все десять посылок придут тебе в программу.

3) Парсь пришедшую информацию в порт.


msd   (2005-05-26 13:25:00) [23]

но ведь резидентная прослушка - это не тру программирование (если вам скажут перезвонить позже, не будете ж вы каждые 55msec перезванивать). Если не ошибаюсь, на контроллере прерываний есть прерывание от СОМ порта. Винда ж перепрограммирует обработчики прерываний и от неё можно получить сигнал, что в СОМ порте что-то изменилось. И тогда  лезть в порт. Конечно, если я не ошибаюсь насчёт контроллера прерываний.
Огромное спасибо.


isasa   (2005-05-26 11:28:00) [24]

в дополнение

destructor TMainForm.Destroy;
begin
 inherited;

 DropDevice;
end;

function TMainForm.DropDevice: boolean;
begin
 Dispose(CommTimeouts);
 Dispose(IOOverLapped);
 Dispose(EvOverLapped);
 Dispose(DCB);
 Result:=true;
end;

procedure TMainForm.StopButtonClick(Sender: TObject);
begin
 CheckTimer.Enabled:=false;
 StartButton.Enabled:=true;
 StopButton.Enabled:=false;
 RxTrayIcon.Animated:=false;

 CloseHandle(EvOverLapped^.hEvent);
 CloseHandle(IOOverLapped^.hEvent);
 Memo1.Lines.Add(FormatDateTime('"Стоп " dddd d mmmm yyyy, " в " hh:nn:ss ', Now()));
end;


isasa   (2005-05-26 11:20:00) [25]

На форме стоят две кнопки "Старт" и "Стоп" для решения данной проблемы :)
Программуля висит резидентно и слушает порт.


Чапаев   (2005-05-26 10:14:00) [26]

CreateFile()+Overlapped files?


tesseract   (2005-05-26 10:11:00) [27]

Всё вроде верно но процедуру считывания надо писать в отдельном потоке и при выходе использовать CancelIO(cHandle)  - а то твоя программа будет вечной.


isasa   (2005-05-25 17:51:00) [28]

иллюстративно (для описания работы)
пример рабочий и писал именно для сканера штрих-кодов

type
 pThreadData = ^TThreadData;
 TThreadData = record
   BufLen : Longword;
 end;

 TMainForm = class(TForm)
   Panel1: TPanel;
   ExitButt: TButton;
   StartButton: TButton;
   Memo1: TMemo;
   GlobalAction: TActionList;
   wRestore: TAction;
   wHide: TAction;
   wExit: TAction;
   RxTrayIcon: TRxTrayIcon;
   StopButton: TButton;
   CheckTimer: TTimer;
   PopupMenu: TPopupMenu;
   mRestore: TMenuItem;
   mHide: TMenuItem;
   N1: TMenuItem;
   mExit: TMenuItem;
   LEDDisplay: TRzLEDDisplay;
   RzLabel1: TRzLabel;
   RxLight: TLMDLight;
   ParamButton: TButton;
   mParam: TMenuItem;
   N2: TMenuItem;
   Button2: TButton;
   procedure ExitButton(Sender: TObject);
   procedure mRestoreClick(Sender: TObject);
   procedure AppMinimize(Sender: TObject);
   procedure StartButtonClick(Sender: TObject);
   procedure CheckDevice(Sender: TObject);
   procedure StopButtonClick(Sender: TObject);
   procedure ParamButtonClick(Sender: TObject);
   procedure StatDevice(Sender: TObject);
 private
   CommTimeouts : PCommTimeouts;
   EvOverLapped, IOOverLapped : POverlapped;
   EventMsk, ioError, cBytesRead, cBytesToRead : DWORD; // Longword
   cBuff : array[1..MaxWLenBuff] of Char;
   TotalBytes : DWORD;
   function OpenPort(var cHandle : THandle; PortName : PAnsiChar) : DWord;
   function ReadDevice(cHandle : THandle; var Buff : PChar; var cBytesRead : Longword) : Longword;
   function DropDevice : boolean;
   procedure ViewPortStat(DCB: TDCB);
 public
   { Public declarations }
   AutoRun, CheckInterval : DWORD;
   cHandle: THandle;
   DCB : PDCB;
   Port : integer;
   constructor Create(Owner: TComponent); override;
   destructor Destroy; override;
 end;

var
 MainForm: TMainForm;

................................

constructor TMainForm.Create(Owner: TComponent);
var PortName : string;
begin
 inherited;

 New(IOOverLapped);
 New(EvOverLapped);
 New(CommTimeouts);
 New(DCB);
 ParamForm:=TParamForm.Create(Self);
 AutoRun:=ParamForm.GetIParam(RegKey, 'AutoRun');
 CheckInterval:=ParamForm.GetIParam(RegKey, 'CheckInterval');
 StartButton.Enabled:=true;
 StopButton.Enabled:=false;
 TotalBytes:=0;
 Port:=ParamForm.GetIParam(RegKey,'Port');
 PortName:=ParamForm.PortNameBox.Items[Port];
 if OpenPort(cHandle, PChar(PortName))<>0 then exit;
 GetCommState(cHandle, DCB^);
 DCB^.BaudRate:=CBR_9600;
 DCB^.Flags:=$00;
 DCB^.ByteSize:=8;
 DCB^.Parity:=0;
 DCB^.StopBits:=0;
 SetCommState(cHandle, DCB^);

 CommTimeouts^.ReadIntervalTimeout:=ParamForm.GetIParam(RegKey, 'ReadIntervalTimeout');
 CommTimeouts^.ReadTotalTimeoutMultiplier:=0;
 CommTimeouts^.ReadTotalTimeoutConstant:=0;
 CommTimeouts^.WriteTotalTimeoutMultiplier:=0;
 CommTimeouts^.WriteTotalTimeoutConstant:=0;
 SetCommTimeouts(cHandle, CommTimeouts^);
end;

.....................................

procedure TMainForm.StartButtonClick(Sender: TObject);
begin
 IOOverLapped^.Offset:=0;
 IOOverLapped^.OffsetHigh:=0;
 IOOverLapped^.hEvent:=CreateEvent(nil, False, False, nil); //  THandle
 EvOverLapped^.hEvent:=CreateEvent(nil, False, False, nil); //  THandle
 SetCommMask(cHandle, EV_RXCHAR+EV_RXFLAG+EV_RLSD);

 CheckTimer.Interval:=CheckInterval;
 CheckTimer.OnTimer:=CheckDevice;
 CheckTimer.Enabled:=true;
end;

.................................................

function TMainForm.OpenPort(var cHandle : THandle; PortName : PAnsiChar) : DWORD;
var ErrCod : DWord;
begin
 cHandle := CreateFile(PortName,
              GENERIC_READ+GENERIC_WRITE,
              FILE_SHARE_READ+FILE_SHARE_WRITE,
              nil,
              OPEN_EXISTING,
              FILE_ATTRIBUTE_NORMAL+FILE_FLAG_OVERLAPPED,
              0);
 if not GetCommModemStatus(cHandle, ErrCod) then begin
   Result:=ErrCod;
   Memo1.Lines.Add('Ошибка открытия порта - '+IntToStr(ErrCod));
   exit;
 end;
 if cHandle<>INVALID_HANDLE_VALUE then Result:=0
 else begin
   Memo1.Lines.Add('Ошибка открытия порта - '+IntToStr(ErrCod));
   Result:=GetLastError;
 end;
end;

procedure TMainForm.CheckDevice(Sender: TObject);
var
 bResult : boolean;
 mBuff : PChar;
 s : string;
begin
 CheckTimer.Enabled:=false;
 mBuff:=@cBuff;
 WaitCommEvent(cHandle, EventMsk, EvOverLapped);
 ioError:=GetLastError;
 RxLight.Active:=(ioError=ERROR_IO_PENDING);
 if ioError=ERROR_IO_PENDING then begin
   repeat                                      // ----
     bResult:=GetOverlappedResult(cHandle, EvOverLapped^, cBytesRead, false);
     ioError:=GetLastError;
     RxLight.Active:=(ioError=ERROR_IO_PENDING);
     case EventMsk of
       EV_RXCHAR : begin
                   if ioError=ERROR_IO_INCOMPLETE then begin
                     ioError:=ReadDevice(cHandle, mBuff, cBytesRead);
                     if ioError=0 then begin
                       SetString(s, mBuff, cBytesRead);
                       MainForm.Memo1.SetFocus;
                       MainForm.Memo1.Lines.Add(s);
                       //MainForm.Memo1.Text:=MainForm.Memo1.Text+s;
                       //MainForm.Memo1.Lines.Add(StrToHex(s)+' - '+StrToBin(s));
                       MainForm.Memo1.Update;
                     end;
                     Inc(TotalBytes,cBytesRead);
                     LEDDisplay.Caption:=IntToStr(TotalBytes);
                   end;
                 end;

     end;
   until bResult or (ioError<>ERROR_IO_PENDING); // ----
 end;
 CheckTimer.Enabled:=true;
end;


Marser   (2005-05-25 16:28:00) [29]

SetCommMask
WaitCommEvent


Алхимик   (2005-05-25 13:06:00) [30]

Это простенькая программа для работы с СОМ портом + компонент.


Алхимик   (2005-05-25 13:05:00) [31]

Посмотри, может пригодится:
http://kladovka.net.ru/index.php?action=view&filename=COMSniffer.zip&directory=Programs


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо