【问题标题】:Serial Port.Datareceived is not firing (.net 4.5)Serial Port.Datareceived 未触发(.net 4.5)
【发布时间】:2018-01-07 02:03:54
【问题描述】:

我正在使用 .net 4.5,因为我了解到一些互联网上关于 .net 对 rad 串行数据的代码实现错误的讨论,所以我使用了下面的代码。

问题是,尽管我可以看到我创建了一个 COM 端口连接(到正确的 COM 端口号),但它永远不会在收到数据时触发。 数据接收基于一个简单的 Arduino 应用程序(Arduino 监视器确实显示数据通过串行发送),但 .net 永远不会在串行事件时触发。

我在 eventread 上设置了断点,它永远不会被命中

我在这里查看过其他讨论,例如.NET SerialPort DataReceived event not firing,但到目前为止,他们还没有解决我遇到的问题。我尝试了串行线设置的各种组合,并相信以下是正确的。 至于 Arduino 部分,该行设置为:

Serial.begin(9600);

我将我的班级称为:`InfraredSensor mySens = new InfraredSensor("COM4",9600);'

class InfraredSensor
{
    private string Eventlogapp = "IRlogging"; 
    private SerialPort Port;
    public InfraredSensor(string COMport, int baudrate) //constructor
    {
        if (applicationlog != "") this.EventlogSapec = applicationlog;
        WriteEventLog(EventlogSapec, EventSource, "Initializing-IR:" + COMport, info, EventIRStarted);

        // I found that the .net standard implementation for com port reading is not OK (.net doesnt follow win32 api).
        // There are numerous readings about it, but a good way to read seams to be to use Serial BaseStream.ReadAsync
        // code below is based upon : http://www.c-sharpcorner.com/code/2880/serial-port-with-efficient-data-reading-in-c-sharp.aspx

        this.comport = COMport;
        SerialPort Port = new SerialPort(comport);

        Port.BaudRate = baudrate;
        Port.DataBits = 8;
        Port.Parity = Parity.None;
        Port.StopBits = StopBits.One;
        Port.Handshake = Handshake.None;

        Port.NewLine = Environment.NewLine;
        Port.ReceivedBytesThreshold = 2; // + linefeed 
        Port.DataReceived += ReadEvent;
        Port.Open();
        Port.DtrEnable = true;
       // i've tested from here i do have an open connection
       // its just dat ReadEvent never fires...
    }


      private void ReadEvent(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] buffer = new byte[2];//todo i only send "A" or "B", for the debug moment 
        Action kickoffRead = null;

        kickoffRead = (Action)(() => Port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
        {
            try
            {
                int count = Port.BaseStream.EndRead(ar);
                byte[] dst = new byte[count];
                Buffer.BlockCopy(buffer, 0, dst, 0, count);
                RaiseAppSerialDataEvent(dst);
            }
            catch (Exception ex)
            {
                WriteEventLog(Eventlogapp, "IR", "Failure-IR:" + ex.Message, info, 204);
            }
            kickoffRead();
        }, null)); kickoffRead();
    }

    private void RaiseAppSerialDataEvent(byte[] Data)
    {
    // code never gets to here
        string msg = Encoding.Default.GetString(Data);
    int breakpointhere = 0;

        if (msg.Contains('A')) WriteEventLog(Eventlogapp, "IR", "Sensor A", info, 213);

        if (msg.Contains('B')) WriteEventLog(Eventlogapp, "IR", "Sensor B", info, 214);


    }
}

我的想法已经用完了(头发让我发疯了)是什么导致了这种行为?

【问题讨论】:

  • 在致电Port.Open() 之前,您是否尝试过将Port.DtrEnable = true; 移动到?我以前没有使用 .NET 进行串行通信,但如果不是那样愚蠢的话,我不会感到惊讶。除此之外,我建议下载某种串行数据嗅探器,以确保端口实际上接收数据。
  • 确保您的COMport 字符串在设备管理器中正确/匹配。我经历过 Windows 在移除并重新插入设备时更改端口名称,尽管插入到同一个端口。虽然,这可能是我的环境所特有的,所以用(大)茶匙盐服用。
  • @Clint 是的,我试过了,我也不确定,但有些人建议在另一个谈话中
  • @marcushobson 我可以清楚地看到它的 COM4,arduino IDE 也使用 4。我也确定 IDE 没有锁定端口 4,我断开连接并重新启动,我什至可以验证我有连接,因为 Port.IsOpen 在类的构造函数中工作正常。

标签: c# serial-port


【解决方案1】:

最后这花了我 2 天的时间......

在我现在使用的 arduino 代码中

serial.print("Mytext\n");  // using \n to be sure of escape character

对于我现在使用的串行线路配置

this.comport = COMport;
this.Port = new SerialPort(comport);
this.Port.BaudRate = baudrate;
this.Port.DataBits = 8;
this.Port.Parity = Parity.None;
this.Port.StopBits = StopBits.One;
this.Port.Handshake = Handshake.None;
this.Port.RtsEnable = true;
      //  Port.NewLine = "\n";
       //   Port.ReceivedBytesThreshold = 2; // + linefeed 
        this.Port.DataReceived += new new SerialDataReceivedEventHandler(ReadEvent);

....
..
SerialDataReceivedEventHandler(ReadEvent);
//code didnt change inside but the method has changed see the +=

【讨论】:

    【解决方案2】:

    DataReceived 事件在有数据通过串行端口时触发,但它可以随机触发。因此,您可以在一个事件中获得部分消息,而在另一个事件中获得另一半消息。你应该有某种密钥来知道你什么时候有完整的消息。所以建立你的字符串,直到你有整个消息然后根据消息做一些事情。

    例如,当有换行时,我的设备的消息就完成了。所以我的代码看起来像:

    char ESC = (char)27;
    char CR = (char)13;
    char LF = (char)10;
    StringBuilder sb = new StringBuilder();
    
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string Data = serialPort1.ReadExisting();
    
        foreach (char c in Data)
        {
            if (c == LF)
            {
                sb.Append(c);
    
                //we have our message, do something, maybe like
                if (sb.ToString().Contains("A"))
                {
                    //print A
                }
                else
                {
                    //print B
                }
            }
            else
            {
                sb.Append(c);
            }
        }
    }
    

    【讨论】:

    • 即使它会在 '\n' 上触发,我有点怀疑.. 那么它不会导致我现在必须失败的代码,因为 '\n' 不是 A 或 B。它虽然是一个主题这引起了我的兴趣,因为我在.net 4.0 中遇到了麻烦,有时会丢失字节,这在我的项目中是不允许的
    猜你喜欢
    • 1970-01-01
    • 2019-07-23
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多