ISSN 1991-3087
Рейтинг@Mail.ru Rambler's Top100
Яндекс.Метрика

НА ГЛАВНУЮ

Последовательная связь с использованием WPF, RS232 и микроконтроллера

 

Петряев Вячеслав Евгеньевич,

студент кафедры автоматизации производственных процессов Уральского государственного лесотехнического университета.

 

Эта статья покажет, как использовать последовательную передачу данных через RS232, используя технологию Microsoft WPF. Я не хочу останавливаться на внешнем виде программы, а уделить большее внимание коду. В частности есть ключевые пункты, такие как Dispatcher.Invoke метод и преобразование символов их из ASCII в 16 систему счисления, что является камнями преткновения в последовательной связи с микроконтроллером.

Ключевые слова: WPF, COM порт, RS232, C#.

Keywords: WPF, Serial Port, RS232, C#.

 

Следует начать с того, что нужно показать, как создать приложение. Чтобы создать проект для приложения:

1.                  Запустите Visual Studio 2010.

2.                  В меню File («Файл») выберите команду New («Создать»), а затем команду New Project («Проект»).

 

Рис. 1. Выбор меню создания проекта.

 

3.                  Откроется диалоговое окно New Project («Создание проекта»).

 

Рис. 2. Диалоговое окно создания проекта

Примечание. В поле со списком Target Framework Version («Целевая версия платформы») по умолчанию выбрано последнее использованное значение. При создании проекта убедитесь в том, что выбрана нужная версия платформы.

Шаг 1. Выберите язык в нашем случае C#, а затем выберите пункт Windows.

Шаг 2. Выберите пункт WPF Application («Приложение WPF»).

Шаг 3. Введите имя проекта.

Совет. Хотя в имени проекта можно использовать пробелы, делать это не рекомендуется.

Шаг 4. Нажмите кнопку ОК, чтобы создать новое приложение WPF.

 

 

Присвоим приложению заголовок. Свойство Title находится в верхней левой части хрома окна. [1]

Теперь можно начинать создавать приложение. Код написан просто, с небольшим вниманием на обозначения. Во-первых, начнем с интерфейса. Сперва сделаем 2 ComboBox для выбора номера COM порта и скорости передачи, а так же разместим TextBox для данных, которые нужно отправить, и Richtextbox для отображения полученной информации из COM порта, и пару кнопок для действий.

Первый важный фактор – то, откуда будут получены номера COM портов и скорость. Есть способы, с помощью которых можно получить эти данные от компьютера, но для большего контроля поместим все названия в файл XML по имени CommsData.xml. Эти данные обеспечены “Источником данных” и размещены в предалах Windows.Resource элемента. XPath показывает какой элемент выбран, а x:Key – то, на что я ссылаюсь в коде.

<Window.Resources>

 <XmlDataProvider x:Key="ComPorts" Source="CommsData.xml" XPath="/Comms/Ports" />

 <XmlDataProvider x:Key="ComSpeed" Source="CommsData.xml" XPath="/Comms/Baud" />

</Window.Resources>

Приведем содержание CommsData.xml.

<Comms>

 <Ports>COM1</Ports>

 <Baud>921600</Baud>

</Comms>

Так можно дописать сколько нужно строк с нужными названиями COM портов и скоростей.

В каждом элементе ComboBox нужно указать место, откуда он будет брать информацию. В нашем случае это xml файл. Для выбора порта:

<ComboBox Name="Comm_Port_Names” ItemsSource="{Binding Source={StaticResource ComPorts}}"/>

Для выбора скорости:

<ComboBox Name="Baud_Rates" ItemsSource="{Binding Source={StaticResource ComSpeed}}"/>

С интерфейсом закончили и можно приступать к добавлении функциональности.

Во-первых, мы должны добавить ссылку на библиотеку IO.PORTS, которая содержит команды для управления COM портом.

using System.IO.Ports;

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

SerialPort serial = new SerialPort();

Есть несколько свойств последовательного порта, которые можно редактировать. Это происходит в рамках исходного кода перед нажатием кнопки Connect. Главное их установить до открытия порта.

serial.PortName = Comm_Port_Names.Text; //Com Port Name

serial.BaudRate = Convert.ToInt32(Baud_Rates.Text);

serial.Handshake = System.IO.Ports.Handshake.None;

serial.Parity = Parity.None;

serial.DataBits = 8;

serial.StopBits = StopBits.One;

serial.ReadTimeout = 200;

serial.WriteTimeout = 50;

Информацию об этих свойствах смотрите в RS232 протоколе. Эти параметры удовлетворяют в большинстве случаев. Есть два важных свойства. ReadTimeout – это свойство устанавливает максимальное времяЮ которое программа читает данные с порта от начала приема. Если сделать его маленьким, то могут возникать ошибки и сообщение может быть укорочено. WriteTimeout – время, отведенное для отправки данных через порт.

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

serial.DataReceived+=new SerialDataReceivedEventHandler(Recieve);

Будем записывать данные в строку

String recieved_data;

А затем вызовем функцию этих данных в нашу форму. Что бы это сделать вначале нужно подключить еще одну библиотеку:

using System.Windows.Threading;

private void Recieve(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

{

 recieved_data = serial.ReadExisting();

 Dispatcher.Invoke(DispatcherPriority.Send,

            new UpdateUiTextDelegate(WriteData), recieved_data);

}

Сейчас мы должны использовать Dispatcher.Invoke метод. Его цель проста: главная форма находится под контролем своего потока; когда последовательный порт объявляет о получении данных, создается новый поток, чтобы прочитать эти данные. Этот метод позволяет передать нашу строку из одного потока в другой без ошибок.

Данные могут быть отображены в любом элементе, способном отображать текст. В нашем случае это RichTextBox. Сперва нужно создать абзац.

FlowDocument mcFlowDoc = new FlowDocument();

Paragraph para = new Paragraph();

Вот так выглядит функция для отображения данных:

private void WriteData(string text)

{

 para.Inlines.Add(text);

 mcFlowDoc.Blocks.Add(para);

 Commdata.Document = mcFlowDoc;

}

Отправка данных. Для общения с микроконтроллером данные необходимо преобразовать в 16 систему. Текст, набранный в SerialData TextBox запускает функцию SerialCmdSend.Во-первых нужно проверить открыт ли порт. Во-вторых преобразовать данные в 16 систему.

private void Send_Data(object sender, RoutedEventArgs e)

 {

 SerialCmdSend(SerialData.Text);

 SerialData.Text = "";

 }

 public void SerialCmdSend(string data)

 {

 if (serial.IsOpen)

  {

  try

   {

   byte[] hexstring = Encoding.ASCII.GetBytes(data);

   foreach (byte hexval in hexstring)

   {

  byte[] _hexval = new byte[] { hexval };

  serial.Write(_hexval, 0, 1);

  Thread.Sleep(10);

  }

 }

 catch (Exception ex)

 {

 para.Inlines.Add("Ошибка отправки" + data + "\n" + ex + "\n");

 mcFlowDoc.Blocks.Add(para);

 Commdata.Document = mcFlowDoc;

  }

 }

 else

 {

 }

}

Вот что получается в итоге:

 

 

Если вы студент и у вас нет Visual studio, то вы можете получить его бесплатно на сайте dreamspark.ru.

Все. Сейчас вы имеете рабочее WPF приложение, способное работать с портом последовательной связи. Имея эти знания, вы можете начать разрабатывать, например, свою SCADA систему.

 

Литература

 

1.                  «Создание первого приложения WPF». - http://msdn.microsoft.com/ru-ru/netframework/ff934691.

2.                  Библиотека MSDN. - http://msdn.microsoft.com/library/ms123401.

 

Поступила в редакцию 12.09.2011 г.

2006-2019 © Журнал научных публикаций аспирантов и докторантов.
Все материалы, размещенные на данном сайте, охраняются авторским правом. При использовании материалов сайта активная ссылка на первоисточник обязательна.