Страница 1 из 1
Как прочесть состояние COM-порта
Добавлено: 08 Август 2007, 10:17
Dias2004
Задача: по внешнему физическому событию (нажатие тревожной кнопки) программа на Clarion должна выполнить некие действия. Напрограммировать действие удалось без проблем.
Как заметить событие?
Поскольку внешний мир для ПК - это скорее всего состояние портов,
как наиболее просто обратиться к COM-порту?
Я так понимаю, что для этих целей существуют Windows API, но до сих пор ни разу не приходилось пользоваться...
Если есть опыт или хотя бы мнение по поводу способов решения задачи, подскажите пожалуйста.
Добавлено: 08 Август 2007, 23:44
Andrew Listiev
Приветствую!
Как ты уже отметил, лучше использовать Win API. В своё время написал хороший набор классов для работы с последовательным портом. По личному опыту могу сказать, что лучше не придумать, полная свобода. Есть сторонние библиотеки, такие как ClaCom (вроде так, насколько помню

, только платные) пользовал также. Довольно приличные. Есть MSCom.ocx (опять-таки могу ошибиться в названии). Так что есть поле для исследований

Добавлено: 20 Август 2007, 15:51
Dias2004
Написал код на Дельфи. Всего две функции:
1. открыть порт (CreateFile).
2. прочесть его состояние.
Выглядит это так:
Код: Выделить всё
<декларация переменных>
hport: THandle;
vStatus: dword;
<однократно исполняемый код>
hport := CreateFile('COM1',
GENERIC_READ,
0,
nil,
OPEN_EXISTING,
0,
0);
Win32Check(hport <> INVALID_HANDLE_VALUE);
<код, исполняемый по таймеру>
Win32Check(GetCommModemStatus(hport,vStatus));
Работает. Значение vStatus прекрасно отражает текущее состояние входов порта.
Хочу написать это на Clarion, но не знаю и не нашел пока как описать тип данных указатель (handle) на файл.
Пробовал объявить прототип функции CreateFile, как указано в справочнике по WinAPI, имеющемуся в примерах, вот так:
Код: Выделить всё
CreateFileA(*LPCSTR,DWORD,DWORD,*SECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE),HANDLE,PASCAL,RAW
но компилятор сразу ругается на возвращаемый тип HANDLE - illegal return type. Подскажите, кто знает, как составить правильное описание?
Добавлено: 21 Август 2007, 16:18
StillZero
*LPCSTR - по нашему *CSTRING
DWORD - LONG
*SECURITY_ATTRIBUTES - можно создать группу, тогда это будет указатель на нее, тебе можно заменить на LONG и передавать 0
HANDLE - LONG
получается так вроде:
CreateFileA(*CSTRING,LONG,LONG,LONG,LONG,LONG,LONG),LONG,PASCAL,RAW
Добавлено: 22 Август 2007, 12:02
Dias2004
Спасибо, я продвинулся!
Все собралось, и порт открылся. Но при попытке получить статус - ошибка. В чем может быть проблема?
Выглядит так:
Код: Выделить всё
<Equates>
GENERIC_READ EQUATE(80000000h)
OPEN_EXISTING EQUATE(3)
INVALID_HANDLE_VALUE EQUATE(-1)
BOOL EQUATE(SIGNED)
DWORD EQUATE(ULONG)
HANDLE EQUATE(UNSIGNED)
LPCSTR EQUATE(CSTRING)
<прототипы>
CreateFile(*LPCSTR,DWORD,DWORD,DWORD,DWORD,DWORD,HANDLE),HANDLE,PASCAL,RAW,NAME('CreateFileA')
GetCommModemStatus(HANDLE,DWORD),BOOL,PASCAL,RAW,NAME('GetCommModemStatus')
PortCOM1 cstring('COM1')
hPort long
vStatus long
<однократно открыли порт>
hPort = CreateFile(PortCOM1,GENERIC_READ,0,0,OPEN_EXISTING,0,0)
IF hPort = INVALID_HANDLE_VALUE
message('Порт COM1 открыть не удалось.')
.
<по таймеру запрашиваем статус>
IF GetCommModemStatus(hPort,vStatus).
Вызов GetCommModemStatus возвращает 0 (ошибка) и значение vStatus всегда остается нулем независимо от состояния порта. При этом код на Дельфи (см. первое сообщение) работает, и состояние порта отслеживается.
Знатоки, помогите заблудшему.
Добавлено: 22 Август 2007, 16:05
StillZero
GetCommModemStatus неверно описан, смотри внимательнее в MSDN, второй параметр это out и соотвественно должен быть описан как *DWORD или что-тоже *LONG
чтобы узнать почему ошибка см GetLastError.
кстати в описании говорится, что эта функция GetCommModemStatus должна использоваться вместе с WaitCommEvent
Добавлено: 24 Август 2007, 8:48
Dias2004
StillZero, действительно я проигнорировал тип параметра out, хуже того - даже и не знал, что это есть передача по ссылке...
Все заработало, спасибо!
Что касается использования WaitCommEvent: в описании не сказано, что ее использование обязательно, просто функция позволяет избавиться от необходимости циклического вызова GetCommModemStatus. В моем конкретном случае в программе уже имеется таймер и его обработчик, поэтому я решил не возиться с еще одной функцией, а организовать именно циклический вызов.
Добавлено: 24 Август 2007, 11:01
Admin
Re:
Добавлено: 27 Октябрь 2008, 14:08
han
Зарегистрировался в приват, получил разрешение админа, но скачать не могу мой login и password не проходят.
Ч.Д.
Re: Re:
Добавлено: 27 Октябрь 2008, 16:02
Admin
han писал(а):
Зарегистрировался в приват, получил разрешение админа, но скачать не могу мой login и password не проходят.
Ч.Д.
Читаем тут:
http://forum.clarionlife.net/phpbb/view ... =15&t=1326