Serial port Communication on the same Windows machine does not work

Sorry, quick question:

I have this hardware setup:

The same machine: "Com3" β†’ USB β†’ To Serial β†’ To USB β†’ "Com4"

And I followed the MSDN SerialPort Class and MSDN SerialPort.ReadLine () to create this procedure:

SerialPort SendSerialPort = new SerialPort("Com3", 9600); SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600); SendSerialPort.Open(); ReceiveSerialPort.Open(); SendSerialPort.WriteLine("Test"); var message = ReceiveSerialPort.ReadLine(); // control stops here SendSerialPort.Close(); ReceiveSerialPort.Close(); Console.WriteLine(message); 

However, when I am inclined towards ReadLine() , my control stops and just waits. I did not expect this.

I expect to get the string Test and assign it to my var message . Could you tell me what I'm doing wrong here?

EDIT

I tested my hardware using the Serial Port Utility and it worked just fine .

+6
source share
3 answers

I changed from the example you provided :

To actually have both ports for reading and writing back and forth, you really need to implement read and write streams for both.

You can use a timer.

 public static void Main() { SerialPort SendSerialPort = new SerialPort("Com3", 9600); SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600); StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; Thread readThread = new Thread(Read); // Set the read/write timeouts _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; SendSerialPort.Open(); ReceiveSerialPort.Open(); bool _continue = true; readThread.Start(); Console.Write("Name: "); name = Console.ReadLine(); Console.WriteLine("Type QUIT to exit"); while (_continue) { message = Console.ReadLine(); if (stringComparer.Equals("quit", message)) _continue = false; else SendSerialPort.WriteLine(String.Format("<{0}>: {1}", name, message)); } readThread.Join(); SendSerialPort.Close(); } public static void Read() { while (_continue) { try { string message = ReceiveSerialPort.ReadLine(); Console.WriteLine(message); } catch (TimeoutException) { } } } 

Typically, written data will indicate the start and end value to tell the other port that the message is complete, as well as for the ports to confirm that they are reading the data that they should be, usually with commands on what to do with the data. (outside the scope of this issue).

Also missing and important is the initialization of your ports.

I prefer to use the default constructor (for preference only)

 SerialPort Constructor () 

And then set any values, for example:

 _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); _serialPort.Parity = SetPortParity(_serialPort.Parity); _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); 

All constructors will give the following values:

This constructor uses default property values ​​if none are specified. For example, the DataBits property is 8 by default, the Parity property is None by default, the StopBits property is 1 by default, and the default port name is COM1.

Even shaking hands is the default. If you look at the source code .

 private const Handshake defaultHandshake = Handshake.None; 
+4
source

The problem with your code on this line

 var message = ReceiveSerialPort.ReadLine(); 

You lock your code to wait for the line, if the line never appears, it will stay here forever or the value set to ReadTimeout

So why the line never arrives?

The problem may be an error in WriteLine("Test"); , you must handle errors, or it may be that your input blocks your ReadLine() code before WriteLine("Test") can pass, you can insert Thread.Sleep(100) between, but this does not improve the code.

Note Your code will also work, as sometimes, depending on the conditions of the race.

This synchronized / blocking reading from serial ports seems simple in code with only one line; but it creates many negative side effects in your communication protocol.

A much better solution (given that you like reading / writing data from the microcontroller) is to either use the stream as suggested by Yvette , or use Stream.BeginRead (Byte [], Int32, Int32, AsyncCallback, Object) asynchronously , which I would prefer.

Asynchronous reading will trigger an event when something arrives at the serial port. The main idea of ​​this programming strategy is not to do step-by-step programming, but to expect what will ever work out and then process it correctly.

In a communication protocol with asynchronous reading, AutoResetEvent is very useful, so you send something, then run AutoResetEvent , if the expected result is asynchronously expected, you set this event, and your code can continue if AutoResetEvent and you can handle it with this.

+5
source

It cannot be locked when data is available. What you sent is stuck in the transfer buffer, lost due to a wiring error, caused an error, or was ignored. If it works with another program, a connection error may not be a problem.

Remember that just installing Baudrate is not enough, you should also use the DataBits, Parity and Stopbits properties in accordance with the device settings. A mismatch can cause an error, a view that you can only see when writing an event handler for the ErrorReceived event. Never skip this event, problems may occur if you never check.

And above all, the Handshake property must be set correctly. The correct value depends on how the ports are connected together, too often to not connect them. Start by setting it to Handshake.None, so that an incorrect state for DSR and CTS signals cannot block reception, and an incorrect state for DTR and RTS signals cannot block transmission. Remember that the usual for another program the possibility of hardware establishment of communication, non-compliance is guaranteed to lead to a halt in communication.

If you use synchronous reads instead of the DataReceived event, you should usually deal with the fact that the device is not responding. Or because it is turned off, not connected at all, or does not work. Use the ReadTimeout property to prevent your program from freezing. Strive for 10,000 milliseconds, this is a smart choice.

Beware of the accident of this problem, taking another program, you can easily configure the port correctly, and now it suddenly starts working. And be careful that starting the thread does nothing, now there will be the thread that is stuck, and the Join () call will close.

+2
source

All Articles