简体   繁体   中英

Serial Port.Datareceived is not firing (.net 4.5)

I am using .net 4.5 and since i got aware about some internet discussion about .net having wrong code implementation to rad serial data, i went with the code below.

The problems is however even despite i can see i create a COM port connection (to the right com port number), its never firing on data received. The data receiving is based upon a simple Arduino app, (Arduino monitor does show data gets send over serial), but .net never seams to fire upon serial events.

I've put breakpoints on eventread, it never gets hit

i've looked at other discussions here like .NET SerialPort DataReceived event not firing but so far they don't resolve the issue i have. I tried various combination of serial line setups, and believe the below ones are correct. as for Arduino part the line is setup as:

Serial.begin(9600);

I call my class like : `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);


    }
}

I ran out of ideas (and hair as its driving me nuts) what could cause this behaviour ?

finally this took me 2 days ...

in arduino code i now use

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

for the serial line config i now use

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 +=

The DataReceived event fires when there is data coming through the serial port, but it can fire randomly. So you could get part of the message in one event and the other half of the message in another event. You should have some sort of key to know when you have the whole message. So build your string until you have the whole message then do something based on the message.

For example, my device's message is done when there is a Line Feed. So my code looks something like:

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);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM