Форум: "WinAPI";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
ВнизCOM порт Найти похожие ветки
← →
msd © (2005-05-25 11:28) [0]нужно сделать так, чтоб прога запускала процедуру, как только в COM-порт поступает число (от штрих-код сканера). что-то типа "OnCOMPortChange". прога под Win95. вариант просмотра порта каждые 55msec (вроде это мин. для win95) - как-то глупо, тем более нет гарантии, что один и тот же товар не будет сканиться несколько раз подряд.
и что надо учесть при программировании проги в d7 для win95?
Спасибо большое!
← →
Алхимик © (2005-05-25 13:05) [1]Посмотри, может пригодится:
http://kladovka.net.ru/index.php?action=view&filename=COMSniffer.zip&directory=Programs
← →
Алхимик © (2005-05-25 13:06) [2]Это простенькая программа для работы с СОМ портом + компонент.
← →
Marser © (2005-05-25 16:28) [3]SetCommMask
WaitCommEvent
← →
isasa © (2005-05-25 17:51) [4]иллюстративно (для описания работы)
пример рабочий и писал именно для сканера штрих-кодов
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;
← →
tesseract (2005-05-26 10:11) [5]Всё вроде верно но процедуру считывания надо писать в отдельном потоке и при выходе использовать CancelIO(cHandle) - а то твоя программа будет вечной.
← →
Чапаев © (2005-05-26 10:14) [6]CreateFile()+Overlapped files?
← →
isasa © (2005-05-26 11:20) [7]На форме стоят две кнопки "Старт" и "Стоп" для решения данной проблемы :)
Программуля висит резидентно и слушает порт.
← →
isasa © (2005-05-26 11:28) [8]в дополнение
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;
← →
msd © (2005-05-26 13:25) [9]но ведь резидентная прослушка - это не тру программирование (если вам скажут перезвонить позже, не будете ж вы каждые 55msec перезванивать). Если не ошибаюсь, на контроллере прерываний есть прерывание от СОМ порта. Винда ж перепрограммирует обработчики прерываний и от неё можно получить сигнал, что в СОМ порте что-то изменилось. И тогда лезть в порт. Конечно, если я не ошибаюсь насчёт контроллера прерываний.
Огромное спасибо.
← →
Fredericco © (2005-05-26 16:53) [10]1) TComPortDriver
2) Есть такое понятие как очередь и стартовые и стоповые биты в посылке. Даже если за 55 мсек товар просканируют 10 раз (при том что и два раза нереально), то все десять посылок придут тебе в программу.
3) Парсь пришедшую информацию в порт.
← →
msd © (2005-05-27 17:52) [11]Кстати, а win95 будет корректно с int64 работать?
← →
Reindeer Moss Eater © (2005-05-27 17:54) [12]очень смешно
← →
Marser © (2005-05-29 01:08) [13]
> msd © (27.05.05 17:52) [11] [Новое
>сообщение][Ответить]
> Кстати, а win95 будет корректно с int64 работать?
А почему нет?
← →
msd © (2005-05-29 12:37) [14]не знаю, почему нет, но слышал мнение, что не будет.
← →
Marser © (2005-05-29 13:06) [15]
> msd © (29.05.05 12:37) [14] [Новое
>сообщение][Ответить]
> не знаю, почему нет, но слышал мнение, что не будет.
Какое отношение разрядность имеет к ОС?
← →
msd © (2005-05-30 11:12) [16]2 Marser
мне тоже интересно, какое, но ведь всё может быть. мне такое сказал один программист, не просто ж он языком трепал. но для корректного вывода надо обоснованное мнение многих
← →
Reindeer Moss Eater © (2005-05-30 11:22) [17]Он высосал это из пальца
← →
msd © (2005-07-03 15:15) [18]с CreateFile тоже всё круто, все компоненты типа async32, TComPortDriver так работают, тока на моём компе (winXP, на других не пробовал) handle всегда invalid. В TComPortDriver такая ситуация даже не обрабатывается! Т.е. хэндл инвалид, а прога типа подключилась и типа работает. Ну и что делать? поможите,а?
← →
Digitman © (2005-07-04 09:08) [19]
> на моём компе .. handle всегда invalid
> что делать?
читать справку, где черным по белому написано :
If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
← →
msd © (2005-07-04 14:28) [20]справку я читать умею.
и мне пофиг, почему хэндл инвалид.
Мне нужен валид, ВСЕГДА.
← →
Digitman © (2005-07-04 14:33) [21]
> msd © (04.07.05 14:28) [20]
> справку я читать умею.
сомневаюсь.
> мне пофиг
чего ж тебе тогда набобно, старче, если тебе "пофиг" ?
> Мне нужен валид, ВСЕГДА
нужен ? получи !
не получил ? УЗНАЙ, олух, ПОЧЕМУ ты его не получил ! На то и GEtLastError существует ! И не для Пушкина он существует, а для тебя, олуха !
← →
msd © (2005-07-06 23:12) [22]спасибо большое, тов. Дигитмэн.
← →
msd © (2005-07-06 23:16) [23]А почему в компоненте TComPortDriver не предусмотрен invalid_handle_value? И он даже не обрабатывает такой ситуации?
А по сабжу: пишет, что-то вроде "cannot open..." не помню точно.
Завтра точно посмотрю.
← →
Германн © (2005-07-07 01:05) [24]С одной стороны - вопрос задан в форуме WinAPI.
С другой стороны автор сабжа пытается пользоваться компонентом TComPortDriver?
Не очень понятно, что автор хочет?
Может ли он использовать сторонние компоненты?
Может ли он использовать "условно-бесплатные" компоненты?
И еще к msd © (06.07.05 23:16) [23]
>А почему в компоненте TComPortDriver
А почему ты спрашиваешь об этом компоненте тут? Вопросы о нестандартных компонентах нужно адресовать автору.
← →
msd © (2005-07-07 20:13) [25]я не спрашиваю про компоненту. я спрашиваю, почему её автор не "додумался" проверить. дело не в компонентах. все они используют апишную функцию CreateFile. И вот она всегда возвращает инвалидный хэндл. Код ошибки - 5 "The Request is known but currently can"t be implemented" - что-то типа того написано в MSDN.
А компоненты я смотрел для того, чтобы посмотреть, как это у других реализовано. И я ничего не спрашиваю о них у вас, не наезжаю на их авторов. Просто привожу информацию, т.к. мне кажется, что это часть моего вопроса.
Извините, если я опять написал чего не по сабжу.
Но, по-моему, тов Digitman и Германн со своими нравоучениями и нападками немного не в тему в форуме WinAPI.
← →
simpson © (2005-07-07 23:37) [26]> msd © (26.05.05 13:25) [9]
> резидентная прослушка - это не тру программирование
Рыдал весь. :) Афтар жжот. :) Перевод этой фразы в студию!
> isasa © (25.05.05 17:51) [4]
Если уж созрел для того, чтобы помочь советом товарищу, то советуй хотя бы правильно. Проверять по таймеру наличие данных во входном буфере порта при живой функции WaitCommEvent по меньшей мере странно.
По сабжу. Если GetLastError, после того, как ты вызвал CreateFile, вернувщую INVALID_HANDLE_VALUE, вернула значение 5, то общественность требует привести ссылку из MSDN, где ты нашел это:
> The Request is known but currently can"t be implemented
В разделе "Platform SDK: Debugging and Error Handling" написано, что код ошибки 5 - это "Access is denied.". Доступ запрещен.
Ну, и безусловно, хотелось бы код в студию.
← →
jack128 © (2005-07-07 23:57) [27]msd © (07.07.05 20:13) [25]
я не спрашиваю про компоненту. я спрашиваю, почему её автор не "додумался" проверить
На автора не надо гнать, автор все проверяет.function TCommPortDriver.Connect: boolean;
begin
...
FHandle := CreateFile( pchar(FPortName),
GENERIC_READ or GENERIC_WRITE,
0, // Not shared
nil, // No security attributes
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0 // No template
) ;
Result := Connected; (Connected := FHandle <> INVALID_HANDLE_VALUE)
if not Result then
exit
Это ТЫ не удосуживаешься узнать, почему порт не открывается.
msd © (07.07.05 20:13) [25]
Код ошибки - 5 "The Request is known but currently can"t be implemented" - что-то типа того написано в MSDN.
"Ты гонишь, Спидди" (по мотивам старого мультика)
windows.pas
{ Access is denied. }
ERROR_ACCESS_DENIED = 5;
Просто кто то уже открыл порт, вот ты и не можешь получить доступ к нему..
← →
Digitman © (2005-07-08 09:16) [28]
> msd
if not CommPortDriver.Connect then
SysErrorMessage(GetLastError);
ЭТО ты мог бы и сам сообразить, заглянув в исх.текст метода Connect() и в справку !
← →
msd © (2005-07-08 12:54) [29]афтар сторонник русского языка.
simpson, лучше не рыдать, а подумать, что если есть прерывание от ком-порта, то резидентная прослушка - не лучший способ, и можно использовать это прерывание.
jack128, а кто мог открыть порт? в реестре, в device map, на com1 и com2 ничего не висит. может, другая причина? а если его кто открыл, то могу я узнать, можно ли его тоже пользовать? ну и, есстественно, попользовать порт?
автор не выводит никакого сообщения, и если хэндл окажется инвалид, то дальше всё "типа" работает, т.е. читаются и пишутся пустые строки, не зависимо от того, что на самом деле. Вот фрагмент TComportDriver"а
function TComportDriverThread.Connect: Boolean;
var
comName: array[0..4] of Char;
tms: TCommTimeouts;
begin
if Connected then
Exit;
StrPCopy(comName,"COM");
comName[3] := chr(ord("1") + ord(FComportNumber));
comName[4] := #0;
FComportHandle := CreateFile(comName,GENERIC_READ OR GENERIC_WRITE,0,nil,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if not Connected then
Exit;
ApplyComPortSettings;
tms.ReadIntervalTimeout := 1;
tms.ReadTotalTimeoutMultiplier := 0;
tms.ReadTotalTimeoutConstant := 1;
tms.WriteTotalTimeoutMultiplier := 0;
tms.WriteTotalTimeoutConstant := 0;
SetCommTimeouts(FComportHandle,tms);
Sleep(1000);
end;
← →
Digitman © (2005-07-08 13:18) [30]
> если есть прерывание от ком-порта
... то нефига туда лезть своими шаловливыми ручонками - ОС прекрасно и без тебя справится с обработкой прерываний... твоя же5 задача - ГРАМОТНО и ЭФФЕКТИВНО использовать WinAPI в части асинхронного ввода/вывода
> резидентная прослушка
где ты такой дурнопахнущей терминологии нахватался - "резидентная прослушка" ?
нет никаких "резидентных прослушек" !
есть Win32-процессы, любой из которых является резидентным, и есть асинхронный и синхронный ввод/вывод
а циклическое чтение данных из порта ввода - это и есть циклическое чтение данных из порта ввода, а не какая-то там "прослушка", тем более еще и какая-то там "резидентная")
> дальше всё "типа"
вот именно - "типа" !
← →
Digitman © (2005-07-08 13:25) [31]
> автор не выводит никакого сообщения
с какого перепугу автор обязан что-то "выводить" тебе ?
автор вернул тебе булев результат коннекта, и тебе следует анализировать этот результат, прежде чем ничтоже сумняшеся пытаться что-то читать/писать из/в порт !
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.038 c