Визуальная электроника

Эта статья показывает, как записывать и читать данные от устройства, подключенного к последовательному порту (COM-порт) из приложения на языке C# в среде .NET. В этой статье мы создадим class RS485Server для работы с нашим газоанализатором по интерфейсу RS485. В недалеком прошлом для работы с Serial Port в среде .Net 1.1, мы должны были использовать либо Windows API, либо использовать управление из сторонних библиотек. В среде .Net 2.0 (и в более поздних версиях .NET) компания Microsoft добавила поддержку последовательного порта включением класса SerialPort как части пространства имен System.IO.Ports. Реализация класса RS485Server сделана очень прямо и очевидно. Для начала опишем используемые классом переменные:

C# Code:
  1. SerialPort _serialPort;
  2. // Статус клиента
  3. private bool client_running;
  4. private int loc_req;
  5. // Статус приемника
  6. private string returnData = "";
  7. private bool start_ok = false;
  8. private bool parse_ok = false;

На следующем этапе реализуем функцию Connect, отвечающую за открытие нашего com порта:

C# Code:
  1. public bool Connect(string Name, int Speed)
  2. {
  3. client_running = false;
  4. _serialPort = new SerialPort(Name,
  5. Speed,
  6. Parity.None,
  7. 8,
  8. StopBits.One);
  9. _serialPort.Handshake = Handshake.None;
  10. _serialPort.WriteTimeout = 50;
  11. _serialPort.ReadTimeout = 50;
  12. _serialPort.DataReceived += new SerialDataReceivedEventHandler(Receiver);
  13. try
  14. {
  15. _serialPort.Open();
  16. }
  17. catch (Exception ex)
  18. {
  19. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  20. }
  21.  
  22. if (_serialPort.IsOpen)
  23. {
  24. client_running = true;
  25. }
  26. else
  27. {
  28. MessageBox.Show(
  29. "Не могу открыть порт!",
  30. "Ошибка",
  31. MessageBoxButtons.OK,
  32. MessageBoxIcon.Information,
  33. MessageBoxDefaultButton.Button1,
  34. MessageBoxOptions.DefaultDesktopOnly);
  35. }
  36.  
  37. return client_running;
  38. }

Как видите функция получилась достаточно простой. В качестве аргументов она принимает имя com порта и требуюмую скорость. Для определения существующих com портов удобно пользоваться следующей конструкцией:

C# Code:
  1. string[] portnames = System.IO.Ports.SerialPort.GetPortNames();
  2. domainUpDown1.Items.Clear();
  3. foreach (string port in portnames)
  4. {
  5. domainUpDown1.Text = port;
  6. domainUpDown1.Items.Add(port);
  7. }

Для приема данных нам нужно создать обработчик события EventHandler для "SerialDataReceivedEventHandler". В качестве этого приемника будет выступать метод Receiver:

C# Code:
  1. public void Receiver(object sender, SerialDataReceivedEventArgs e)
  2. {
  3. if (client_running == true)
  4. {
  5. if (_serialPort.IsOpen)
  6. {
  7. SerialPort sp = (SerialPort)sender;
  8. int buferSize = sp.BytesToRead;
  9. for (int i = 0; i < buferSize; ++i)
  10. {
  11. // читаем по одному байту
  12. char bt = (char)sp.ReadByte();
  13.  
  14. if (bt == '{' && start_ok == false) { start_ok = true; returnData = ""; }
  15.  
  16. if (start_ok == true)
  17. {
  18. returnData = returnData + bt.ToString();
  19. }
  20.  
  21. if (bt == '}' && start_ok == true) { start_ok = false; parse_ok = true; }
  22. }
  23.  
  24. if (parse_ok == true)
  25. {
  26. parse_ok = false;
  27. Console.WriteLine("RS485 --> " + returnData.ToString());
  28. try
  29. {
  30. if (loc_req == 1)//GET Device
  31. {
  32. Ans_Device newDevice = JsonConvert.DeserializeObject(returnData);
  33. Form1.myForm.Device1.DrawDeviceData(newDevice);
  34. newDevice = null;
  35. }
  36. }
  37. catch (Exception ex)
  38. {
  39. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  40. }
  41. }
  42. }
  43. }
  44. }

Мы уже писали про использование формата JSON для общения наших устройств с серверным ПО. По этому в потоке происходит чтение данных с нашего com порта, и поиск данных заключенных в фигурные скобки { }. Далее для десериализации принятых данных используется компонент JsonConvert Class. Использовать его достаточно просто, для парсинга принятых данных, необходимо создать класс, соответствующий нашему запросу:

C# Code:
  1. //Класс ответа девайса
  2. public class Ans_Device
  3. {
  4. public string ANSWER { get; set; }
  5. public string NAME { get; set; }
  6. public int SENSORS { get; set; }
  7. public byte RS485_ADRESS { get; set; }
  8. public int[] IP_ADDRESS { get; set; }
  9. public int[] NETMASK { get; set; }
  10. public int[] GATEWAY { get; set; }
  11. }

Для десеарилизации наших данных достаточно создать экземпляр класса Ans_Device с нашими десериализованными данными:

C# Code:
  1. Ans_Device newDevice = JsonConvert.DeserializeObject(returnData);

Для завершения создания нашего класса осталось реализовать два простых метода. Первый, это метод Send, отправляющий данные в com порт:

C# Code:
  1. public void Send(string datagram, int request)
  2. {
  3. loc_req = request;
  4. _serialPort.Write(datagram.ToString());
  5. Console.WriteLine("RS485 <-- " + datagram.ToString());
  6. }

Второй, это метод Close, закрывающий наш порт, если он открыт:

C# Code:
  1. public void DisConnect()
  2. {
  3. try
  4. {
  5. if (_serialPort.IsOpen)
  6. {
  7. client_running = false;
  8. Thread.Sleep(500);
  9. _serialPort.Close();
  10. }
  11. }
  12. catch (Exception ex)
  13. {
  14. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  15. }
  16. }

Ниже можно наблюдать видео работы получившегося класса.

Комментарии  
Здравствуйте! Меня зовут Даниил. Ваш сайт - v2020e.ru, очень заинтересовал меня. Я готов предложить Вам выгодную цену. Если мое предложение заинтересует Вас, я бы хотел попросить открыть доступ к метрике на мой аккаунт - Daniil89217894501@yandex.ru. Я уверен в том, что мы сможем достичь взаимовыгодного соглашения. Для обеспечения безопасной сделки, я предлагаю воспользоваться биржей Telderi. Буду признателен за ответ и дальнейшее обсуждение нашей потенциальной сделки. С уважением, Даниил. Контакты для связи: 8 (921) 789-45-01 мобильный номер https://t.me/Danya_spb_ru телеграм Daniil89217894501@yandex.ru эл. почта
Добавить комментарий