COM-порт в Windows (программирование): различия между версиями

Содержимое удалено Содержимое добавлено
м <source> -> <syntaxhighlight> (phab:T237267)
Строка 56:
 
Открытый порт должен быть закрыт перед завершением работы [[программа|программы]]. В [[Win32 (программирование)|Win32]] закрытие объекта по его [[дескриптор]]у выполняет функция <code>CloseHandle</code>:
<sourcesyntaxhighlight lang="c">
BOOL CloseHandle(
HANDLE hObject
);
</syntaxhighlight>
</source>
При успешном завершении функция возвращает не нулевое значение, при ошибке нуль.
 
=== Пример открытия/закрытия на языке [[Си (язык программирования)|C]] ===
<sourcesyntaxhighlight lang="c">
#include <windows.h>
//. . .
Строка 77:
CloseHandle(Port);
//. . .
</syntaxhighlight>
</source>
В данном [[пример]]е открывается порт <code>СОМ2</code> для [[чтение|чтения]] и [[запись|записи]], используется синхронный режим обмена. Проверяется успешность открытия порта, при ошибке выводится сообщение и программа завершается. Если порт открыт успешно, то он закрывается.
 
Строка 256:
winbase.h
 
<sourcesyntaxhighlight lang="cpp">
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
Строка 264:
DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
</syntaxhighlight>
</source>
 
'''ReadIntervalTimeout''' - время в миллисекундах, задающее максимальное время, для интервала между поступлением двух символов по линии связи. Если интервал между поступлением каких-либо двух символов будет больше этой величины, операция ReadFile завершается и любые буферизированные данные возвращаются.
 
Чтобы операция ReadFile немедленно возвращала управление со всеми полученными данными (асинхронный режим) следует задавать следующие значения:
<sourcesyntaxhighlight lang="cpp">
ReadIntervalTimeout=0xFFFFFFFF;
ReadTotalTimeoutConstant=0;
ReadTotalTimeoutMultiplier=0;
</syntaxhighlight>
</source>
 
'''ReadTotalTimeoutMultiplier''' - Множитель, используемый, чтобы вычислить полный период времени простоя для операций чтения, в миллисекундах. Для каждой операции чтения, это значение умножается на затребованное число байтов, которые читаются.
Строка 291:
Вариант 1: (максимальная задержка при чтении и записи = TIMEOUT)
 
<sourcesyntaxhighlight lang="cpp">
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
Строка 298:
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = TIMEOUT;
</sourcesyntaxhighlight>
 
Вариант 2: Инициализация значениями (без задержки при чтении)
 
<sourcesyntaxhighlight lang="cpp">
COMMTIMEOUTS CommTimeOuts={0xFFFFFFFF,0,0,0,1500};
</syntaxhighlight>
</source>
 
== Пример настройки порта ==
Строка 315:
Настройку структуры можно выполнить вручную или при помощи функции GetCommConfig().
Например:
<sourcesyntaxhighlight lang="cpp">
/* Получение существующих настроек */
unsigned long new_size = 0;
Строка 326:
goto error;
}
</sourcesyntaxhighlight>
 
== Выделение памяти для структуры COMMPORT ==
Строка 333:
Прием и передача данных для последовательного порта может выполнятся в синхронном или асинхронном режимах. Асинхронный режим позволяет реализовать работу по событиям, в то время как синхронный лишен этой возможности, но является более простым в реализации.
Для работы в синхронном режиме, порт должен быть открыт следующим образом:
<sourcesyntaxhighlight lang="cpp">
CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
</syntaxhighlight>
</source>
Предпоследний параметр '''dwFlagsAndAttributes''' должен быть равен 0.
После успешного открытия порта, данные могут быть считаны или записаны при помощи функций ReadFile() и WriteFile().
 
<sourcesyntaxhighlight lang="cpp">
HANDLE port = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
Строка 348:
if(ReadFile(port,dst,size, &size,0))
printf("\nRead %d bytes",size);
</syntaxhighlight>
</source>
Функция ReadFile/WriteFile осуществляет чтение/запись из файла (устройства) начиная с текущей позиции после окончания чтения обновляет указатель в файле.
 
<sourcesyntaxhighlight lang="cpp">
BOOL ReadFile(
HANDLE hFile, // хендл файла
Строка 359:
LPOVERLAPPED lpOverlapped //структура OVERLAPPED
);
</syntaxhighlight>
</source>
 
Недостатком этого способа является то, что вызывая функцию ReadFile(), мы не знаем есть ли данные для чтения. Можно циклически проверять их наличие, но это приводит к дополнительным расходам времени ЦП.
Поэтому на практике часто удобней использовать асинхронный режим. Для этого при вызове функции CreateFile() параметр '''dwFlagsAndAttributes''' должен быть равен '''FILE_FLAG_OVERLAPPED'''.
<sourcesyntaxhighlight lang="cpp">
CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
</syntaxhighlight>
</source>
Далее, необходимо настроить реакцию порта на события при помощи функции SetCommMask() и используя функции WaitCommEvent() и WaitForSingleObject() ожидать событие или тайм аут.
Например:
<sourcesyntaxhighlight lang="cpp">
const int READ_TIME = 100;
OVERLAPPED sync = {0};
Строка 397:
}
CloseHandle(sync.hEvent);
</syntaxhighlight>
</source>
 
== Сброс порта ==
Строка 404:
 
=== tty.h ===
<sourcesyntaxhighlight lang="cpp">
#ifndef TTY_H
#define TTY_H
Строка 437:
 
#endif
</syntaxhighlight>
</source>
 
=== tty.cpp ===
<sourcesyntaxhighlight lang="cpp">
#include "tty.h"
#include <iostream>
Строка 616:
}
 
</syntaxhighlight>
</source>
 
{{Темы|Программирование}}