Ricky Castle Ответов: 1

Как опросить последовательный порт и отправить команды


Здравствуйте, я пытаюсь разработать интерфейс, который автоматически отправляет запросы на последовательный порт. Я также хотел бы посылать определенные команды по своему желанию.

Пожалуйста, смотрите код ниже. Прошу прощения, если это выглядит неряшливо. Я все еще учусь.

- Форма загружается и подключается к последовательному порту - готово, с ручными кнопками подключения и отключения, а также
- Опрос последовательности запросов и чтение ответов - (я сделал это вручную на двух отдельных запросах с помощью одного нажатия кнопки, с thread.sleep(100) (не уверен, что это эффективно)
- Отображение ответов в соответствующих им текстовых полях (также выполняется вручную из двух отдельных запросов, преобразованных в float для отображения на семисегментном элементе управления). Сбой, если я делаю только один запрос, я думаю, из-за события datareceived. Как с этим справиться?


- Отбрасывать ответы от последовательного порта при отправке "команды" по сравнению с "запросом"- ?????



Моя конечная цель-создать интерфейс "реального времени", который постоянно запрашивает последовательный порт до 5 запросов, но также может вручную проверять конкретные запросы и вводить команды, отбрасывая ответы от команды.

Что я уже пробовал:

namespace SerialPort
{
 public partial class Form1 : Form
 {
 public Form1()
 {
 InitializeComponent();
 cmdClose.Enabled = false;

 }

public System.IO.Ports.SerialPort myport;

public void serialport_connect(String port, int baudrate , Parity parity, int databits, StopBits stopbits) 
 {

 myport = new System.IO.Ports.SerialPort(
 port, baudrate, parity, databits, stopbits);
 try
 {
 myport.Open();
 cmdClose.Enabled = true;
 cmdConnect.Enabled = false;
 txtReceive.Text = ("Connected\n");
 myport.DataReceived += new SerialDataReceivedEventHandler(myport_DataReceived_1);
 }
 catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
 }


public void myport_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
 {

 txt1.Text= (myport.ReadExisting().ToString().Replace("@", "").Replace("O", "").Replace("A", "") + "\n");
 float f1 = (float)double.Parse(txt1.Text);
 SevenSegment.Value = f1;

 Thread.Sleep(100);

 

txt2.Text= (myport.ReadExisting().ToString().Replace("@", "").Replace("O", "").Replace("A", "") + "\n");
 float f2 = (float)double.Parse(txt2.Text);
 SevenSegment2.Value = f2;

 }
 private void Form1_Load(object sender, EventArgs e)
 {
 String port = "COM1";
 int baudrate = 9600;
 Parity parity = Parity.None;
 int databits = 8;
 StopBits stopbits = StopBits.One;
 serialport_connect(port, baudrate, parity, databits, stopbits);
 }


 private void cmdConnect_Click(object sender, EventArgs e)
 {
 String port = "COM1";
 int baudrate = 9600;
 Parity parity = Parity.None;
 int databits = 8;
 StopBits stopbits = StopBits.One;
 serialport_connect(port, baudrate, parity, databits, stopbits);


 }

private void cmdClose_Click_1(object sender, EventArgs e)
 {

 if (myport.IsOpen) 
 {
 myport.Close();
 cmdClose.Enabled = false;
 cmdConnect.Enabled = true;
 txtReceive.AppendText("Disconnected\n");
 }
 }


 private void btn1_Click(object sender, EventArgs e)
 {

 byte[] byte1 = { 0x4f, 0x49, 0x0D };
 myport.Write(byte1, 0, byte1.Length);
 txt1.AppendText(byte1 + "\r" + "\n");

 }

private void btn2_Click(object sender, EventArgs e)
 {
 byte[] byte2 = { 0x2f, 0x33, 0x0D };
 myport.Write(byte2, 0, byte2.Length);
 txt2.AppendText(myport.ReadExisting().ToString().Replace("@", "").Replace("O", "").Replace("A", "") + "\n");

 }

 

 

//This is the code that works ok, but for the single queries, it crashes. 

private void btn12_Click(object sender, EventArgs e)
 {
 byte[] byte1 = { 0x3f, 0x56, 0x0D };
 myport.Write(byte1, 0, byte1.Length);
 txt1.AppendText(byte1 + "\r" + "\n");

 Thread.Sleep(100);

 byte[] byte2 = { 0x3f, 0x49, 0x0D };
 myport.Write(byte2, 0, byte2.Length);
 txt2.AppendText(byte2 + "\r" + "\n");
 }
 }

Member 14732673

во-первых, 9600 бод-это очень медленно. если вы находитесь на очень быстром компьютере, устройство, с которым вы разговариваете, может не успеть обработать первое сообщение, прежде чем вы передадите ему второе сообщение. Если вы нажимаете на кнопки очень быстро, посылая ему сообщение за сообщением.
У вас есть сон между сообщениями, где он работает. Попробуйте поставить еще несколько спальных мест. Это метод проб и ошибок.

удачи

1 Ответов

Рейтинг:
1

OriginalGriff

Первое, что нужно заметить, это то, что это не сработает - событие DataRecieved обрабатывается в новом потоке, поэтому вы не можете получить доступ к элементам управления в методе обработчика - при попытке оно вызовет исключение кросс-потока.
The second thing is that serial ports are just that: serial. They receive data one byte at a time, and you normally get a DataRecived event raised for each character - so your code will start to get problems fairly quickly. It will read the first character, then pause, then read an unknown number of characters and process those - thread.Sleep specifies a minimum time to pause the thread, not a maximum, and the data is only received as fast as the "other end" of the link sends them (which even at 9600 baud - 1000 characters per second, pretty much - can have significant "gaps" between successive characters depending on what else it is doing at the time) so any form of "timing based" message processing is a bad idea.

Вместо того чтобы обрабатывать данные в событии DataRecieved, поместите их в буфер или очередь и обработайте, когда у вас есть "полное сообщение".