![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
COM порт [D7, Win95/98]
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