C#写入后,SerialPort收到的数据有误

时间:2016-07-15 12:01:31

标签: c# serial-port

我有一个通信设备,它通过COM每两秒发送一次请求。在请求之间,设备等待响应。我使用SerialPort在C#中构建软件。我为数据接收调用一个事件处理程序,并在while循环的新线程中运行一个方法,它检查请求是否符合预期,并调用负责响应的方法。问题是,在响应下一次收到的数据是错误的。这是代码: SerialPortManager

class SerialPortManager : IDisposable
{
...
public void connect()
    {
        if (mSerialPort.IsOpen)
            return;
        mSerialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
        try
        {
            mSerialPort.Open();
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            mStatus = Status.DISCONNECTED;
            return;
        }
        if (mSerialPort.IsOpen)
        {
            mStatus = Status.CONNECTED;
            Thread tryToResponseThread = new Thread(tryToResponse);
            tryToResponseThread.Start();
        }
    }
private void tryToResponse()
    {
        while (mStatus == Status.CONNECTED)
        {
            if (mRequest.Length >= 56)
            {
                string checksum = "555555555555555580808080";
                if (mRequest.Length > 56)
                {
                    mRequest.Remove(55, mRequest.Length - 56);
                    Debug.Print("cutting");
                }
                if (mRequest.ToString().StartsWith(checksum))
                {
                    StringBuilder strToCMD = new StringBuilder();
                    for (int i = 0; i < mRequest.Length; i += 2)
                    {
                        strToCMD.Append(mRequest[i]);
                        strToCMD.Append(mRequest[i + 1]);
                        strToCMD.Append("  ");
                    }
                    StringBuilder address = new StringBuilder();
                    StringBuilder group = new StringBuilder();
                    address.Append(mRequest.ToString(24, 8));
                    group.Append(mRequest.ToString(24 + 8, 2));
                    mMainForm.appendCMDTextboxText(Environment.NewLine);
                    mMainForm.appendCMDTextboxText(DateTime.Now.ToLongTimeString() + " [RX] " + address.ToString() + " " + group.ToString() + "\t");
                    mMainForm.appendCMDTextboxText(strToCMD.ToString());
                    byte[] request = ByteArrayConverter.fromString16(mRequest.ToString());
                    mRequest.Clear();
                    response(request);
                    Array.Clear(request, 0, request.Length);
                    Debug.Print("starts with checksum");
                }
                else if (mRequest.ToString().Contains(checksum))
                {
                    int indexOfChecksum = mRequest.ToString().IndexOf(checksum);
                    mRequest.Remove(0, indexOfChecksum);
                    Debug.Print("contains");
                }
                else
                {
                    int index = 0;
                    bool found = false;
                    for (int i = 0; i < checksum.Length; i++)
                    {
                        StringBuilder s = new StringBuilder();
                        int sub = mRequest.Length - checksum.Length + i + 2;
                        if (sub == mRequest.Length)
                            break;
                        s.Append(mRequest.ToString().Substring((Math.Max(0, mRequest.Length - checksum.Length + i + 2))));
                        s.Append(mRequest.ToString(0, i + 2));
                        if (s.ToString().Equals(checksum))
                        {
                            index = sub;
                            found = true;
                            break;
                        }
                    }
                    if (found)
                    {
                        mRequest.Remove(0, index);
                    }
                    else
                    {
                        mRequest.Clear();
                    }
                    Debug.Print("on start and end");
                }
            }
        }
    }
private void response(byte[] request)
    {
        Luminaire lumToResponse = mLuminaireManager.getLuminaire(request);
        if (lumToResponse == null)
        {
            return;
        }
        else
        {
            if (lumToResponse.isNotResponding())
                return;
        }
        byte[] responseMsg = lumToResponse.getWholeFrame(request);
        mMainForm.setCommandLabelForResponsingLuminaire(lumToResponse);
        mMainForm.appendCMDTextboxText(Environment.NewLine + DateTime.Now.ToLongTimeString() + " [TX]\t");
        string responseMsgAsString = ByteArrayConverter.toString(responseMsg).Replace("-", "  ");
        mMainForm.appendCMDTextboxText(responseMsgAsString);
        write(responseMsg, 0, responseMsg.Length);
        mSerialDataEventArgs.clearData();
    }
public void write(byte[] buffer, int offset, int count)
    {
        if (mStatus == Status.DISCONNECTED || mSerialPort.IsOpen == false)
        {
            mStatus = Status.DISCONNECTED;
            return;
        }
        mSerialPort.Write(buffer, offset, count);
    }
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        if (mStatus == Status.DISCONNECTED)
            return;
        int dataLength = mSerialPort.BytesToRead;
        if (dataLength == 0)
            return;
        byte[] data = new byte[dataLength];
        mSerialPort.Read(data, 0, dataLength);
        mSerialDataEventArgs.setData(data);
        mDataReceived?.Invoke(this, mSerialDataEventArgs);
    }

...
}

用于传递接收数据的帮助程序类:

public class SerialDataEventArgs : EventArgs
{

    public SerialDataEventArgs()
    {

    }
    public void setData(byte[] data)
    {
        clearData();
        mData = data;
    }
    public SerialDataEventArgs(byte[] dataInByteArray)
    {
        mData = dataInByteArray;
    }
    public void clearData()
    {
        if (mData == null)
            return;
        Array.Clear(mData, 0, mData.Length);
    }
    public byte[] mData;
}

主要课程:

public partial class MainForm : Form
{
...
private void MainForm_Load(object sender, EventArgs e)
    {
        mSerialPortManager = new SerialPortManager();
        mSerialPortManager.setPortBoudRate((int)numUpDown_SerialPortSpeed.Value);
        mLuminaireManager = new LuminaireManager();
        mSerialPortManager.mMainForm = this;
        mSerialPortManager.mLuminaireManager = mLuminaireManager;
        fixTableLayoutColumnSize(ref tl_SingleLuminaire);
        fillTheRestOfSingleLuminaireGroupBoxes();
        fillSerialPortComboBoxWithNamesOfAvailablePorts();
        mSerialPortManager.mDataReceived += new EventHandler<SerialDataEventArgs>(serialPortManager_DataReceived);
        mIsPaused = false;
    }
private void serialPortManager_DataReceived(object sender, SerialDataEventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new EventHandler<SerialDataEventArgs>(serialPortManager_DataReceived), new object[] { sender, e });
            return;
        }
        if (mIsPaused)
            return;
        mSerialPortManager.mRequest.Append(ByteArrayConverter.toString(e.mData).Replace("-", ""));
    }
...
}

沟通应如下所示:

request:  5555555555555555808080800100000001001A0006070001060031B1
response: 55555555555555558080808001000000010000808076
request:  5555555555555555808080800200000001001A0006070001060034B2
response: 555555555555555580808080020000000100008041BA
request:  5555555555555555808080800300000001001A000607000106003473
response: 55555555555555558080808003000000010000804049

等等。这只是一个例子,请求框架应该是什么样子。如您所见,设备要求1,2,3,4等。它总是按此顺序询问。最后四个值只是校验和。我在回复后收到的内容如下:

request:  5555555555555555808080800200000001001A0006070001060034B2
response: 555555555555555580808080020000000100008041BA
request:  55555555555555558080808002000000000A0100000000000000BCAE

响应2后,应该要求3.如果我将软件设置为无响应,则每个请求看起来都很好。 我做错了什么?

1 个答案:

答案 0 :(得分:-2)

好的,所以一切都好。我的COM界面坏了:(两种方式都很好 - DataReceived事件处理程序和read()在write()之后(无论哪种解决方案在编程方式上都更好)。谢谢大家帮我解决了我的案例!< / p>