等待串口的响应,然后发送下一个数据

Wait for response from the Serial Port and then send next data(等待串口的响应,然后发送下一个数据)
本文介绍了等待串口的响应,然后发送下一个数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从 .bin 文件中以字节为单位读取数据,并将整个字节数据拆分为 16-16 字节帧,所以我想一帧一帧地读取 16 字节并等待第一帧完成其周期.

I am reading data in bytes from .bin file and split the whole byte data into 16-16 bytes frames, so I want to 16 bytes frame one by one and wait until the first frame finished its cycle.

SerialPort 类的回调方法:

Callback method of SerialPort class:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

    // Read data from serial port:
    byte[] buffer = new byte[serialPort.BytesToRead];
    serialPort.Read(buffer, 0, buffer.Length);
    StringBuilder sb = new StringBuilder();
    List<string> response = new List<string>();
    for (int i = 0; i < buffer.Length; i++)
    {
        string currentByte = string.Format("{0:X2}", buffer[i]);
        response.Add(currentByte);

        sb.AppendFormat("{0:X2}", buffer[i]);
    }

    string responesCode = response[1].ToString();
    if (responesCode == "44")
    {
        // Wait until the first response is not received
        foreach (var packet in packetList.Skip(1))
        {
            // This method which sending the the data
            this.ReadByteDataFromFile(packet);
        }
    }
}

FdBrowseFile_Click 按钮点击:

private void FdBrowseFile_Click(object sender, RoutedEventArgs e)
{
    Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
    Nullable<bool> result = dlg.ShowDialog();
    if (result == true)
    {
        byte[] fileBytes = File.ReadAllBytes(filename);

        foreach (byte[] copySlice in fileBytes.Slices(16))
        {
            var splitedByteArray = copySlice;
            if (splitedByteArray.Length != 16)
            {
                byte[] padd = new byte[16];
                var startAt = 0;
                Array.Copy(splitedByteArray, 0, padd, startAt, splitedByteArray.Length);
                packetList.Add(padd);
            }
            else
            {
                packetList.Add(splitedByteArray);
            }
        }
        ReadByteDataFromFile(packetList[0]);
    }
}

ReadByteDataFromFile 方法:

ReadByteDataFromFile method:

public void ReadByteDataFromFile(byte[] packet) {
 try {
  byte[] mBuffer = new byte[24];
  byte[] payload = new byte[16];
  int i = 0;
  foreach(var bytes in packet) {
   payload[i++] = bytes;
  }
  CheckSumHelper checkSumHelper = new CheckSumHelper();
  var ckSum = checkSumHelper.GetCheckSum(payload);
  mBuffer[0] = 0x02;
  mBuffer[1] = 0x10;
  mBuffer[2] = CheckSumHelper.GetBytesFromDecimal(packet[0]);
  mBuffer[3] = CheckSumHelper.GetBytesFromDecimal(packet[1]);
  mBuffer[4] = CheckSumHelper.GetBytesFromDecimal(packet[2]);
  mBuffer[5] = CheckSumHelper.GetBytesFromDecimal(packet[3]);
  mBuffer[6] = CheckSumHelper.GetBytesFromDecimal(packet[4]);
  mBuffer[7] = CheckSumHelper.GetBytesFromDecimal(packet[5]);
  mBuffer[8] = CheckSumHelper.GetBytesFromDecimal(packet[6]);
  mBuffer[9] = CheckSumHelper.GetBytesFromDecimal(packet[7]);
  mBuffer[10] = CheckSumHelper.GetBytesFromDecimal(packet[8]);
  mBuffer[11] = CheckSumHelper.GetBytesFromDecimal(packet[9]);
  mBuffer[12] = CheckSumHelper.GetBytesFromDecimal(packet[10]);
  mBuffer[13] = CheckSumHelper.GetBytesFromDecimal(packet[11]);
  mBuffer[14] = CheckSumHelper.GetBytesFromDecimal(packet[12]);
  mBuffer[15] = CheckSumHelper.GetBytesFromDecimal(packet[13]);
  mBuffer[16] = CheckSumHelper.GetBytesFromDecimal(packet[14]);
  mBuffer[17] = CheckSumHelper.GetBytesFromDecimal(packet[15]);
  mBuffer[18] = 0x17;
  mBuffer[19] = 0x00;
  mBuffer[20] = 0x00;
  mBuffer[21] = 0x00;
  mBuffer[22] = Convert.ToByte(int.Parse(ckSum, System.Globalization.NumberStyles.HexNumber));
  mBuffer[23] = 0x03;
  serialPort.Write(mBuffer, 0, mBuffer.Length);
 } catch (Exception ex) {
  ExceptionHandler exceptionHandler = new ExceptionHandler();
  exceptionHandler.HandleException(ex);
 }
}

如何为 ReadByteDataFromFile 方法添加延迟?

How I can add a delay for ReadByteDataFromFile method?

推荐答案

写完第一帧后循环等待完整响应.

Wait in a loop for a full response after you write a first frame.

// Set read timeout to value recommended in the communication protocol specification 
// so serial port operations don't stuck.
_port.WriteTimeout = 200;
_port.ReadTimeout = 200;

public void OnClick()
{
    // Write first frame.
    _port.Write(...);
    // Now wait for the full response.

    // Expected response length. Look for the constant value from the device communication 
    // protocol specification or extract from the response header (first response bytes) if  
    // there is any specified in the protocol.
    int count = ...; 
    var buffer = new byte[count];
    var offset = 0;
    while (count > 0)
    {
        var readCount = _port.Read(buffer, offset, count);                 
        offset += readCount;
        count -= readCount;
    }
    // Now buffer contains full response or TimeoutException instance is thrown by SerialPort.
    // Check response status code and write other frames.
}

为了不阻塞 UI 线程,您很可能仍然需要使用同步 API 和 Task.Run().请参阅 C# 串行等待事件和超时端口通信 StackOverflow 上的讨论.

In order to not block UI thread you most probably still need to utilize synchronous API and Task.Run(). See C# await event and timeout in serial port communication discussion on StackOverflow.

有关详细信息,请查看 Kim Hamilton 的 5 大 SerialPort 技巧 文章.

For more information check Top 5 SerialPort Tips article by Kim Hamilton.

这篇关于等待串口的响应,然后发送下一个数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)