Автор: John Smith
Автор перевода: Савелий Бондини
Источник: csharp.simpleserial.com/
В данной статье рассматривается написание небольшого приложения для передачи данных через последовательный порт на языке C# c использованием .NET фреймворка. В состав .NET входит класс, предоставляющий средства для работы с последовательным портом, скрывающий в себе громоздкую реализацию и имеющий понятный и удобный интерфейс. Метод, описанный в этой статье можно с легкостью адаптировать под любой проект, где есть необходимость в последовательном соединении.
В программе имеется две кнопки (Start и Stop), а также элемент ввода текста - TextBox. Когда приложение запущено, чтобы открыть COM-порт необходимо нажать на кнопку Start. Когда порт открыт, входящие данные будут выводиться в TextBox. Вводимые в TextBox пользователем данные будут отправляться на последователный порт. Закрыть COM-порт можно с помощью кнопки Stop.
Создание приложения
Откройте Visual С# Express и выберите Файл -> Новый проект (File->New Project). Нажмите на иконку "Приложение Windows" (Windows Application) и назовите новый проект "Последовательное соединение" (поле ввода имени проекта находится внизу диалогового окна). Таким образом будет создана пустая форма (Form1) и скелет кода приложения.
Добавьте две кнопки к форме Form1 из окна инструментов (Toolbox palette). Выберите первую кнопку (button1). В окне свойств (Properties palette) задайте свойство кнопки Имя (Name) как "buttonStart", а свойство Текст (Text) на "Start". Аналогичные действия выполните для второй кнопки изменив свойства на "buttonStop" и "Stop" соответственно. Кроме того у второй кнопки (Stop) необходимо установить значение False для свойства Enable.
Далее добавьте элемент TextBox к форме. Задайте свойствам Multiline (многострочность) и ReadOnly (только чтение) этого элемента значение "True", а свойству ScrollBars (панель прокрутки) значение "Vertical" (вертикальная). Измените размер элемента TextBox и кнопок, чтобы они выглядели как на рисунке 1.
Теперь выделите мышкой кнопку Start. В окне свойств Properties нажмите на иконку Events (события) и найдите событие с именем "Click" и дважды кликните по нему мышкой. Это создаст скелет кода для обработки события клика мышкой по данной кнопке. Чуть позже мы добавим туда свой код, а пока вернитесь обратно к вкладке дизайнера формы, выделите мышкой кнопку Stop и создайте для нее событие "Click", как вы это сделали для кнопки Start. Используя тот же способ, для элемента TextBox создайте обработчик события "KeyPress" (нажатие клавиши клавиатуры), для элемента формы Form1 создайте обработчик события "FormClosing" (закрытие формы) и для последоватлельного порта обработчик события "DataReceived" (прием данных).
Далее скопируйте и вставте код из обработчиков событий из листинга ниже в пустые обработчики событий вашего проекта. Также скопируйте и вставте объявления переменных для RxString, убедившись, что они находятся перед началов функции Form1() как это показано в листинге. Наконец, полностью скопируйте и вставте функцию DisplayText() в свой проект.
Тестирование приложения
Будучи в редакторе Visual C# Express нажмите F5 (Run). Когда приложение запустится нажмите кнопку Start, чтобы открыть COM-порт. Входящие последовательные тектовые данные будут выводиться в элемент textBox1. Все, что вы печатаете в textBox1 будет передаваться в обратную сторону, через COM-порт. Если у вас нету подключенного последовательного устройства, подходящего для тестирования программы используйте кольцевой коннектор (loopback connector). Сделать его можно замкнув пины 2 и 3 последовательного кабеля или DB9F коннектора. С помощью loopback коннектора все, что вы печатаете в textBox1 будет отправлено обратно через порт и выведено обратно в textBox1. Чтобы закрыть порт нажмите кнопку Stop.
Если программа не работает, внимательно проверьте ваш код и последовательное соединение. В коде функции "buttonStart_Click()", убедитесь, что вы задали именно тот COM-порт, к которому пытаетесь подключиться. Он дожен физически находиться на вашем компьютере. Как правило порт называется "COM1", но он также может называться "COM2", "COM3" и т.д. Если порт подключен к внешнему последовательному устройству, COM-параметры (скорость передачи данных и т.д.) устройства должны соответствовать тем, что заданны в программе. Следует отметить, что в нашем приложение нету подтверждения соединения для COM-порта. Если внешнее устройство требует такое подтверждение требуется подправить параметры подключения.
Как это работает
Благодаря классу SerialPort, вся основная работа выполняется "за кулисами". Остальное интуитивно и просто. Единственным неясным местом является метод "Invoke", который позволяет функции "DisplayText()" обновлять textBox1. Давайте рассмотрим подробнее код каждого обработчика событий.
Методе buttonStart_Click() начинается с указания имени COM-порта и установки скорости передачи данных (Baud Rate). В нашем примере имя порта (PortName) "COM1", но вы можете назначить любое другое из тех, что доступно на вашем компьютере. Baud rate долженбыть такой же как и на устройстве с которым вы устанавливаете последовательное соединение. Далее мы вызывает функцию "Open()". Если порт успешно открыт, мы устанавливаем для кнопки Start неактивное состояние и делаем активной кнопку Stop, разрешая писать в textBox1.
Как только порт serialPort1 открыт, все входящие последовательные данные будут автоматические обрабатываться событим "DataReceived". Внутрие обработчика этого события мы считываем все входящие данные из внутреннего приемного буфера в строку RxString. Следующая часть является важной. Порт serialPort1 работает в отдельном потоке. Этот поток не может непосредственно вызывать функции в главном потоке нашего приложения. Это позволяет сделать специальный метод "Invoke()". Итак, мы используем Invoke(), чтобы вызвать функцию DisplayText(). RxString является глобальной переменной, доступной обоим потокам. Функция DisplayText() просто добавляет значение строки RxString к тому, что уже выведено в textBox1.
Обработчик события textBox1_KeyPress() передает, введенные в textBox1 данные, в последовательный порт SerialPort1. Функция Write() может передавать только символьные данные типа char, поэтому объявлен макссив размером [1], которому присваевается значение нажатой клавиши KeyChar. Аргументы функции Write() используются для отправки символлов из массива buff, используя нулевое смещение от начала массива и количество отправляемых символов равному [1]. В конце событие устанавливается как "Handled", чтобы введенный символ не выводился в textBox1.
Нажатие кнопки Stop вызывает функцию buttonStop_Click(). Если serialPort1 открыт, мы закрываем порт, устанавливаем состояние кнопки как неактивное, устанавливаем свойство "ReadOnly" для элемента textBox1. Если приложение закрывать до того, как закрыт порт serialPort1, то оно повиснет. Для этого предусмотрена функция Form1_FormClosing().