1

Solution

Reading the data byte wise via "port.ReadByte" is too slow, the problem is inside the SerialPort class. i changed it to reading bigger chunks via "port.Read" and there are now no buffer overruns.

although i found the solution myself, writing it down helped me and maybe someone else has the same problem and finds this via google...

(how can i mark it as answered?)

EDIT 2

by setting

port.ReadBufferSize = 2000000;

i can delay the problem for ~30 seconds. so it seems, .Net really is too slow... since my application is not that critical, i just set the buffer to 20MB, but i am still interested in the cause.

EDIT

i just tested something i had not thought of before (shame on me):

port.ErrorReceived += (object self, SerialErrorReceivedEventArgs se_arg) => { Console.Write("| Error: {0} | ", System.Enum.GetName(se_arg.EventType.GetType(), se_arg.EventType)); };

and it seems that i have an overrun. Is the .Net implementation too slow for 500k or is there an error on my side?

Original Question

i built a very primitive oszilloscope (avr, which sends adc data over uart to an ftdi chip). On the pc side i have a WPF Programm that displays this data.

The Protokoll is:

two sync bytes (0xaffe) - 14 data bytes - two sync bytes - 14 data bytes - ...

i use 16bit values, so inside the 14 data bytes are 7 channels (lsb first).

I verified the uC Firmware with hTerm, and it does send and receive everything correct. But, if i try to read the data with C#, sometimes some bytes are lost. The oszilloscop programm is a mess, but i created a small sample application, which has the same symptoms.

I added two extension methods to a) read one byte from the COM Port and ignore -1 (EOF) and b) wait for the sync pattern.

The sample programm first syncs onto the data stream by waiting for (0xaffe) and then compares the received bytes with the expected values. the loop runs a few times until an assert failed message pops up. I could not find anything about lost bytes via google, any help would be appreciated.

Code

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialTest
{
    public static class SerialPortExtensions
    {
        public static byte ReadByteSerial(this SerialPort port)
        {
            int i = 0;
            do
            {
                i = port.ReadByte();
            } while (i < 0 || i > 0xff);
            return (byte)i;
        }

        public static void WaitForPattern_Ushort(this SerialPort port, ushort pattern)
        {
            byte hi = 0;
            byte lo = 0;

            do
            {
                lo = hi;
                hi = port.ReadByteSerial();
            } while (!(hi == (pattern >> 8) && lo == (pattern & 0x00ff)));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //500000 8n1
            SerialPort port = new SerialPort("COM3", 500000, Parity.None, 8, StopBits.One);
            port.Open();
            port.DiscardInBuffer();
            port.DiscardOutBuffer();

            //Sync
            port.WaitForPattern_Ushort(0xaffe);


            byte hi = 0;
            byte lo = 0;
            int val;

            int n = 0;

            // Start Loop, the stream is already synced
            while (true)
            {
                //Read 7 16-bit values (=14 Bytes)
                for (int i = 0; i < 7; i++)
                {
                    lo = port.ReadByteSerial();
                    hi = port.ReadByteSerial();

                    val = ((hi << 8) | lo);
                    Debug.Assert(val != 0xaffe);
                }
                //Read two sync bytes
                lo = port.ReadByteSerial();
                hi = port.ReadByteSerial();

                val = ((hi << 8) | lo);
                Debug.Assert(val == 0xaffe);

                n++;
            }
        }
    }
}
Lukas Rieger
  • 676
  • 10
  • 31
  • Check, check, and check again that both sides are in complete agreement on the serial parameters (that you've indicated are 500000 8n1). – Damien_The_Unbeliever Dec 03 '12 at 13:00
  • hterm with the same parameters receives everything (checked over more than 20 sec), while my console program loses a few bytes every ~1 sec. i slightly modified the example source code, and added two pictures. i can't post them here, so here is a link: https://skydrive.live.com/redir?resid=5062EFE7E0C8ECCC!624&authkey=!AG_DmTLUP08dpoM – Lukas Rieger Dec 04 '12 at 02:36
  • i just tested something, which i should have thought of earlier: i added the line `port.ErrorReceived += (object self, SerialErrorReceivedEventArgs se_arg) => { Console.Write("| Error: {0} | ", System.Enum.GetName(se_arg.EventType.GetType(), se_arg.EventType)); };` and it seems, the problem is an overrun. now the question i have is, can i solve this, and if yes, how? if i find anything myself, i will report it back here. – Lukas Rieger Dec 04 '12 at 02:53

1 Answers1

1

Reading the data byte wise via "port.ReadByte" is too slow, the problem is inside the SerialPort class. i changed it to reading bigger chunks via "port.Read" and there are now no buffer overruns.

Lukas Rieger
  • 676
  • 10
  • 31