Windows com порт как файл

Содержание
  1. Работа с COM портом на C++ в Windows
  2. COM-порт в Windows (программирование)
  3. Содержание
  4. Открытие порта [ править ]
  5. lpFileName [ править ]
  6. dwDesiredAccess [ править ]
  7. dwShareMode [ править ]
  8. lpSecurityAttributes [ править ]
  9. dwCreationDistribution [ править ]
  10. dwFlagsAndAttributes [ править ]
  11. hTemplateFile [ править ]
  12. Закрытие порта [ править ]
  13. Пример открытия/закрытия на языке C [ править ]
  14. Структура DCB [ править ]
  15. DCBlength [ править ]
  16. BaudRate [ править ]
  17. fBinary [ править ]
  18. fParity [ править ]
  19. fOutxCtsFlow [ править ]
  20. fOutxDsrFlow [ править ]
  21. fDtrControl [ править ]
  22. fDsrSensitivity [ править ]
  23. fTXContinueOnXoff [ править ]
  24. fOutX [ править ]
  25. fInX [ править ]
  26. fErrorChar [ править ]
  27. fNull [ править ]
  28. fRtsControl [ править ]
  29. fAbortOnError [ править ]
  30. fDummy2 [ править ]
  31. wReserved [ править ]
  32. XonLim [ править ]
  33. XoffLim [ править ]
  34. ByteSize [ править ]
  35. Parity [ править ]
  36. StopBits [ править ]
  37. XonChar [ править ]
  38. XoffChar [ править ]
  39. ErrorChar [ править ]
  40. EofChar [ править ]
  41. EvtChar [ править ]
  42. wReserved1 [ править ]
  43. Замечания [ править ]
  44. Заполнение структуры DCB [ править ]
  45. Структура COMMTIMEOUTS [ править ]
  46. Заполнение структуры COMMTIMEOUTS [ править ]
  47. Пример настройки порта [ править ]
  48. Структура COMMPORT [ править ]
  49. Стандартный диалог настройки порта [ править ]
  50. Выделение памяти для структуры COMMPORT [ править ]
  51. Прием и передача данных [ править ]
  52. Сброс порта [ править ]
  53. Пример настройки порта и выполнения чтения/записи данных [ править ]

Работа с COM портом на C++ в Windows

Последовательные порты полюбились разработчикам за их простоту в обслуживании и использовании.

И конечно же писать в консоль терминальной программы это всё хорошо, но хочеться своё приложение, которое по нажатии клавиши на экране выполняет нужные вам действия 😉

В этой статье опишу как работать с com портом на языке Си++.

Решение простое, но почемуто рабочий пример найден был не сразу. За сим сохраняю его тут.

Конечно вы можете использовать кроссплатформенные решения вроде QSerial — библиотеки в составе Qt, я наверное так и сделаю, но в будующем. Сейчас же речь о «чистом» виндовском C++. Писать будем в Visual Studio. У меня 2010, хотя роли это никакой не играет.

Создаём новый консольный Win32 проект.

Инклудим header файлы:

Объявляем обработчик com порта:

Я делаю это глобально, чтобы не заморачиваться с указателями при передаче его в функции.

Дальше начинаем формировать функцию main:

Терпеть не могу виндовский стиль программирования. Обозвали всё посвоему и сидят радуются.

Теперь магия объявления строки с именем порта. Дело в том, что char оно преобразовывать само не умеет.

Работа с последоавательными портами в Windows проходит как с файлом. Открываем первый ком порт для записи/чтения:

Теперь нужно настроить параметры соединения:

На msdn советуют сначала получить параметры, а затем менять их. Мы ещё только учимся, поэтому делаем как просят.

Теперь объявим строку, которую будем передавать и переменные необходимые для этого:

Посылаем строку. Напомню, что пример простейший, поэтому никаких особо проверок я не делаю:

Также я решил вывести для контроля размер строки и количество отосланных байт:

В конце программы делаем бесконечный цикл чтения данных:

Теперь функция чтения:

Вот собственно и весь пример.

Я создал виртуальный com порт. И слал из COM1 в COM2:

COM-порт в Windows (программирование)

Написать программу, управляющую устройством через COM-порт, для MS-DOS не так сложно. С платформой Win32 дело обстоит сложнее. Но только на первый взгляд. Конечно напрямую работать с регистрами портов нельзя, Windows это не позволяет, зато можно не обращать внимания на тонкости различных реализаций (i8251, 16450, 16550A) и не возиться с обработкой прерываний.

Содержание

Открытие порта [ править ]

С последовательными и параллельными портами в Win32 работают как с файлами. Для открытия порта используется функция CreateFile . Эта функция предоставляется Win32 API. Ее прототип выглядит так:

lpFileName [ править ]

Указатель на строку с именем открываемого или создаваемого файла. Формат этой строки может быть очень «хитрым». В частности можно указывать сетевые имена для доступа к файлам на других компьютерах. Можно открывать логические разделы или физические диски и работать в обход файловой системы.

Последовательные порты имеют имена «COM1», «COM2», «COM3», «COM4», «COM5», «COM6», «COM7», «COM8», «COM9». Для доступа к портам, чей номер больше 9, необходимо указывать имя порта как «\\.\COMx», где x — номер порта. Например, «\\.\COM72» (в нотации языка C/C++ строка будет выглядеть «\\\\.\\COM72»). Такой синтаксис подходит для любого номера порта. Точно так же они назывались в MS-DOS. Параллельные порты называются «LPT1», «LPT2» и так далее.

Читайте также:  Происхождение операционной системы windows

dwDesiredAccess [ править ]

Задает тип доступа к файлу. Возможно использование следующих значений:

  • 0 Опрос атрибутов устройства без получения доступа к нему.
  • GENERIC_READ Файл будет считываться.
  • GENERIC_WRITE Файл будет записываться.
  • GENERIC_READ|GENERIC_WRITE Файл будет и считываться и записываться.

dwShareMode [ править ]

Задает параметры совместного доступа к файлу. Коммуникационные порты нельзя делать разделяемыми, поэтому данный параметр должен быть равен 0.

lpSecurityAttributes [ править ]

Задает атрибуты защиты файла. Поддерживается только в Windows NT. Однако при работе с портами должен в любом случае равняться NULL .

dwCreationDistribution [ править ]

Управляет режимами автосоздания, автоусечения файла и им подобными. Для коммуникационных портов всегда должно задаваться OPEN_EXISTING .

dwFlagsAndAttributes [ править ]

Задает атрибуты создаваемого файла. Также управляет различными режимами обработки. При работе с портом этот параметр должен быть или равным 0 , или FILE_FLAG_OVERLAPPED . Нулевое значение используется при синхронной работе с портом, а FILE_FLAG_OVERLAPPED при асинхронной, или, другими словами, при фоновой обработке ввода/вывода. Подробнее про асинхронный ввод/вывод я расскажу позже.

hTemplateFile [ править ]

Задает описатель файла-шаблона. При работе с портами всегда должен быть равен NULL .

При успешном открытии файла, в данном случае порта, функция возвращает дескриптор ( HANDLE ) файла. При ошибке [[| INVALID HANDLE VALUE ]]. Код ошибки можно получитить вызвав функцию [[| GetLastError ]].

Закрытие порта [ править ]

Открытый порт должен быть закрыт перед завершением работы программы. В Win32 закрытие объекта по его дескриптору выполняет функция CloseHandle :

При успешном завершении функция возвращает не нулевое значение, при ошибке нуль.

Пример открытия/закрытия на языке C [ править ]

В данном примере открывается порт СОМ2 для чтения и записи, используется синхронный режим обмена. Проверяется успешность открытия порта, при ошибке выводится сообщение и программа завершается. Если порт открыт успешно, то он закрывается.

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

Основные параметры последовательного порта описываются структурой DCB . Временные параметры — структурой COMMTIMEOUTS . Существует еще несколько информационных и управляющих структур, но они используются реже. Настройка порта заключается в заполнении управляющих структур и последующем вызове функций настройки.

Основную информацию содержит структура DCB :

Эта структура содержит почти всю управляющую информацию, которая в реальности располагается в различных регистрах последовательного порта.

DCBlength [ править ]

Задает длину, в байтах, структуры DCB . Используется для контроля корректности структуры при передаче ее адреса в функции настройки порта.

BaudRate [ править ]

Скорость передачи данных. Возможно указание следующих констант: CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600, CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000 . Эти константы соответствуют всем стандартным скоростям обмена. На самом деле, это поле содержит числовое значение скорости передачи, а константы просто являются символическими именами. Поэтому можно указывать, например, и CBR_9600 , и просто 9600 . Однако рекомендуется указывать символические константы, поскольку при компиляции программы проверяется корректность их имен.

fBinary [ править ]

Включает двоичный режим обмена. Win32 не поддерживает недвоичный режим, поэтому данное поле всегда должно быть равно 1 , или логической константе TRUE (что предпочтительней). В Windows 3.1, если это поле было равно FALSE , включался текстовый режим обмена. В этом режиме поступивший на вход порта символ, заданный полем EofChar , свидетельствовал о конце принимаемых данных.

fParity [ править ]

Включает режим контроля четности. Если это поле равно TRUE , то выполняется проверка четности, при ошибке, в вызывающую программу, выдается соответствующий код завершения.

fOutxCtsFlow [ править ]

Включает режим слежения за сигналом [[| CTS ]]. Если это поле равно [[| TRUE ]] и сигнал [[| CTS ]] сброшен, передача данных приостанавливается до установки сигнала CTS . Это позволяет подключеному к компьютеру прибору приостановить поток передаваемой в него информации, если он не успевает ее обрабатывать.

fOutxDsrFlow [ править ]

Включает режим слежения за сигналом [[| DSR ]]. Если это поле равно TRUE и сигнал DSR сброшен, передача данных прекращается до установки сигнала DSR .

fDtrControl [ править ]

Задает режим управления обменом для сигнала [[| DTR ]]. Поле может принимать следующие значения:

  • DTR_CONTROL_DISABLE Сигнал DTR снимается при открытии порта. У открытого порта может быть изменён функцией EscapeCommFunction.
  • DTR_CONTROL_ENABLE Сигнал DTR устанавливается при открытии порта. У открытого порта может быть изменён функцией EscapeCommFunction.
  • DTR_CONTROL_HANDSHAKE Сигнал DTR автоматически устанавливается/снимается в ходе работы с портом. Не может быть изменён функцией EscapeCommFunction.
Читайте также:  Выключить hiberfil windows 10

fDsrSensitivity [ править ]

Задает чувствительсть коммуникационного драйвера к состоянию линии [[| DSR ]]. Если это поле равно TRUE , то все принимаемые данные игнорируются драйвером (коммуникационный драйвер расположен в операционной системе), за исключением тех, которые принимаются при установленом сигнале DSR .

fTXContinueOnXoff [ править ]

Задает, прекращается ли передача при переполнении приемного буфера и передаче драйвером символа XoffChar . Если это поле равно TRUE , то передача продолжается, несмотря на то, что приемный буфер содержит более XoffLim символов и близок к переполнению, а драйвер передал символ XoffChar для приостановления потока принимаемых данных. Если поле равно FALSE , то передача не будет продолжена до тех пор, пока в приемном буфере не останется меньше XonLim символов и драйвер не передаст символ XonChar для возобновления потока принимаемых данных. Таким образом это поле вводит некую зависимость между управлением входным и выходным потоками информации.

fOutX [ править ]

Задает использование XON/XOFF управления потоком при передаче. Если это поле равно TRUE , то передача останавливается при приеме символа XoffChar , и возобновляется при приеме символа XonChar .

fInX [ править ]

Задает использование XON/XOFF управления потоком при приеме. Если это поле равно TRUE , то драйвер передает символ XoffChar , когда в приемном буфере находится более XoffLim , и XonChar , когда в приемном буфере остается менее XonLim символов.

fErrorChar [ править ]

Указывает на необходимость замены символов с ошибкой четности на символ задаваемый полем ErrorChar . Если это поле равно TRUE , и поле fParity равно TRUE , то выполняется замена.

fNull [ править ]

Определяет действие выполняемое при приеме нулевого байта. Если это поле TRUE , то нулевые байты отбрасываются при передаче.

fRtsControl [ править ]

Задает режим управления потоком для сигнала RTS. Поле может принимать следующие значения:

  • RTS_CONTROL_DISABLE Сигнал RTS снимается при открытии порта. У открытого порта может быть изменён функцией EscapeCommFunction.
  • RTS_CONTROL_ENABLE Сигнал RTS устанавливается при открытии порта. У открытого порта может быть изменён функцией EscapeCommFunction.
  • RTS_CONTROL_HANDSHAKE Сигнал RTS автоматически устанавливается/снимается в ходе работы с портом. Не может быть изменён функцией EscapeCommFunction. Сигнал RTS устанавливается, когда приемный буфер заполнен менее, чем на половину, и снимается, когда буфер заполняется более чем на три четверти.
  • RTS_CONTROL_TOGGLE Задаёт, что сигнал RTS установлен, когда есть данные для передачи. Когда все символы из передающего буфера переданы, сигнал снимается.

fAbortOnError [ править ]

Задает игнорирование всех операций чтения/записи при возникновении ошибки. Если это поле равно TRUE , драйвер прекращает все операции чтения/записи для порта при возникновении ошибки. Продолжать работать с портом можно будет только после устранения причины ошибки и вызова функции ClearCommError.

fDummy2 [ править ]

Зарезервировано и не используется.

wReserved [ править ]

Не используется, должно быть установлено в 0 .

XonLim [ править ]

Задает минимальное число символов в приемном буфере перед посылкой символа XON .

XoffLim [ править ]

Определяет максимальное количество байт в приемном буфере перед посылкой символа XOFF . Максимально допустимое количество байт в буфере вычисляется вычитанием данного значения из размера приемного буфера в байтах.

ByteSize [ править ]

Определяет число информационных бит в передаваемых и принимаемых байтах. Число информационных бит может быть в диапазоне от 4 до 8 .

Parity [ править ]

Определяет выбор схемы контроля четности. Данное поле должно содержать одно из следующих значений:

  • EVENPARITY Дополнение до четности
  • MARKPARITY Бит четности всегда 1
  • NOPARITY Бит четности отсутствует
  • ODDPARITY Дополнение до нечетности
  • SPACEPARITY Бит четности всегда 0

StopBits [ править ]

Задает количество стоповых бит. Поле может принимать следующие значения:

  • ONESTOPBIT Один стоповый бит
  • ONE5STOPBIT Полтора стоповых бита
  • TWOSTOPBITS Два стоповых бита

XonChar [ править ]

Задает символ XON используемый как для приема, так и для передачи. Обычно 0x11 ( 17 ).

XoffChar [ править ]

Задает символ XOFF используемый как для приема, так и для передачи. Обычно 0x13 ( 19 ).

Читайте также:  Windows синий экран 00000019

ErrorChar [ править ]

Задает символ, использующийся для замены символов с ошибочной четностью.

EofChar [ править ]

Задает символ, использующийся для сигнализации о конце данных.

EvtChar [ править ]

Задает символ, использующийся для сигнализации о событии.

wReserved1 [ править ]

Зарезервировано и не используется.

Замечания [ править ]

Если структура DCB содержит конфигурацию для последовательного порта, совместимого с 8250, то к значениям полей ByteSize и StopBits применяются следующие ограничения:

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

Заполнение структуры DCB [ править ]

Структура COMMTIMEOUTS [ править ]

ReadIntervalTimeout — время в миллисекундах, задающее максимальное время, для интервала между поступлением двух символов по линии связи. Если интервал между поступлением каких-либо двух символов будет больше этой величины, операция ReadFile завершается и любые буферизированные данные возвращаются.

Чтобы операция ReadFile немедленно возвращала управление со всеми полученными данными (асинхронный режим) следует задавать следующие значения:

ReadTotalTimeoutMultiplier — Множитель, используемый, чтобы вычислить полный период времени простоя для операций чтения, в миллисекундах. Для каждой операции чтения, это значение умножается на затребованное число байтов, которые читаются.

ReadTotalTimeoutConstant — Константа, используемая, чтобы вычислить полный (максимальный) период времени простоя для операций чтения, в миллисекундах. Для каждой операции чтения, это значение добавляется к произведению члена структуры ReadTotalTimeoutMultiplier и прочитанного числа байтов.

Значение нуля и для члена ReadTotalTimeoutMultiplier, и для члена ReadTotalTimeoutConstant указывает, что полное время простоя не используются для операций чтения.

WriteTotalTimeoutMultiplier — Множитель, используемый, чтобы вычислить полный период времени простоя для операций записи, в миллисекундах. Для каждой операции записи, это значение умножается на число записываемых байтов.

WriteTotalTimeoutConstant — Константа, используемая, чтобы вычислить полный период времени простоя для операций записи, в миллисекундах. Для каждой операции записи, это значение добавляется к произведению члена структуры WriteTotalTimeoutMultiplier и записанного числа байтов.

Значение нуля и для члена WriteTotalTimeoutMultiplier, и для члена WriteTotalTimeoutConstant указывает, что полное время простоя не используются для операций записи.

Заполнение структуры COMMTIMEOUTS [ править ]

Вариант 1: (максимальная задержка при чтении и записи = TIMEOUT)

Вариант 2: Инициализация значениями (без задержки при чтении)

Пример настройки порта [ править ]

Структура COMMPORT [ править ]

Стандартный диалог настройки порта [ править ]

Для настройки параметров COM — порта может быть вызвано штатное окно Windows. Вызов осуществляется функцией CommConfigDialog(), которая в качестве параметров принимает имя настраиваемого порта, хендл родительского окна и указатель на структуру COMMCONFIG. Следует отметить, что для корректного вызова окна, структура COMMCONFIG должна быть заполнена значениями заранее. Настройку структуры можно выполнить вручную или при помощи функции GetCommConfig(). Например:

Выделение памяти для структуры COMMPORT [ править ]

Прием и передача данных [ править ]

Прием и передача данных для последовательного порта может выполнятся в синхронном или асинхронном режимах. Асинхронный режим позволяет реализовать работу по событиям, в то время как синхронный лишен этой возможности, но является более простым в реализации. Для работы в синхронном режиме, порт должен быть открыт следующим образом:

Предпоследний параметр dwFlagsAndAttributes должен быть равен 0. После успешного открытия порта, данные могут быть считаны или записаны при помощи функций ReadFile() и WriteFile().

Функция ReadFile/WriteFile осуществляет чтение/запись из файла (устройства) начиная с текущей позиции после окончания чтения обновляет указатель в файле.

Недостатком этого способа является то, что вызывая функцию ReadFile(), мы не знаем есть ли данные для чтения. Можно циклически проверять их наличие, но это приводит к дополнительным расходам времени ЦП. Поэтому на практике часто удобней использовать асинхронный режим. Для этого при вызове функции CreateFile() параметр dwFlagsAndAttributes должен быть равен FILE_FLAG_OVERLAPPED.

Далее, необходимо настроить реакцию порта на события при помощи функции SetCommMask() и используя функции WaitCommEvent() и WaitForSingleObject() ожидать событие или тайм аут. Например:

Сброс порта [ править ]

Пример настройки порта и выполнения чтения/записи данных [ править ]

Код для работы с COM-портом. Многострадальный, соответственно относительно простой и понятный, при этом обходит основные подводные камни. Надеюсь, может быть полезен.

Оцените статью