C# SerialPort Recieve Problem

Posted on 2010-08-30
Last Modified: 2013-12-17
Hello guys,
I have a cash register and I communicate with it on a low level. So, the idea is the following. The fiscal printer has got fiscal memory. IN this memory it records everything you've sold. But before I make a sale I want to check if this memory is full, cos I'll have problems with registring the sale. How do I do this? By sending a request that return something and with this something the state of the printer. So I write the following funcion that sends data.

FiscalPrinters.DatecsFP1000 fiscal = new FiscalPrinters.DatecsFP1000();
            if(serialPort.IsOpen == false)
            fiscal.izpratiKomanda(0x3E, 0x20);
            serialPort.Write(fiscal.izpratiKomanda(0x3E, 0x20), 0, fiscal.izpratiKomanda(0x3E, 0x20).Length);

I leave the port opened to recieve the data. I use a program to monitor the communication. The data sended is:
01 24 20 3E 05 30 30 38 37 03  in HEX
The recieved data is:
01 3C 20 3E 33 30 2D 30 38 2D 31 30 20 30 39 3A
35 38 3A 32 30 04 88 80 C0 86 86 92 05 30 37 35   in Hex
3B 03

and in string 30-08-10 it gives me the date. Which means everything in the sent command is OK :).
So, to read this line, which contains a control bit, that says is there free memory in the printer, I've written the following functuin attaced to a SerialPort DataRecieved event.

if (!serialPort.IsOpen)

But the event eider doesn't trigger, or throws the following exception:
The I/O operation has been aborted because of either a thread exit or an application request.

What am I doing wrong?
Question by:IncognitoMan
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7

Expert Comment

ID: 33558110

The ReadLine() function will wait (freezing your program) until some data is received and is terminated by CrLf (carriage return line feed). Are you sure that the printer responses are terminated with CrLf? I don't see them in the data that you said is sent back. (Hex values are 13, 10, respectively)

Make sure you do not close the serial port an ANY time after you send the data or any time before you read the response. Just to make sure you don't close it, you should use this code instead of the one you posted above:

(In DataReceived event handler)

if (!serialPort.IsOpen)
   throw new Exception("Serial Port is not Open");

Open in new window


Expert Comment

ID: 33558130
If the device doesn't send CrLf, then you can just use Read() instead, and specify the number of bytes to read. You will know which method to use by looking at the protocol for the device, which should tell you whether or not CrLf is used.

Expert Comment

ID: 33558193
What this means, almost certainly, is that the SerialPort object attempted to complete the call to ReadLine after the port was been closed.  

This can happen because of the lack of synchronization between UI events which may cause the port to close, and the background thread in the SerialPort object that is performing the actual ReadFile operation (this executes as a result of ReadLine in your delegate).

The problem with ReadLine, and the reason that you way not want to use it, is that it blocks (i.e. freezes your program) until the the line terminating condition occurs (CrLf) -- this may be AFTER you have closed the port.  Thus the exception.

You could simply use ReadExisting () and buffer the data in byte[] variable and test the buffer for the CrLf terminating characters.  
Remember to clear this buffer AFTER you have processed and displayed its content.  If you do this, the exception should be resolved.
Quiz: What Do These Organizations Have In Common?

Hint: Their teams ended up taking quizzes, too.


Expert Comment

ID: 33558639
1.- As stated before, binary data cannot be handled with the ReadLine command. Looking at your response data there is no CrLf to indicate end of string so I would not expect ReadLine to do anything sensible.
2.- I cannot see where you initialise the serial port parameters. These have to be set the same way as the printer. You need to do something like this for 8 bit clear comms:
            serialPort = new SerialPort("COM1");
            serialPort.BaudRate = 9600;
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.Even;
            serialPort.HandShake = Handshake.None;
3.- Use the Read function and the set up a state machine to handle the data. Given that this is a syncrhonous request/response protocol it is quite easy to handle. You need to do something like this:
            serialPort.Write(command, command.Length())
            int status=1
            while(status > 0)
                        byte[] buffer = new buffer[256];
                        int bytes = serialPort.Read(buffer, 256)
                        int byte;
                        for (byte=0;byte < bytes;byte++)
                                    byte b = buffer[byte];
                                     case 1:
                                                if (b == ????)

I can't help you much more with the state machine as I do not know the protocol that this particular printer uses.

Author Comment

ID: 33559376
Strange, very strange. Your method worked. It did solve the exception. So what I did was, I read the data, and then convert the string into a byte array.
string str = serialPort.ReadExisting();
                byte[] data = new byte[str.Length];
                data = System.Text.ASCIIEncoding.ASCII.GetBytes(str);

But using a Serial Port monitoring program, I saw that the device is returning the folloing:
01 3C 20 3E 33 30 2D 30 38 2D 31 30 20 31 38 3A
30 33 3A 30 39 04 88 80 C0 86 86 92 05 30 37 35   (HEX)
38 03

And the contents ot the byte array are:

01 66 32 63 51 48 45 48 56 45 49 48 32 49 56 58
48 51 58 48 57 04 63 63 63 63 63 63 05 48 55 53    (DEC)
56 03

The information that I want to read is between the 04 and 05 bytes on the second line. But in the port monitoring program they are 88 80 C0 86 86 92, which is exactly what should be returned, and the byte array in the program has got 63 63 63 63 63 63 which is totolly wrong. It cant return this :).
Maybo the problem is that I convert the string into byte array. But is there a way to read this message from the device and but it derectly into a byte array?

Expert Comment

ID: 33559659

That is strange indeed.
Yes, I would recommend you switch to using the Read(byte[], int) method so that you read the bytes directly without converting to a string.

You can use the "BytesToRead" property to get the length of the buffer you need.
Something like this:

int count = serialPort.BytesToRead;
byte[] buf = new byte[count];
serialPort.Read(buf, count);
//now buf contains the bytes that were read.

Here is a more abbreviated version:
byte[] buf = new byte[serialPort.BytesToRead];
serialPort.Read(buf, buf.Length);

Let me know how that goes.

Accepted Solution

ricovox earned 500 total points
ID: 33559695
oops, I made a mistake.

the Read method takes three parameters: Read(buffer, start, length)
so it should be
Read(buf, 0, count) or Read(buf, 0, buf.Length) in the above example code

Expert Comment

ID: 33559793
If it turns out that you are still getting invalid data, perhaps you could write a small utility to convert the bytes you receive from DEC to HEX, and that might help clarify things.


foreach(byte b in buf)

That way you can directly compare the output in C# to that in your port monitoring program

Expert Comment

ID: 33559803
P.S. Better use "PrintLine" or Print(b.ToString("X") + " ");
so the numbers won't all run together.

Featured Post

Manage your data center from practically anywhere

The KN8164V features HD resolution of 1920 x 1200, FIPS 140-2 with level 1 security standards and virtual media transmissions at twice the speed. Built for reliability, the KN series provides local console and remote over IP access, ensuring 24/7 availability to all servers.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It started not too long ago. It was at first annoying. My keystrokes seemed to be randomly generated, not the ones I typed on the keyboard. For some reason this only happened in certain applications (especially browsers such as IE11, Firefox and Chr…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question