gearhead

I've been trying to a simple Comm program to work using the
ReadExisting method of the .Net 2.0 SerialPort class.
The data value is being transmitted to me from a PIC micro dev board

as 4 ascii characters. i.e. binary 1234 is sent as a character

array of '1' '2' '3' '4'

The data received event fires when ReceivedBytesThreshold is
reached as it should, but I only get back one character when there are
4 in the buffer. I verified this by retrieving the BytesToRead
property and it is set to 4.

If I add additional ReadExisting method calls afterwards I will get
one and only one char back for each read.

I also tried the Read method for byte and char but same result as ReadExisting.

Lastly I ran Hyperterm and another terminal program
and they both receive the entire 4 chars with no problems.
The databits, baudrate, and handshaking are all set the same
for my code as well as the terminal programs. I have also
tried setting the DtrEnable and RtsEnable to true but with
no success.

sorry for the long post but i tried to be as brief as possible

Any help will be greatly appreciated.



Re: .NET Base Class Library Got it working

gearhead

I tried running the release version of the .exe and the program works but not flawlessly.

The reception rate is extremely slow compared to hyperterm or a similiar terminal

program. Not sure if playing with the read timeout would help or not.





Re: .NET Base Class Library Got it working

JonCole - MSFT

The SerialPort class is owned by the BCL team - moving this post to that forum for better visibility.




Re: .NET Base Class Library Got it working

nobugz

This is all pretty unusual behavior for SerialPort. Post your code if you want us to help you.





Re: .NET Base Class Library Got it working

Carsten Kanstrup

I have done some tests, which shows that the DataReceived event fires when the number of characters in the receive buffer is greater than or equal to the threshold level and the event handler for the data received event is not busy. The DataReceived event does not fire again before you return from the event handler.

ReadExisting just reads what is in the receive buffer when the DataReceived event fires, so especially at low speeds it may only return one character. You should always check the returned value from ReadExisting to see how many characters are actually received. If you call ReadExisting (or ReadByte) many times immediately after each other it is very likely that you get in synchronization with the transmission speed so that each call only returns one character.

I always recommend using ReadByte in a "While YourCOMPort.BytesToRead > 0" or a "Do - Loop Until YourCOMPort.BytesToRead = 0" loop instead of ReadExisting if you want to empty the entire receive buffer.





Re: .NET Base Class Library Got it working

gearhead

I appreciate the info.

Interesting, so even though there are additional bytes received they are not available to be read via the SerialPort class. Basically there are two

buffers What stimulates the movement of the data from otherl buffer to the SerialPort class





Re: .NET Base Class Library Got it working

gearhead

Stan



Re: .NET Base Class Library Got it working

Carsten Kanstrup

No. All received bytes are available.

If you have not changed the threshold level, DataReceived will fire as soon as the first byte is received. When this happens, SerialPort graps a thread from the thread pool and uses this for the event handler for the DataReceived event. At low speeds it is very likely that there is only one character in the receive buffer when your event handler starts running so ReadExisting may only return one character even though your telegram consists of four characters. However, the UART driver continues to put received data into the receive buffer, so if you call ReadExisting (or ReadByte) again, a new character may be available.

If you want to receive a telegram, which consists of four characters, you must wait for four characters (or a timeout). Note however that until you return from the event handler, DataReceived will not fire again.

You can either collect the whole telegram in the event handler or just use the event handler to invoke a subroutine on the UI thread. The first method is best for high speed operation. Since the event handler uses its own thread, it doesn't matter if you block this thread with Read(), so you can just wait for your four bytes. If you choose to empty the receive buffer from a subroutine on the UI thread, you must return as soon as the buffer is empty or else you will block the UI thread. This means a lot of overhead with DataReceived event, thread pool thread and a new invoke for the next character(s).

The question with the two buffers is indeed a very good one. According to the help files, ReadBufferSize refers to the size of the buffer in the UART driver and BytesToRead is the total number of bytes in the two buffers together, but unfortunately the buffer in the SerialPort object is not described anywhere - at least I have not been able to find any documentation. Perhaps the SerialPort object just makes an extra buffer in case the requested buffer size is bigger than the UART driver can support, but it is pure guesswork. As usual, Microsoft don't provide any below-the-hood information, so we all have to base our programs on guesswork and tests .





Re: .NET Base Class Library Got it working

JonCole - MSFT

Sorry, I shouldn't have used the acronym. It means Base Class Library.




Re: .NET Base Class Library Got it working

gearhead

Carsten,

Thank you for all the help. I had a bit of a time getting the code to work. Discovered that

the debugger does not permit single stepping in a event handler. Guess I forgot

that I wasnt debugging on a microchip platform. So I had to be a

bit more clever when testing. For the actual project my received input is of varying length

8 bit ascii lines produced by a test instrument. Each line is terminated by a "\n" (newline).

I do a ReadExisting until I get a "\n", then send the line to the RichTextBox.

The code I started with appears here http://msmvps.com/blogs/coad/archive/2005/03/23/39466.aspx

The modifications were minor but essential. I learned a lot and thanks again.

Stan





Re: .NET Base Class Library Got it working

Carsten Kanstrup

Why not use ReadLine It is tailor cut for applications like this.

The application you refer to open and close the port for each write. This is not a good idea. Open the port when the right COM port is selected (COM1, COM2 etc.) and don't close it before you terminate your application or change the COM port.

Perhaps it is a good idea to read the description of our serial port program on the address: http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm . The program and the examples are in VB, but the knowledge is general useable.





Re: .NET Base Class Library Got it working

gearhead

We must not be looking at the same code. The code I downloaded has a button to open port and a button to

close port. The port remains open during the entire time of receive and transmit.





Re: .NET Base Class Library Got it working

Carsten Kanstrup

This is the code I found in your link:

Code Snippet

// Open the port for communications
port.Open();

// Write a string
port.Write("Hello World");

// Write a set of bytes
port.Write(new byte[] {0x0A, 0xE2, 0xFF}, 0, 3);

// Close the port
port.Close();

Certainly not something to recommend!