- How to read serial port data?
- What does RS232 stand for?
- How to read data from a serial port?
- Serial Port Monitor by Eltima Software
- Serial Port Monitor
- Main features of Serial Port Reader for Windows:
- • Reading COM port activity
- • Working with multiple ports in one session
- • Multiple views for sniffed data
- • Emulating serial communication
- • Capturing Modbus data
- • Repetitive data exchange
- Steps to capture serial port data on Windows with COM Port Reader
- The RS232 Connection and Signals
- • DTE and DCE
- • DB-9 to DB-25 Conversion
- • RS-232 Connections
- • RS-232 Signals
- Работа с COM портом на C++ в Windows
- COM-порт в Windows (программирование)
- Содержание
- Открытие порта [ править ]
- lpFileName [ править ]
- dwDesiredAccess [ править ]
- dwShareMode [ править ]
- lpSecurityAttributes [ править ]
- dwCreationDistribution [ править ]
- dwFlagsAndAttributes [ править ]
- hTemplateFile [ править ]
- Закрытие порта [ править ]
- Пример открытия/закрытия на языке C [ править ]
- Структура DCB [ править ]
- DCBlength [ править ]
- BaudRate [ править ]
- fBinary [ править ]
- fParity [ править ]
- fOutxCtsFlow [ править ]
- fOutxDsrFlow [ править ]
- fDtrControl [ править ]
- fDsrSensitivity [ править ]
- fTXContinueOnXoff [ править ]
- fOutX [ править ]
- fInX [ править ]
- fErrorChar [ править ]
- fNull [ править ]
- fRtsControl [ править ]
- fAbortOnError [ править ]
- fDummy2 [ править ]
- wReserved [ править ]
- XonLim [ править ]
- XoffLim [ править ]
- ByteSize [ править ]
- Parity [ править ]
- StopBits [ править ]
- XonChar [ править ]
- XoffChar [ править ]
- ErrorChar [ править ]
- EofChar [ править ]
- EvtChar [ править ]
- wReserved1 [ править ]
- Замечания [ править ]
- Заполнение структуры DCB [ править ]
- Структура COMMTIMEOUTS [ править ]
- Заполнение структуры COMMTIMEOUTS [ править ]
- Пример настройки порта [ править ]
- Структура COMMPORT [ править ]
- Стандартный диалог настройки порта [ править ]
- Выделение памяти для структуры COMMPORT [ править ]
- Прием и передача данных [ править ]
- Сброс порта [ править ]
- Пример настройки порта и выполнения чтения/записи данных [ править ]
How to read serial port data?
This article is intended to help you understand the basics of the hardware and software (protocol) standards for RS232. It will also show you how to use the COM port reader software to read data traveling through RS232 devices in real time.
What does RS232 stand for?
Serial ports, also known as RS232 ports, are an interface used for serial communication that transmits a single bit at a time. COM or communications ports are other names for serial ports.
The use of serial ports has declined with the development of USB and other high-speed solutions, but they still are used in some very important applications. Serial ports are instrumental in the operation of industrial automation systems and are often used to connect lab equipment and other scientific instruments to computers and networks.
It is imperative that you regularly monitor and analyze serial port activity when working with serial devices. You want to be able to see traffic flowing in both directions from your RS232/422/485 ports. This could be event notifications from apps, status messages or other information that enables you to troubleshoot the equipment if necessary and can serve as a guide for installing new devices.
How to read data from a serial port?
There is no specific operating system tool or function that allows you to read serial ports in Windows. But there is a solution, as the software is available that can check, monitor and analyze RS232 port activity. It gives you a tool for Windows that can read COM ports.
Serial Port Monitor by Eltima Software
Serial Port Monitor
COM Port Reader is a professional-grade software tool that should be your first choice when seeking an answer to the question of how to read data from RS232 ports. The tool allows you to send commands or other information to COM-based devices or RS232 applications in a variety of formats (string, binary, octal, decimal, hexadecimal, mixed). The returned responses can be monitored and saved in a single log file that employs the first-in-first-out method. Serial Port Reader also lets you redirect serial port output a file or the clipboard, so it is available for further analysis at any time.
Main features of Serial Port Reader for Windows:
• Reading COM port activity
This software utility allows you to read RS232 data from a designated port and monitor it even if another application had already opened it. Captured serial data can be displayed in various formats, and the opportunity of real-time monitoring is a great feature for problem resolution.
The received data can be saved to a file of your choice or copied to the clipboard. The tool displays and files input/output control codes (IOCTLs) along with their complete parameters. Sessions can be saved by Com Port Reader and can be reloaded if required.
• Working with multiple ports in one session
Multiple serial ports can be read simultaneously by this software tool. This feature is very useful when comparing data collected from different COM ports that are interacting with the same application within monitoring session. In this case, all data is received and stored in a single log file on a first-in-first-out basis.
• Multiple views for sniffed data
Serial Port Reader allows you to choose the way that collected data is displayed on your computer. Four different view are available: table, line, dump, or terminal. You have the option of monitoring all view modes at the same time.
• Emulating serial communication
An option in terminal mode allows simulated data transmission from a serial application to a monitored COM port. Various data formats, such as string, binary, octal, decimal, hexadecimal, or mixed, can be used to test the COM port or its attached device’s reactions.
• Capturing Modbus data
COM Port Reader’s powerful filters enable you to read serial data transmitted over Modbus RTU and Modbus ASCII. The utility is fully compatible with these protocols, as well as those employed in RS-232, RS-485, and RS-422 interfaces
• Repetitive data exchange
Sending the same command from a serial app to a monitored serial port multiple times can give a clearer picture of the port’s behavior. This serial port utility simplifies that task with a playback feature that can display differences between sessions automatically.
Steps to capture serial port data on Windows with COM Port Reader
This how to read serial port data and collect it using COM Port Reader. First, you need to download the tool, install and launch it. Then you need to start a monitoring session like this:
- In Serial Port Reader go to the “Main menu”, choose “Session -> New session”. Alternately, you can click on the “New” icon on the main toolbar or press “Ctrl + N”. This invokes the “New monitoring session” screen.
- Select which view modes that you want displayed during your monitoring session:
Table view – recorded IRPs are displayed in the form of the table
Line view – requests passed through a particular serial line are displayed along with details
Dump view – shows data passed through the serial line
Terminal view – all received data is displayed in ASCII characters on a text console.
Modbus view displays received and sent Modbus data (RTU and ASCII).
“Select all” and “Select none” button are there to simplify your selections.
Choose, whether you would like to “Start monitoring now” or “Start in new window” for the immediate behavior of a new session.
In “Capture options” you can specify the events you are interested in capturing – Create/Close, Read/Write, Device Control.
Click “Start monitoring” to activate the session. A new monitoring window will be displayed.
Give your session a meaningful name so you can return to it for later analysis
The RS232 Connection and Signals
• DTE and DCE
DTE stands for Data Terminal Equipment. An example of a DTE is a computer. DCE stands for Data Communication Equipment. A modem is an excellent example of a DCE.
A DTE normally comes with a Male Connector, while a DCE comes with a Female Connector. This is not always the case. Here is a simple test to confirm device type. Using a voltmeter, measure Pin 3 and Pin 5 of a DB-9 Connector. DTE devices will indicate a voltage of -3V to -15V. DCE devices will have the voltage on Pin 2.
Note: The result for a DB-25 Connector is reversed (Please refer to DB-9 to DB-25 conversion table below).
• DB-9 to DB-25 Conversion
• RS-232 Connections
Straight-through cables are used to connect a DTE (e.g. computer) to a DCE (e.g. modem), with all signals in one side connected to the corresponding signals in the other side in a corresponding one-to-one basis. When connecting two DTE devices directly with no modem in between, a crossover, or null-modem cable is used. This type of cable cross transmits and receives data signals between the two sides. There is no standard and many variations on how the other control signals are wired. Below is an example of one of them:
• RS-232 Signals
The graphic above illustrates a typical RS-232 logic waveform (Data format: 1 Start bit, 8 Data bits, No Parity, 1 Stop bit). Data transmission begins with a Start bit, followed by the data bits (LSB sent first and MSB sent last), and ends with a «Stop» bit.
The voltage of Logic «1» (Mark) is between -3VDC to -15VDC, while the Logic «0» (Space) is between +3VDC to +15VDC.
RS-232 connects the Ground of 2 different devices together, which is the so-called «Unbalanced» connection. Unbalanced connections have a distance limitation of 50 ft (approximately 15 meters) and are very susceptible to noise.
Работа с 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» и так далее.
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.
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 ).
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-портом. Многострадальный, соответственно относительно простой и понятный, при этом обходит основные подводные камни. Надеюсь, может быть полезен.