Visual studio управление com портом
Прошу помощи в понимании, а может и в решении интересующего меня вопроса.
Сначала обрисую суть поставленного передо мной задания, предупрежу сразу в программировании я, так сказать, очень молодой и это в какой-то степени мой первый проект, который я хочу реализовать на платформе visual studio.
Задача:
Есть некое устройство, которое соединяется с компьютером по RS-485 и передает данные 38400 бит/сек, устройство может передавать пакеты с дискретностью 25 Гц или 50Гц.
Командно-информационный пакет, передаваемый устройством, состоит из 6 блоков, в начале каждого пакета передается маркер начала пакета "0xFF, 0xFF", затем идут 6 блоков данных в конце пакета передается 2-х байтовое поле .В конце идет бит четности (формируется при выполнении операции "Исключающее ИЛИ "четное число логических единиц в байте должно соответствовать биту чётности 0 ) и 2 стоповых бита.
— Длина одного пакета 52 байта.
— Время паузы между двумя пакетами не более 2-х бит.
Характеристики блока данных:
— Длина блока 8 байт.
— Далее 4 значения по 2 байта
Собственно вопрос, который меня интересует: как это все правильно организовать.
Первым делом я кинулся искать как работать с COM-портом, наткнулся на пространство имен:
Ну, и первым делом, как мудрый ВАСЯ, определяю доступные порты в системе и вывожу их в combobox.
Далее, по кнопке старт я запускаю само чтение данных приходящих с устройства. Вот тут для меня начинается дремучий лес.
Теперь вопрос:
Как я понимаю эту проблему — в порт записываются данные, переданные устройством, а мне их необходимо считать.
Как мне правильно дождаться начала пакета "0xFF,0xFF", чтобы после это принимать оставшуюся часть пакета, или прием стоит начать после получения конца предыдущего пакета?
Если у кого-то есть подобные коды обработки ожидания начала или конца пакетов и нет желания объяснять, просьба скинуть участки кода буду разбираться сам.
После правильного начала приема пакетов мне их необходимо рассортировать, ничего лучше чем засунуть принятый пакет в переменную последовательности байт я не нашел, точнее это можно сказать единственное, что улеглось в моей голове.
Но приходит мне какая то ересь.
Правильно ли я понимаю этот процесс чтения из com-порта?
Просьба пнуть, ткнуть, дать леща или помочь в решении данного задания кому как будет угодно.
Кто знает что почитать конкретно по этому вопросу, где доступно написано или есть подобные решения просьба скинуть почитать что бы лучше разбираться.
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Represents a serial port resource.
Examples
The following code example demonstrates the use of the SerialPort class to allow two users to chat from two separate computers connected by a null modem cable. In this example, the users are prompted for the port settings and a username before chatting. Both computers must be executing the program to achieve full functionality of this example.
Remarks
Use this class to control a serial port file resource. This class provides synchronous and event-driven I/O, access to pin and break states, and access to serial driver properties. Additionally, the functionality of this class can be wrapped in an internal Stream object, accessible through the BaseStream property, and passed to classes that wrap or use streams.
The SerialPort class supports the following encodings: ASCIIEncoding, UTF8Encoding, UnicodeEncoding, UTF32Encoding, and any encoding defined in mscorlib.dll where the code page is less than 50000 or the code page is 54936. You can use alternate encodings, but you must use the ReadByte or Write method and perform the encoding yourself.
You use the GetPortNames method to retrieve the valid ports for the current computer.
If a SerialPort object becomes blocked during a read operation, do not abort the thread. Instead, either close the base stream or dispose of the SerialPort object.
Constructors
Initializes a new instance of the SerialPort class.
Initializes a new instance of the SerialPort class using the specified IContainer object.
Initializes a new instance of the SerialPort class using the specified port name.
Initializes a new instance of the SerialPort class using the specified port name and baud rate.
Initializes a new instance of the SerialPort class using the specified port name, baud rate, and parity bit.
Initializes a new instance of the SerialPort class using the specified port name, baud rate, parity bit, and data bits.
Initializes a new instance of the SerialPort class using the specified port name, baud rate, parity bit, data bits, and stop bit.
Fields
Indicates that no time-out should occur.
Properties
Gets the underlying Stream object for a SerialPort object.
Gets or sets the serial baud rate.
Gets or sets the break signal state.
Gets the number of bytes of data in the receive buffer.
Gets the number of bytes of data in the send buffer.
Gets a value indicating whether the component can raise an event.
Gets the state of the Carrier Detect line for the port.
Gets the IContainer that contains the Component.
Gets the state of the Clear-to-Send line.
Gets or sets the standard length of data bits per byte.
Gets a value that indicates whether the Component is currently in design mode.
Gets or sets a value indicating whether null bytes are ignored when transmitted between the port and the receive buffer.
Gets the state of the Data Set Ready (DSR) signal.
Gets or sets a value that enables the Data Terminal Ready (DTR) signal during serial communication.
Gets or sets the byte encoding for pre- and post-transmission conversion of text.
Gets the list of event handlers that are attached to this Component.
Gets or sets the handshaking protocol for serial port transmission of data using a value from Handshake.
Gets a value indicating the open or closed status of the SerialPort object.
Gets or sets the value used to interpret the end of a call to the ReadLine() and WriteLine(String) methods.
Gets or sets the parity-checking protocol.
Gets or sets the byte that replaces invalid bytes in a data stream when a parity error occurs.
Gets or sets the port for communications, including but not limited to all available COM ports.
Gets or sets the size of the SerialPort input buffer.
Gets or sets the number of milliseconds before a time-out occurs when a read operation does not finish.
Gets or sets the number of bytes in the internal input buffer before a DataReceived event occurs.
Gets or sets a value indicating whether the Request to Send (RTS) signal is enabled during serial communication.
Gets or sets the ISite of the Component.
Gets or sets the standard number of stopbits per byte.
Gets or sets the size of the serial port output buffer.
Gets or sets the number of milliseconds before a time-out occurs when a write operation does not finish.
Methods
Closes the port connection, sets the IsOpen property to false , and disposes of the internal Stream object.
Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object.
Discards data from the serial driver's receive buffer.
Discards data from the serial driver's transmit buffer.
Releases all resources used by the Component.
Releases the unmanaged resources used by the SerialPort and optionally releases the managed resources.
Determines whether the specified object is equal to the current object.
Serves as the default hash function.
Retrieves the current lifetime service object that controls the lifetime policy for this instance.
Gets an array of serial port names for the current computer.
Returns an object that represents a service provided by the Component or by its Container.
Gets the Type of the current instance.
Obtains a lifetime service object to control the lifetime policy for this instance.
Creates a shallow copy of the current Object.
Creates a shallow copy of the current MarshalByRefObject object.
Opens a new serial port connection.
Reads a number of bytes from the SerialPort input buffer and writes those bytes into a byte array at the specified offset.
Reads a number of characters from the SerialPort input buffer and writes them into an array of characters at a given offset.
Synchronously reads one byte from the SerialPort input buffer.
Synchronously reads one character from the SerialPort input buffer.
Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object.
Reads up to the NewLine value in the input buffer.
Reads a string up to the specified value in the input buffer.
Returns a String containing the name of the Component, if any. This method should not be overridden.
Writes a specified number of bytes to the serial port using data from a buffer.
Writes a specified number of characters to the serial port using data from a buffer.
Writes the specified string to the serial port.
Writes the specified string and the NewLine value to the output buffer.
Events
Indicates that data has been received through a port represented by the SerialPort object.
Occurs when the component is disposed by a call to the Dispose() method.
Indicates that an error has occurred with a port represented by a SerialPort object.
Indicates that a non-data signal event has occurred on the port represented by the SerialPort object.
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Представляет ресурс последовательного порта.
Примеры
В следующем примере кода показано использование класса, позволяющее SerialPort двум пользователям общаться с двух отдельных компьютеров, подключенных с помощью кабеля модема NULL. В этом примере пользователям предлагается ввести параметры порта и имя пользователя перед чатом. Оба компьютера должны выполнять программу, чтобы обеспечить полную функциональность этого примера.
Комментарии
Используйте этот класс для управления ресурсом файла последовательного порта. Этот класс предоставляет синхронный и управляемый событиями операции ввода-вывода, доступ к состояниям закрепления и прерывания и доступ к свойствам последовательного драйвера. Кроме того, функциональные возможности этого класса могут быть упакованы во внутренний Stream объект, доступный через BaseStream свойство, и передаваться в классы, которые переносят или используют потоки.
Класс SerialPort поддерживает следующие кодировки: ASCIIEncoding, , UTF8EncodingUnicodeEncoding, UTF32Encodingи любая кодировка, определенная в mscorlib.dll где кодовая страница меньше 50000 или кодовая страница составляет 54936. Вы можете использовать альтернативные кодировки, но необходимо использовать ReadByte или Write метод и выполнить кодирование самостоятельно.
Метод используется GetPortNames для получения допустимых портов для текущего компьютера.
SerialPort Если объект блокируется во время операции чтения, не прерывайте поток. Вместо этого закройте базовый поток или удалите SerialPort объект.
Конструкторы
Инициализирует новый экземпляр класса SerialPort.
Инициализирует новый экземпляр класса SerialPort, используя указанный объект IContainer.
Инициализирует новый экземпляр класса SerialPort, используя указанное имя порта.
Инициализирует новый экземпляр класса SerialPort, используя указанное имя порта и скорость передачи в бодах.
Инициализирует новый экземпляр класса SerialPort, используя указанное имя порта, скорость передачи в бодах и бит четности.
Инициализирует новый экземпляр класса SerialPort, используя указанное имя порта, скорость передачи в бодах, бит четности и биты данных.
Инициализирует новый экземпляр класса SerialPort, используя указанное имя порта, скорость передачи в бодах, бит четности, биты данных и стоп-бит.
Указывает, что отсчет времени ожидания не производится.
Свойства
Возвращает базовый объект Stream для объекта SerialPort.
Возвращает или задает скорость передачи для последовательного порта (в бодах).
Получает или задает состояние сигнала разрыва.
Возвращает число байтов данных, находящихся в буфере приема.
Получает число байтов данных, находящихся в буфере отправки.
Возвращает значение, показывающее, может ли компонент вызывать событие.
Получает состояние линии обнаружения несущей для порта.
Возвращает объект IContainer, который содержит коллекцию Component.
Возвращает состояние линии готовности к приему.
Возвращает или задает стандартное число битов данных в байте.
Возвращает значение, указывающее, находится ли данный компонент Component в режиме конструктора в настоящее время.
Возвращает или задает значение, показывающее, игнорируются ли пустые байты (NULL), передаваемые между портом и буфером приема.
Получает или задает состояние сигнала готовности данных (DSR).
Получает или задает значение, включающее поддержку сигнала готовности терминала (DTR) в сеансе последовательной связи.
Получает или задает кодировку байтов для преобразования текста до и после передачи.
Возвращает список обработчиков событий, которые прикреплены к этому объекту Component.
Возвращает или задает протокол установления связи для передачи данных через последовательный порт с использованием значения Handshake.
Возвращает значение, указывающее открытое или закрытое состояние объекта SerialPort.
Возвращает или задает значение, используемое для интерпретации окончания вызова методов ReadLine() и WriteLine(String).
Возвращает или задает протокол контроля четности.
Возвращает или задает байт, которым заменяются недопустимые байты потока данных при обнаружении ошибок четности.
Получает или задает последовательный порт, в частности, любой из доступных портов COM.
Возвращает или задает размер входного буфера SerialPort.
Получает или задает срок ожидания в миллисекундах для завершения операции чтения.
Возвращает или задает число байтов во внутреннем входном буфере до возникновения события DataReceived.
Возвращает или задает значение, показывающее, включен ли сигнал запроса передачи (RTS) в сеансе последовательной связи.
Получает или задает ISite объекта Component.
Получает или задает стандартное число стоповых битов в байте.
Возвращает или задает размер выходного буфера последовательного порта.
Получает или задает срок ожидания в миллисекундах для завершения операции записи.
Методы
Закрывает соединение порта, присваивает свойству IsOpen значение false и уничтожает внутренний объект Stream.
Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для взаимодействия с удаленным объектом.
Удаляет данные из буфера приема последовательного драйвера.
Удаляет данные из буфера передачи последовательного драйвера.
Освобождает все ресурсы, занятые модулем Component.
Освобождает неуправляемые ресурсы, используемые объектом SerialPort, а при необходимости освобождает также управляемые ресурсы.
Определяет, равен ли указанный объект текущему объекту.
Служит хэш-функцией по умолчанию.
Извлекает объект обслуживания во время существования, который управляет политикой времени существования данного экземпляра.
Получает массив имен последовательных портов для текущего компьютера.
Возвращает объект, представляющий службу, предоставляемую классом Component или классом Container.
Возвращает объект Type для текущего экземпляра.
Получает объект службы времени существования для управления политикой времени существования для этого экземпляра.
Создает неполную копию текущего объекта Object.
Создает неполную копию текущего объекта MarshalByRefObject.
Открывает новое соединение последовательного порта.
Считывает из входного буфера SerialPort определенное число байтов и записывает их в байтовый массив, начиная с указанной позиции.
Считывает из входного буфера SerialPort определенное число символов и записывает их в символьный массив, начиная с указанной позиции.
Считывает из входного буфера SerialPort один байт в синхронном режиме.
Считывает из входного буфера SerialPort один символ в синхронном режиме.
Считывает все непосредственно доступные байты в соответствии с кодировкой из потока и из входного буфера объекта SerialPort.
Считывает данные из входного буфера до значения NewLine.
Считывает из входного буфера строку до указанного значения value .
Возвращает объект String, содержащий имя Component, если оно есть. Этот метод не следует переопределять.
Записывает указанное число байтов в последовательный порт, используя данные из буфера.
Записывает указанное число символов в последовательный порт, используя данные из буфера.
Записывает указанную строку в последовательный порт.
Записывает указанную строку и значение NewLine в выходной буфер.
События
Указывает, что данные были получены через порт, представленный объектом SerialPort.
Возникает при удалении компонента путем вызова метода Dispose().
Указывает, что произошла ошибка с портом, представленным объектом SerialPort.
Указывает, что для порта, представленного объектом SerialPort, возникло событие сигнала, не связанного с данными.
Сограждане, применяющие микроконтроллеры, часто испытывают потребность использования функций обмена по интерфейсу RS-232. Для этого надо уметь программировать и писать обслуживающие программы уже не только для микроконтроллеров, а и для персональных компьютеров.
В приложении - готовый, написанный мною открытый проект, который можно использовать в своих работах как образец-заготовку. Проект небольшой, так что его легко будет освоить, затем дополнить и расширить его функциями, в общем, использовать по своему усмотрению.
Содержание / Contents
Камрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.
При запуске программы PR14_RS-232.exe непосредственно или через оболочку MSVS2010 появится следующее основное окно, что на следующем рисунке.
Все принятые коды выводятся в аналогичном формате в окне «Принятый код», при этом размер принятого кода может быть достаточно большим, и в этом случае дополнительно появляется полоса прокрутки.
То есть используя данную программу можно обмениваться через СОМ1 со скоростью 9600 бит/с, что вполне достаточно для многих приложений при работе с микроконтроллерами.
↑ А что же внутри программы, каков исходный код?
Рассмотрим некоторые особенности и функции кода в этом файле Form1.cs.
В самом начале файла, основные подключения через директивы using, без которых ничего работать не будет. Последние из них, что с комментариями, необходимы для работы с СОМ портом и таймером. По поводу таймера, СОМ порт может обходиться и без него, таймер добавлен для последующего улучшения пользовательского интерфейса.
Создание СОМ порта обеспечивают следующие строки в class Form1. Здесь же видно, что обмениваться данными будем через СОМ1, но легко можно задать и другие.
Кстати, если скорость и другие параметры не устраивают, то их меняем подобно следующему:
В основной функции public Form1() четыре строки. Первая формирует основную форму с кнопками и окошками, это стандартная строка, которая всегда создается автоматически. Следующие две строки создают обработчик прерываний для обменов по СОМ порту и отрывают сам СОМ порт. Четвертая строка выводит шаблон из шести байт в окно выдачи, к которому можно сделать привязку и, конечно, изменить.
В обработчике приема void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) имеется две строки, одна в самом начале, а другая в конце. Эти строки необходимы для синхронизаций, их обязательно надо применять. Управление передается обработчику, как только во входном буфере СОМ порта появляются принятые данные. Для считывания данных применяется следующие три строки. Здесь принятые коды считываются в байтовый буфер buffer.
Очередные следующие за ними три строки выводят данные в окно «Принятый код». Таким образом, в этом обработчике осуществляется прием по RS-232 и побайтный вывод принятого кода, а между байтами вставляются пробелы, что улучшает их обзор.
Где в последней строке, bytes – это сам подготовленный массив байт для выдачи, а bytes.Length – число выдаваемых в СОМ порт байт. Данный обработчик использует еще функцию private byte STB(char ch), служащую для преобразования знаковых символов в числа.
При нажатии кнопок «Очистить» работают обработчики private void button3_Click(object sender, EventArgs e) и private void button2_Click(object sender, EventArgs e), основная задача которых очистка окон приема и выдачи.
Вот такая небольшая программка.
↑ Файлы
↑ Немного о себе
Я занимаюсь схемо-техникой с применением микроконтроллеров. Их было у меня достаточно много: это Intel 8080, 8051, 196, Atmel AT90, AVR, ATtiny и megaAVR, Silabs, а также NiosII. Их я программировал на ассемблере и С, и связывал с персональным компьютером по интерфейсу RS-232 на подобных программах, ну и с более сложным функционалом.
Последовательные порты полюбились разработчикам за их простоту в обслуживании и использовании.
И конечно же писать в консоль терминальной программы это всё хорошо, но хочеться своё приложение, которое по нажатии клавиши на экране выполняет нужные вам действия ;)
В этой статье опишу как работать с com портом на языке Си++.
Решение простое, но почемуто рабочий пример найден был не сразу. За сим сохраняю его тут.
Конечно вы можете использовать кроссплатформенные решения вроде QSerial - библиотеки в составе Qt, я наверное так и сделаю, но в будующем. Сейчас же речь о "чистом" виндовском C++. Писать будем в Visual Studio. У меня 2010, хотя роли это никакой не играет.
Создаём новый консольный Win32 проект.
Инклудим header файлы:
Объявляем обработчик com порта:
Я делаю это глобально, чтобы не заморачиваться с указателями при передаче его в функции.
Дальше начинаем формировать функцию main:
Терпеть не могу виндовский стиль программирования. Обозвали всё посвоему и сидят радуются.
Теперь магия объявления строки с именем порта. Дело в том, что char оно преобразовывать само не умеет.
Работа с последоавательными портами в Windows проходит как с файлом. Открываем первый ком порт для записи/чтения:
Теперь нужно настроить параметры соединения:
На msdn советуют сначала получить параметры, а затем менять их. Мы ещё только учимся, поэтому делаем как просят.
Теперь объявим строку, которую будем передавать и переменные необходимые для этого:
Посылаем строку. Напомню, что пример простейший, поэтому никаких особо проверок я не делаю:
Также я решил вывести для контроля размер строки и количество отосланных байт:
В конце программы делаем бесконечный цикл чтения данных:
Теперь функция чтения:
Вот собственно и весь пример.
Я создал виртуальный com порт. И слал из COM1 в COM2:
Из нашей программы было отправлено "Hello from C++", а из терминала "hello how2.org.ua".
Читайте также: