Работа с COM портами
Получение списка имеющихся в системе портов:
Существует как минимум два способа:
1.Список доступных портов можно узнать, проанализировав ключ
реестра HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM
2.Можно поочередно попробовать открыть порты COM1 .. COM9, таким
образом удастся установить все доступные порты (т.е. порты, не открытые
другими приложениями)
Открытие и настройка COM порта:
Работу с СOM портом проще всего пояснить на примере
var
DCB
: TDCB;
hPort
: THandle;
begin
//
1. Открываем файл
hPort := CreateFile(PChar(\'COM\'+IntToStr(<номер
порта>)),
GENERIC_READ + GENERIC_WRITE,
0, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// 2.
Контроль ошибок
if hPort = INVALID_HANDLE_VALUE then begin
//
Обнаружена ошибка, порт открыть не удалось
exit;
end;
//
3. Чтение текущих настроек порта
if GetCommState(hPort, DCB) then ;
// 4.
Настройки
//
Скорость обмена
DCB.BaudRate := [скорость обмена];
//
Число бит на символ
DCB.ByteSize := [размер \"байта\" при обмене по COM порту - обычно 8
бит];
//
Стоп-биты
DCB.StopBits := [константа, определяющая кол-во стопбитов];
//
Четность
DCB.Parity := [константа, определяющая режим контроля четности];
DCB.Flags := 20625;
//
5. Передача настроек
if not SetCommState(hPort, DCB) then {ошибка
настройки порта};
// 6.
Настройка буферов порта (очередей ввода и вывода)
if not SetupComm(hPort, 16, 16) then {ошибка
настройки буферов};
// 7.
Сброс буфферов и очередей
if PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or
PURGE_RXCLEAR) then ;
...............
// 8.
Закрытие порта
CloseHandle(hPort);
end;
Теперь рассмотрим все шаги по порядку:
Шаг 1
- открытие порта. Порт открывается стандартной командой CreateFile,
только в качестве имени файла передается имя порта (например, \"COM1\")
Шаг 2
- проверка успешности шага 1. Если порт открылся, то функция CreateFile
возвращает его Handle, иначе hPort = INVALID_HANDLE_VALUE, что
свидетельствует об ошибке
Шаг 3
- загрузка текущих настроек порта при помощи функции GetCommState. Этот
шаг не является обязательным, т.к. можно настроить порт, как говорится,
\"с нуля\". После выполнения GetCommState структура DCB заполняется
текущими настройками
Шаг 4
- занесение в структуру DCB необходимых настроек
Шаг 5
- Настрока порта при помощи функции SetCommState. После настройки с
портом уже можно работать, но в примере я выполняю полную настроку (шаги
6 и 7)
Шаг 6
- Настрока размеров буфера приема и предачи при помощи SetupComm. В моем
примере заданы буфера очень небольшого размера, рекомендуется задать
окого 1 кб
Шаг 7
- Очистка буферов и очередей порта - второй параметра функции PurgeComm
является битовой маской и задает, что именно необходимо очитстить - в
нашем случае все по максимуму
Шаг 8
- закрытие порта после завершения работы с ним
Чтение и запись данных:
Запись данных производится следующим образом:
Result := WriteFile(hPort, Buffer, Size, NumberOfBytesWritten, nil);
параметр NumberOfBytesWritten после выполнения содержит количество
реально переданных байт. Чтение данных:
Result := ReadFile(hPort, Buffer, Size, NumberOfBytesReaded, nil);
параметр Size задает читаемый объем информации (его значение должно быть
меньше объема буфера), NumberOfBytesReaded получает количество реально
прочитанных байт
Настройка таймаутов приема и передачи:
Настройку таймаутов можно провести при помощи слудующей функции:
function SetComPortTimeouts: boolean;
var
CommTimeouts
: TCommTimeouts;
ComErrors
: DWORD;
begin
Result
:= false;
//
Если соединение есть, то перенастроим его
if
hPort <> INVALID_HANDLE_VALUE then begin
//
Чтение текущих таймаутов
GetCommTimeouts(hPort, CommTimeouts);
...
настройка параметров структуры
CommTimeouts ...
//
Установка таймаутов
SetCommTimeouts(hPort, CommTimeouts);
Result := true;
end;
end;
Запрос ошибки:
Запрос ошибки производится при помощи функции
ClearCommError
var
ComErrors : DWORD;
begin
ClearCommError(hPort, ComErrors, nil);
end;
Данная функция сбрасывает состояние ошибки, передавая код ошибки в
переменную ComErrors
|