Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.042 c
14-1123239992
12DFBDDh
2005-08-05 15:06
2005.08.28
С днем железнодорожника!


14-1123147824
3DxFantastika
2005-08-04 13:30
2005.08.28
Как перевести дату в UNIX-время (формат)


4-1121238081
webpauk
2005-07-13 11:01
2005.08.28
Запуск .lnk


1-1122699937
Navi
2005-07-30 09:05
2005.08.28
AutoCAD + Delphi - аргументы для SetXRecordData?


1-1123164593
Русланка
2005-08-04 18:09
2005.08.28
А как в DBComboBox программно установить какую либо строку





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский