Что такое порт? Правила для работы с портами

Материал из DRKB

Что такое порт? Правила для работы с портами[править | править код]

 Взято из FAQ: http://blackman.km.ru/myfaq/cont4.phtml

Известно что в компьютере очень много собрано различных устройств, возникает вопрос как операционная система общается с ними. Для этого и служит порт, то есть эта «дверь» через которую программа (операционная система) может управлять данным устройством (считывать данные, заносить их). Причем я разделяю порты на две категории (это чисто мое разделение) - порты общеизвестные (COM, LPT) и порты внутренние, служащие для связи с внутренними устройствами ЭВМ.

2. Некоторые правила для работы с портами

Следует иметь в виду что при разработке программ имеющих дело с портами следует учитывать следующие факторы:

а) Стараться использовать функции высокого уровня для доступа к портам (в частности WinAPI) и не прибегать к низкоуровневым операциям чтения/записи портов. Если вы все-таки решили писать низкоуровневое чтение то эти процедуры нужно выносить в отдельную DLL или VXD, по следующим причинам - известно, что операционная система Windows95/98 а особенно NT являются по своей сути многозадачными системами. То есть если ваша программа обращается конкретно к порту не через динамический вызов функции DLL или VXD ( использования механизма DLL) а напрямую то это может сказаться на корректной работе системы или даже завалить ее. И даже если в Windows95/98 такой подход вполне может работать то в Windows NT вследствие его архитектуры не разрешит непосредственное чтение/запись напрямую, а использование механизма DLL или VXD позволяет обойти эту проблему.
б) Если вы работаете с каким-то нестандартным портом ввода-вывода (например портом хранящим состояние кнопок пульта ДУ TVTunera то наверняка в комплекте поставки родного софта найдется DLL или VXD для управления этим устройством и отпадет нужда писать код, так я при работе с пультом ДУ TVTunerа использую стандартную DLL поставляемую в комплекте, это сразу решило вопросы связанные с управлением портами данного тюнера)

Итак, отступление - немного практики…

Маленький пример для работы с портами (первый пример был уже опубликован в королевстве Дельфи и представлял собой пример работы с весами ПетрВес)

function PortInit : boolean; // инициализация
var f: THandle; 
    ct: TCommTimeouts;
    dcb: TDCB;
begin
  f := Windows.CreateFile(PChar('COM1'), GENERIC_READ or GENERIC_WRITE,
    FILE_SHARE_READ or FILE_SHARE_WRITE,
    nil, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0);

  if (f < 0) 
  or not Windows.SetupComm(f, 2048, 2048)
  or not Windows.GetCommState(f, dcb)
  then
    Exit; // init error dcb.BaudRate := { скоpость };

  dcb.StopBits := { стоп-биты };
  dcb.Parity := { четность };
  dcb.ByteSize := 8;

  if not Windows.SetCommState(f, dcb)
  or not Windows.GetCommTimeouts(f, ct)
  then
    Exit; // error

  ct.ReadTotalTimeoutConstant := 50;
  ct.ReadIntervalTimeout := 50;
  ct.ReadTotalTimeoutMultiplier := 1;
  ct.WriteTotalTimeoutMultiplier := 0;
  ct.WriteTotalTimeoutConstant := 10;
  if not Windows.SetCommTimeouts(f, ct)
  or not Windows.SetCommMask(f, EV_RING + EV_RXCHAR + EV_RXFLAG + EV_TXEMPTY)
  then
    Exit; // error

  Result := True;
end;

function DoneComm: boolean; // закpыть поpт
begin
  Result := Windows.CloseHandle(f);
end; 

function PostComm(var Buf; size: word): integer; // передача в порт
var
  p: pointer;
  i: integer;
begin
  p := @Buf;
  Result := 0;
  while size > 0 do 
  begin
    if not WriteFile(f, p^, 1, i, nil) then Exit;
    Inc(result, i);
    Inc(Integer(p));
    Dec(size);
    Application.ProcessMessages;
  end;
end; 

function ReadComm(var Buf; size: word): integer; // прием из порта
var
  i: integer;
  ovr: TOverlapped;
begin
  FillChar(buf, size, 0);
  FillChar(ovr, SizeOf(ovr), 0);
  i := 0;
  Result := -1;
  if not Windows.ReadFile(f, buf, size, i, @ovr) then
    Exit;
  Result := i;
end;


Данный пример был взят мной из многочисленный FAQ посвященных в DELPHI в сети ФИДО

Итак, для работы с портами COM и LPT нам понадобится знание функций Windows API. Вот подробное описание функций, которые нам нужны (в эквиваленте C) для работы с портами.

(извините за возможный местами неточный перевод ,если что поправьте меня если что не так перевел)


CreateFile[править | править код]

HANDLE CreateFile(
  LPCTSTR lpFileName,  // указатель на строку PCHAR с именем файла
  DWORD dwDesiredAccess, // режим доступа
  DWORD dwShareMode, // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // указатель на атрибуты
  DWORD dwCreationDistribution, // how to create
  DWORD dwFlagsAndAttributes, // атрибуты файла
  HANDLE hTemplateFile // хендл на temp файл
);

Пример кода на Дельфи

  CommPort := 'COM2'; 
  hCommFile := CreateFile(Pchar(CommPort), 
    GENERIC_WRITE, 0, nil, 
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Параметры[править | править код]
LpFileName
Указатель на строку с нулевым символом в конце (PCHAR), которая определяет название создаваемого объекта (файл, канал, почтовый слот, ресурс связи (в данном случае порты),

дисковое устройство, приставка, или каталог)

DwDesiredAccess
Указывает тип доступа к объекту, принимает значение
  • GENERIC_READ - для чтения
  • GENERIC_WRITE - для записи (смешивание с GENERIC_READ операцией GENERIC_READ and GENERIC_WRITE предоставляет полный доступ )
dwShareMode
Набор разрядных флагов, которые определяют как объект может быть разделен по доступу к нему.
Если dwShareMode - 0, объект не может быть разделен.
Последовательные операции открытия объекта будут терпеть неудачу, пока маркер(дескриптор) открытого объекта не будет закрыт.
Фактически предоставляется монопольный доступ. Чтобы разделять объект(цель), используйте комбинацию одних или большее количество следующих значений:
  • FILE_SHARE_DELETE (Только для Windows NT)
  • FILE_SHARE_READ
  • FILE_SHARE_WRITE
LpSecurityAttributes
Указатель на структуру SECURITY_ATTRIBUTES, которая определяет, может ли возвращенный дескриптор быть унаследован дочерними процессами. Если lpSecurityAttributes НУЛЕВОЙ, маркер не может быть унаследован. Используется только в windows NT.
dwCreationDistribution
Определяет поведение функции если объект уже существует и как он будет открыт в этом случае Принимает одно из следующих значений:
  • CREATE_NEW - Создает новый объект (файл) Выдает ошибку если указанный объект (файл) уже существует.
  • CREATE_ALWAYS - Создает новый объект (файл) Функция перезаписывает существующий объект (файл)
  • OPEN_EXISTING - Открывает объект (файл) Выдает ошибку если указанный объект (файл) не существует.(Для более детального смотрите SDK)
  • OPEN_ALWAYS - Открывает объект (файл), если он существует. Если объект (файл) не существует, функция создает его, как будто dwCreationDistribution были CREATE_NEW.
  • TRUNCATE_EXISTING - Открывает объект (файл). После этого объект (файл) будет усечен до нулевого размера.Выдает ошибку если указанный объект (файл) не существует.
DwFlagsAndAttributes
Атрибуты объекта (файла), атрибуты могут комбинироваться
  • FILE_ATTRIBUTE_ARCHIVE
  • FILE_ATTRIBUTE_COMPRESSED
  • FILE_ATTRIBUTE_HIDDEN
  • FILE_ATTRIBUTE_NORMAL
  • FILE_ATTRIBUTE_OFFLINE
  • FILE_ATTRIBUTE_READONLY
  • FILE_ATTRIBUTE_SYSTEM
  • FILE_ATTRIBUTE_TEMPORARY
HTemplateFile
Определяет дескриптор с GENERIC_READ доступом к временному объекту(файлу). Временный объект(файл)поставляет атрибуты файла и расширенные атрибуты для создаваемого объекта (файла)
ИСПОЛЬЗУЕТСЯ ТОЛЬКО В WINDOWS NT Windows 95 - Это значение должно быть установлено в Nil.
Возвращаемые значения[править | править код]

Если функция преуспевает, возвращаемое значение - открытый дескриптор к указанному объекту(файлу). Если файл не существует - 0.

Если произошли функциональные сбои, возвращаемое значение - INVALID_HANDLE_VALUE.

Чтобы получить расширенные данные об ошибках, вызовите GetLastError.

Обратите внимание! Для портов, dwCreationDistribution параметр должен быть OPEN_EXISTING, и hTemplate должен быть Nil. Доступ для чтения-записи должен быть определен явно. SECURITY_ATTRIBUTES Структура содержит описание защиты для объекта и определяет, может ли дескриптор быть унаследован дочерними процессами.


SECURITY_ATTRIBUTES[править | править код]

typedef struct _SECURITY_ATTRIBUTES {
  DWORD nLength;
  LPVOID lpSecurityDescriptor;
  BOOL bInheritHandle;
} SECURITY_ATTRIBUTES;
Параметры[править | править код]
NLength
Определяет размер, в байтах, этой структуры.
Набор это значение к размеру структуры SECURITY_ATTRIBUTES В Windows NT функции которые используют структуру SECURITY_ATTRIBUTES, не
LpSecurityDescriptor
Дескриптор указывающий на описатель защиты для объекта,
Если дескриптор ПУСТОЙ объект может быть назначен в наследование дочерними процессами.
BInheritHandle
Определяет, унаследован ли возвращенный дескриптор, когда новый дескриптор, создан.
Если это значение принимает ИСТИНУ новый дескриптор наследует от головного.
Замечания[править | править код]

Указатель на структуру SECURITY_ATTRIBUTES используется как параметр в большинстве функций работы с окнами в Win32 API.


Структура DCB[править | править код]

Структура DCB определяет установку управления для последовательного порта ввода-вывода (нам она понадобится для разбора примера с программой управления весами ПетрВес)

Примечание: В местах где нельзя дать точный перевод будет дано определение на английском из MSDK и приблизительный его перевод

Описание в эквиваленте C

typedef struct _DCB { // dcb 
  DWORD DCBlength; // Размер DCB
  DWORD BaudRate; // Скорость пересылки данных в бодах; текущая скорость в бодах
  DWORD fBinary: 1; // binary mode, no EOF check
                    // двоичный режим , не проверять конец данных (по умолчанию значение = 1)
  DWORD fParity: 1; // Включить проверку четность (по умолчанию значение = 1)
  DWORD fOutxCtsFlow:1; // CTS управление потоком выхода
  DWORD fOutxDsrFlow:1; // DSR управление потоком выхода
  DWORD fDtrControl:2; // DTR Тип управления потоком скорости передачи данных
  DWORD fDsrSensitivity:1; // DSR sensitivity (чувствительность)
  DWORD fTXContinueOnXoff:1; // XOFF continues Tx (стоп-сигнал продалжает выполнение)
  DWORD fOutX: 1; // XON/XOFF out flow control (СТАРТ-СИГНАЛ / СТОП-СИГНАЛ для управления выходящим потоком (по умолчанию значение = 1)
  DWORD fInX: 1; // XON/XOFF in flow control (СТАРТ-СИГНАЛ / СТОП-СИГНАЛ для управления входящим потоком (по умолчанию значение = 1)
  DWORD fErrorChar: 1; // enable error replacement (включить проверку погрешностей по умолчанию=1)
  DWORD fNull: 1; // enable null stripping (отвергать пустой поток данных (по умолчанию=1))
  DWORD fRtsControl:2; // RTS управление потоком данных
  DWORD fAbortOnError:1; // abort reads/writes on error (проверять операции чтения/записи по умолчанию=1)
  DWORD fDummy2:17; // reserved ЗАРЕЗЕРВИРОВАНО
  WORD wReserved; // not currently used НЕ ДЛЯ ИСПОЛЬЗОВАНИЯ
  WORD XonLim; // transmit XON threshold (порог чувствительности старт-сигнала)
  WORD XoffLim; // transmit XOFF threshold (порог чувствительности стоп-сигнала)
  BYTE ByteSize; // Бит в байте (обычно 8)
  BYTE Parity; // 0..4 = no, odd, even, mark, space (четность байта)
  BYTE StopBits; // 0, 1, 2 = 1, 1.5, 2 (стоповые биты)
  char XonChar; // Tx and Rx XON character (вид старт сигнал в потоке)
  char XoffChar; // Tx and Rx XOFF character (вид стоп сигнал в потоке)
  char ErrorChar; // error replacement character (какой сигнал погрешности, его вид)
  char EofChar; // end of input character (сигнал окончания потока)
  char EvtChar; // received event character РЕЗЕРВ
  WORD wReserved1; // reserved; do not use НЕ ДЛЯ ИСПОЛЬЗОВАНИЯ
} DCB;


with Mode do
begin
  BaudRate := 9600;
  ByteSize := 8;
  Parity := NOPARITY;
  StopBits := ONESTOPBIT; // одиночный стоп-бит
  Flags := EV_RXCHAR + EV_EVENT2;
end;


Параметры[править | править код]
DCBlength
Размер DCB структуры.
BaudRate
Определяет скорость в бодах, в которых порт оперирует.
Этот параметр может принимать фактическое значение скорости в бодах, или один из следующих стандартных индексов скорости в бодах:
  • CBR_110 CBR_19200
  • CBR_300 CBR_38400
  • CBR_600 CBR_56000
  • CBR_1200CBR_57600
  • CBR_2400CBR_115200
  • CBR_4800CBR_128000
  • CBR_9600CBR_256000
  • CBR_14400
fBinary
Определяет, допускается ли двоичный (бинарный) способ передачи данных.
Win32 API не поддерживает недвоичные (небинарные) способы передачи данных в потоке порта, так что этот параметр должен быть всегда ИСТИНЕН.
Попытка использовать ЛОЖЬ в этом параметре не будет работать.
Примечание: Под Windows 3.1 небинарный способ передачи допускается, но для работы данного способа необходимо заполнить параметр EofChar, который будет восприниматься конец данных.
fParity
Определяет, допускается ли проверка четности.
Если этот параметр ИСТИНЕН, проверка четности допускается
fOutxCtsFlow
CTS (clear-to-send) управление потоком выхода
fOutxDsrFlow
DSR (data-set-ready) управление потоком выхода
fDtrControl
DTR (data-terminal-ready) управление потоком выхода
Принимает следующие значения:
  • DTR_CONTROL_DISABLE - Отключает линию передачи дынных
  • DTR_CONTROL_ENABLE - Включает линию передачи дынных
  • DTR_CONTROL_HANDSHAKE - Enables DTR handshaking. If handshaking is enabled, it is an error for the application to adjust the line by using the EscapeCommFunction function.
Допускает подтверждению связи передачи данных
Если подтверждение связи допускается, это - погрешность для того чтобы регулировать(корректировать) линию связи, используя функцию EscapeCommFunction.
fDsrSensitivity
Specifies whether the communications driver is sensitive to the state of the DSR signal.
If this member is TRUE, the driver ignores any bytes received, unless the DSR modem input line is high.
Определяет возможна ли по порту двухсторонняя передача в ту и в другую сторону сигнала.
fTXContinueOnXoff
Определяет, останавливается ли передача потока, когда входной буфер становится полный, и драйвер передает сигнал XoffChar.
Если этот параметр ИСТИНЕН, передача продолжается после того, как входной буфер становится в пределах XoffLim байтов, и драйвер передает сигнал XoffChar, чтобы прекратить прием байтов из потока.

Если этот параметр ЛОЖНЫЙ, передача не продолжается до тех пор, пока входной буфер не в пределах XonLim байтов, и пока не получен сигнал XonChar, для возобновления приема.

fOutX
Определяет, используется ли управление потоком СТАРТ-СИГНАЛА / СТОП-СИГНАЛА в течение передачи потока порту. Если этот параметр ИСТИНЕН, передача останавливается, когда получен сигнал XoffChar и начинается снова, когда получен сигнал XonChar.
fInX
Specifies whether XON/XOFF flow control is used during reception. If this member is TRUE, the XoffChar character is sent when the input buffer comes within XoffLim bytes of being full, and the XonChar character is sent when the input buffer comes within XonLim bytes of being empty.
Определяет, используется ли управление потоком СТАРТ-СИГНАЛА / СТОП-СИГНАЛА в течение приема потока портом. Если этот параметр ИСТИНЕН, сигнал XoffChar посылается, когда входной буфер находится в пределах XoffLim байтов, а сигнал XonChar посылается тогда когда входной буфер находится в пределах XonLim байтов или является пустым
fErrorChar
Определяет, заменены ли байты, полученные с ошибками четности особенностью, указанной параметром ErrorChar Если этот параметр ИСТИНЕН, и fParity ИСТИНЕН, замена происходит.
fNull
Определяет, отвергнуты ли нулевые(пустые) байты. Если этот параметр ИСТИНЕН, нулевые(пустые) байты, будут отвергнуты при получении их.
fRtsControl
RTS управление потоком "запрос пересылки".
Если это значение нулевое, то по умолчанию устанавливается RTS_CONTROL_HANDSHAKE.
Принимает одно из следующих значений:
  • RTS_CONTROL_DISABLE - Отключает строку RTS, когда устройство открыто
  • RTS_CONTROL_ENABLE - Включает строку RTS
  • RTS_CONTROL_HANDSHAKE - Enables RTS handshaking. The driver raises the RTS line when the "type-ahead" (input) buffer is less than one-half full and lowers the RTS line when the buffer is more than three-quarters full. If handshaking is enabled, it is an error for the application to adjust the line by using the EscapeCommFunction function.
Допускает RTS подтверждение связи. Драйвер управляет потоком пересылки.
RTS выравнивается, когда входной буфер - меньше чем половина полного и понижается, когда буфер - больше 2/3 полного. Если подтверждение связи допускается, это используется для регулирования передачи данных EscapeCommFunction.
  • RTS_CONTROL_TOGGLE - Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low.
Определяет, что буфер будет высокий при подготовке данных для передачи. После того, как все байты отосланы, буфер RTS будет низок.
FAbortOnError
Определяет, закончена ли операции чтения/записи, если происходит погрешность.
Если этот параметр ИСТИНЕН, драйвер закрывает все операции чтения/записи с состоянием погрешности при возникновении оной. Драйвер не будет принимать никакие дальнейшие действия, пока не дождется подтверждения погрешности в передаваемых (принимаемых) данных, вызывая функцию ClearCommError.
fDummy2
ЗАРЕЗЕРВИРОВАНО Microsoft
wReserved
ЗАРЕЗЕРВИРОВАНО Microsoft
XonLim
Определяет минимальное число байтов, находящихся во в XoffLim
Определяет максимальное число байтов, находящихся во входном буфере прежде, чем будет генерирована подача СТОП-СИГНАЛА. Максимальное число байтов, позволенных во входном буфере вычитается из размеров, в байтах, самого входного буфера.
ByteSize
Определяет число битов в байтах, переданных и полученных.
Parity
Определяет схему четности, которую нужно использовать.
Этот параметр может быть одним из следующих значений:
  • EVENPARITY
  • MARKPARITY
  • NOPARITY
  • ODDPARITY
StopBits
Определяет число стоповых битов, которые нужно использовать.
Этот параметр может быть одним из следующих значений:
  • ONESTOPBIT - 1 stop bit
  • ONE5STOPBITS - 1.5 stop bits
  • TWOSTOPBITS - 2 stop bits
XonChar
Определяет значение СТАРТ-СИГНАЛА для передачи и приема.
XoffChar
Определяет значение СТОП-СИГНАЛА для передачи и приема.
ErrorChar
Определяет значение СИГНАЛА ОШИБКИ (генерируемого при ошибке четности) для передачи и приема.
EofChar
Определяет значение сигнала конца данных.
EvtChar
Определяет значение сигнала события.
wReserved1
ЗАРЕЗЕРВИРОВАНО Microsoft


Дополнение[править | править код]

Когда структура DCB использует «ручной» выбор конфигурации, следующие ограничения используются для ByteSize и StopBits параметров:

  • Число информационных разрядов должно быть от 5 до 8 битов.
  • Использование 5 информационных разрядов с 2 стоповыми битами - недопустимая комбинация, как - 6, 7, или 8 информационных разрядов с 1.5 стоповыми битами.


Author: Дмитрий Кузан mailto:kuzan@fsskomi.parma.ru
Source: Взято с Vingrad.ru http://forum.vingrad.ru
ID: 01338