I had a requirement of communicating on Serial Port in C#. I have tried to leverage the System.IO.Ports.SerialPort class to meet the needs. Here is the class CgSerialPort which derives from SerialPort and provides access to some custom events. Most of the time, the messages which are communicated have a header-message-footer structure. I have kept the same structure in mind while writing this class. Though, if you have a plain structure -message-, just ignore the ExpectedHeaders/ExpectedFooters part, and do not subscribe to the header/footer related events and you will be fine. The XML comments for each class/method/field/property are self explanatory. Enjoy ... 1 // No Copyright © . Use it anywhere you want. 2 3 using System; 4 using System.Collections.Generic; 5 using System.ComponentModel; 6 using System.IO; 7 using System.IO.Ports; 8 using System.Text; 9 10 namespace SerialProto 11 { 12 // ************************************************************************* 13 /// <summary> 14 /// The class represents a serial port resource. 15 /// </summary> 16 /// <remarks> 17 /// <para>The serial port on a PC is a full-duplex device meaning that 18 /// it can send and receive data at the same time. In order to be able to 19 /// do this, it uses separate lines for transmitting and receiving data. 20 /// Some types of serial devices support only one-way communication, and 21 /// therefore, use only two wires in the cable - the transmit line and the 22 /// signal ground. 23 /// </para> 24 /// <para> In serial communication, a byte of data is transferred through a 25 /// single wire one bit at a time. The packets contain a start bit, data, 26 /// and stop bit. Once the start bit has been sent, the transmitter sends 27 /// the actual data bits. There may either be 5, 6, 7, or 8 data bits, 28 /// depending on the number you have selected. Both receiver and the 29 /// transmitter must agree on the number of data bits, as well as the 30 /// baud rate. 31 /// </para> 32 /// <para> A Null Modem cable simply crosses the receive and transmit lines 33 /// so that transmit on one end is connected to receive on the other end 34 /// and vice versa. In addition to transmit and receive, DTR & DSR, as well 35 /// as RTS & CTS are also crossed in a Null Modem connection. 36 /// </para> 37 /// <para> 38 /// The pin (Male RS232 DB9) looks like this on a 9 pin connection on a DTE 39 /// device: 40 /// ------------------ 41 /// \ 1 2 3 4 5 / 42 /// \ 6 7 8 9 / 43 /// -------------- 44 /// or in some of the pins it may be like this: 45 /// ------------------ 46 /// \ 5 4 3 2 1 / 47 /// \ 9 8 7 6 / 48 /// -------------- 49 /// Here is what each pin is usually meant for: 50 /// Pin # Direction of signal 51 /// 1 Carrier detect (CD) 52 /// 2 Received data (RD) 53 /// 3 Transmitted data (TD) 54 /// 4 Data terminal ready (DTR) 55 /// 5 Signal ground common reference voltage 56 /// 6 Data set ready (DSR) 57 /// 7 Request to send (RTS) 58 /// 8 Clear to send (CTS) 59 /// 9 Ring indicator (RI) (from DCE) incoming signal from modem 60 /// </para> 61 /// <para>If you do not want to use any handshake, you will use three wire 62 /// connections in which you will connect pin 2(RD) of one connector to 63 /// pin 3(TD) of the other. For both the connectors, connect pin 5 (ground) 64 /// of both the connectors with each other (common ground).If you want, 65 /// you can use only one PC as both transmitter and receiver for test 66 /// communication. Then, just take a DB 9 connector and a small wire, and 67 /// connect pin no 2 and 3 using the wire that will connect a loop back. 68 /// That is, whatever you will send, the same data you will be receiving. 69 /// </para> 70 /// <para><seealso cref="SerialPort"/></para> 71 /// <author>Authors:Praveen K. Jha</author> 72 /// </remarks> 73 public class CgSerialPort : SerialPort 74 { 75 #region events and delegates 76 77 /// <summary> Serial port message header received event.</summary> 78 [field: NonSerialized] 79 public event EventHandler<CgSerialPortEventArgs> HeaderReceived; 80 /// <summary> Serial port message footer received event.</summary> 81 [field: NonSerialized] 82 public event EventHandler<CgSerialPortEventArgs> FooterReceived; 83 /// <summary> Serial port message data received event.</summary> 84 [field: NonSerialized] 85 public event EventHandler<CgSerialPortEventArgs> MessageReceived; 86 /// <summary> Serial port header data receive error event.</summary> 87 [field: NonSerialized] 88 public event EventHandler<CgSerialPortEventArgs> HeaderRecvError; 89 /// <summary> Serial port footer data receive error event.</summary> 90 [field: NonSerialized] 91 public event EventHandler<CgSerialPortEventArgs> FooterRecvError; 92 /// <summary> Serial port message data receive error event.</summary> 93 [field: NonSerialized] 94 public event EventHandler<CgSerialPortEventArgs> MessageRecvError; 95 /// <summary> Serial port error event.</summary> 96 [field: NonSerialized] 97 public event EventHandler<CgSerialPortEventArgs> PortError; 98 99 //********************************************************************** 100 /// <summary> 101 /// Delegate for use by this class to manage data received. 102 /// </summary> 103 /// <remarks> 104 /// The delegate is set by <see cref="CgSerialPort"/> and is invoked 105 /// during the DataReceived event handling. 106 /// </remarks> 107 private delegate void DataReceivedCb(); 108 109 #endregion events and delegates 110 111 #region private fields 112 113 /// <summary>The Delegate for use by this class to manage data received. 114 /// The delegate is set by <see cref="CgSerialPort"/> and is invoked 115 /// during the DataReceived event handling.</summary> 116 [NonSerialized] 117 private DataReceivedCb DataRcvdCb; 118 119 /// <summary> Read/write timeout values in milliseconds.</summary> 120 private const int TIMEOUT = 500; 121 private SerialDataReceivedEventHandler DataRcvdHandler; 122 private IList<char> m_expectedHeaders; 123 private IList<char> m_expectedFooters; 124 125 private int m_headerIndex = -1; 126 private int m_footerIndex = -1; 127 private StringBuilder m_sbHdr; 128 private StringBuilder m_sbFtr; 129 130 #endregion private fields 131 132 #region Constructors and overrides 133 134 // ********************************************************************* 135 /// <summary> 136 /// Initializes a new instance of the <see cref="CgSerialPort"/> class. 137 /// </summary> 138 public CgSerialPort() : base() 139 { 140 this.Parity = Parity.Even; 141 this.ReadTimeout = TIMEOUT; 142 this.WriteTimeout = TIMEOUT; 143 } 144 145 // ********************************************************************* 146 /// <summary> 147 /// Initializes a new instance of the <see cref="CgSerialPort"/> class 148 /// using the specified port name. 149 /// </summary> 150 /// <param name="portName"> The port to use (for example, COM1).</param> 151 /// <exception cref="IOException"> 152 /// The specified port could not be found or opened. 153 /// </exception> 154 public CgSerialPort(string portName) 155 : base(portName) 156 { 157 this.Parity = Parity.Even; 158 } 159 160 // ********************************************************************* 161 /// <summary> 162 /// Initializes a new instance of the <see cref="CgSerialPort"/> class 163 /// using the specified port name. 164 /// </summary> 165 /// <param name="portName"> The port to use (for example, COM1).</param> 166 /// <param name="baudRate">The baud rate.</param> 167 /// <exception cref="IOException"> 168 /// The specified port could not be found or opened. 169 /// </exception> 170 public CgSerialPort(string portName, int baudRate) 171 : base(portName, baudRate) 172 { 173 this.Parity = Parity.Even; 174 } 175 176 // ********************************************************************* 177 /// <summary> 178 /// Initializes a new instance of the <see cref="CgSerialPort"/> class 179 /// using the specified port name. 180 /// </summary> 181 /// <param name="portName"> The port to use (for example, COM1).</param> 182 /// <param name="baudRate">The baud rate.</param> 183 /// <param name="parity">One of the <see cref="SerialPort.Parity"/> 184 /// values.</param> 185 /// <exception cref="IOException"> 186 /// The specified port could not be found or opened. 187 /// </exception> 188 public CgSerialPort(string portName, int baudRate, Parity parity) 189 :base(portName, baudRate, parity) 190 { 191 } 192 193 // ********************************************************************* 194 /// <summary> 195 /// Initializes a new instance of the <see cref="CgSerialPort"/> class 196 /// using the specified port name. 197 /// </summary> 198 /// <param name="portName"> The port to use (for example, COM1).</param> 199 /// <param name="baudRate"> The baud rate.</param> 200 /// <param name="parity"> One of the <see cref="SerialPort.Parity"/> 201 /// <param name="dataBits"> The databits value.</param> 202 /// values.</param> 203 /// <exception cref="IOException"> 204 /// The specified port could not be found or opened. 205 /// </exception> 206 public CgSerialPort(string portName, int baudRate, Parity parity, 207 int dataBits) 208 : base(portName, baudRate, parity, dataBits) 209 { 210 } 211 212 // ********************************************************************* 213 /// <summary> 214 /// Initializes a new instance of the <see cref="CgSerialPort"/> class 215 /// using the specified port name. 216 /// </summary> 217 /// <param name="portName"> The port to use (for example, COM1).</param> 218 /// <param name="baudRate"> The baud rate.</param> 219 /// <param name="parity"> One of the <see cref="SerialPort.Parity"/> 220 /// <param name="dataBits"> The databits value.</param> 221 /// <param name="stopBits"> One of the <see cref="SerialPort.StopBits"/> 222 /// values.</param> 223 /// values.</param> 224 /// <exception cref="IOException"> 225 /// The specified port could not be found or opened. 226 /// </exception> 227 public CgSerialPort(string portName, int baudRate, Parity parity, 228 int dataBits, StopBits stopBits) 229 : base(portName, baudRate, parity, dataBits, stopBits) 230 { 231 } 232 233 //********************************************************************** 234 /// <summary> 235 /// Releases the unmanaged resources used by this class and 236 /// optionally releases the managed resources. 237 /// </summary> 238 /// <param name="disposing"><see langword="true"/> to release both 239 /// managed and unmanaged resources; <see langword="false"/> to release 240 /// only unmanaged resources.</param> 241 protected override void Dispose(bool disposing) 242 { 243 if (disposing) 244 { 245 // Free managed objects here; set references to null. 246 } 247 // Free unmanaged objects here; set references to null. 248 base.Dispose(disposing); 249 } 250 251 #endregion Constructors and overrides 252 253 #region Utility methods and properties 254 255 // ********************************************************************* 256 /// <summary> 257 /// Gets or sets the list of char values which are expected to be 258 /// received in header. 259 /// </summary> 260 /// <value> A list of char values.</value> 261 public IList<char> ExpectedHeaders 262 { 263 get { return m_expectedHeaders; } 264 set { m_expectedHeaders = value; } 265 } 266 267 // ********************************************************************* 268 /// <summary> 269 /// Gets or sets the list of char values which are expected to be 270 /// received in footer. 271 /// </summary> 272 /// <value> A list of char values.</value> 273 public IList<char> ExpectedFooters 274 { 275 get { return m_expectedFooters; } 276 set { m_expectedFooters = value; } 277 } 278 279 // ********************************************************************* 280 /// <summary> 281 /// Starts the serial port communication on the specified port. 282 /// </summary> 283 /// <returns> <see langword="true"/> if the serial port was opened and 284 /// started successfully; <see langword="false"/> otherwise.</returns> 285 public bool Start() 286 { 287 bool success = false; 288 try 289 { 290 this.Open(); 291 DataRcvdHandler = 292 new SerialDataReceivedEventHandler(HandleDataReceived); 293 this.DataReceived += DataRcvdHandler; 294 DataRcvdCb = ReadHeader; 295 success = true; 296 } 297 catch (Exception e) 298 { 299 // Do error handling 300 OnPortError(new CgSerialPortEventArgs(e.ToString())); 301 } 302 return success; 303 } 304 305 // ********************************************************************* 306 /// <summary> 307 /// Stops communicating on serial port and closes it. 308 /// </summary> 309 public void Stop() 310 { 311 this.DataReceived -= DataRcvdHandler; 312 DataRcvdCb = null; 313 this.Close(); 314 } 315 316 #endregion Utility methods and properties 317 318 #region Message data receive handling 319 320 // ********************************************************************* 321 /// <summary> 322 /// Handles the <see cref="SerialPort.DataReceived"/> event for serial port. 323 /// </summary> 324 /// <param name="sender">The original object who started this event.</param> 325 /// <param name="e">A <see cref="SerialDataReceivedEventArgs"/> 326 /// containing the event data.</param> 327 private void HandleDataReceived 328 ( 329 object sender, 330 SerialDataReceivedEventArgs e 331 ) 332 { 333 DataRcvdCb(); 334 } 335 336 // ********************************************************************* 337 /// <summary> 338 /// Reads the header of the message (if any). 339 /// </summary> 340 private void ReadHeader() 341 { 342 // See if we've already received header details 343 if (ExpectedHeaders != null && ExpectedHeaders.Count > 0 && 344 m_headerIndex < ExpectedHeaders.Count - 1) 345 { 346 m_headerIndex++; 347 try 348 { 349 if (m_sbHdr == null) m_sbHdr = new StringBuilder(); 350 // Read the next available header 351 string hdr = this.ReadTo(ExpectedHeaders[m_headerIndex].ToString()); 352 m_sbHdr.Append(hdr); 353 if (m_headerIndex == ExpectedHeaders.Count - 1) 354 { 355 m_sbHdr.Append(((List<char>) ExpectedHeaders).ToArray()); 356 DataRcvdCb = ReadMessage; 357 OnHeaderReceived(new CgSerialPortEventArgs(m_sbHdr.ToString())); 358 } 359 } 360 catch (TimeoutException) 361 { 362 // Handle timeout exception 363 OnHeaderRecvError(new CgSerialPortEventArgs(m_sbHdr.ToString())); 364 } 365 } 366 else 367 { 368 DataRcvdCb = ReadMessage; 369 ReadMessage(); 370 } 371 } // end ReadHeader 372 373 // ********************************************************************* 374 /// <summary> 375 /// Reads the footer of the message (if any). 376 /// </summary> 377 private void ReadFooter() 378 { 379 // See if we've already received header details 380 if (ExpectedFooters != null && ExpectedFooters.Count > 0 && 381 m_footerIndex < ExpectedFooters.Count - 1) 382 { 383 m_footerIndex++; 384 try 385 { 386 if (m_sbFtr == null) m_sbFtr = new StringBuilder(); 387 // Read the next available footer 388 string ftr = this.ReadTo(ExpectedFooters[m_footerIndex].ToString()); 389 m_sbFtr.Append(ftr); 390 if (m_footerIndex == ExpectedFooters.Count - 1) 391 { 392 m_sbFtr.Append(((List<char>) ExpectedFooters).ToArray()); 393 DataRcvdCb = ReadHeader; 394 OnFooterReceived(new CgSerialPortEventArgs(m_sbFtr.ToString())); 395 } 396 } 397 catch (TimeoutException) 398 { 399 // Handle timeout exception 400 OnFooterRecvError(new CgSerialPortEventArgs(m_sbFtr.ToString())); 401 } 402 } 403 else 404 { 405 DataRcvdCb = ReadHeader; 406 ReadHeader(); 407 } 408 } // end ReadFooter 409 410 // ********************************************************************* 411 /// <summary> 412 /// Reads the full message content. 413 /// </summary> 414 private void ReadMessage() 415 { 416 // See if we've already received header details 417 if (ExpectedFooters != null && ExpectedFooters.Count > 0) 418 { 419 string msg = string.Empty; 420 try 421 { 422 m_footerIndex = 0; 423 string ftrStart = ExpectedFooters[0].ToString(); 424 // Read the message content 425 msg = this.ReadTo(ftrStart); 426 DataRcvdCb = ReadFooter; 427 OnMessageReceived(new CgSerialPortEventArgs(msg)); 428 if (ExpectedFooters.Count == 1) 429 { 430 // There is only one footer character, meaning we've already 431 // received all footers 432 StringBuilder sb = new StringBuilder(); 433 DataRcvdCb = ReadHeader; 434 OnFooterReceived(new CgSerialPortEventArgs(ftrStart)); 435 } 436 } 437 catch (TimeoutException) 438 { 439 // Handle timeout exception 440 OnMessageRecvError(new CgSerialPortEventArgs(msg.ToString())); 441 } 442 } 443 else 444 { 445 // Nothing in footer is specified, so assume that newline is the 446 // end of message. 447 // Read the message content 448 string msg = this.ReadTo(this.NewLine); 449 DataRcvdCb = ReadFooter; 450 OnMessageReceived(new CgSerialPortEventArgs(msg)); 451 } 452 } // end ReadMessage 453 454 //********************************************************************** 455 /// <summary> 456 /// Raise header received notification event for registered listeners. 457 /// </summary> 458 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 459 /// associated with this notification event.</param> 460 private void OnHeaderReceived(CgSerialPortEventArgs e) 461 { 462 EventHandler<CgSerialPortEventArgs> h = HeaderReceived; 463 if (h != null) 464 { 465 h(this, e); 466 } 467 m_headerIndex = -1; 468 m_sbHdr = null; 469 } 470 471 //********************************************************************** 472 /// <summary> 473 /// Raise header receive error notification event for registered listeners. 474 /// </summary> 475 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 476 /// associated with this notification event.</param> 477 private void OnHeaderRecvError(CgSerialPortEventArgs e) 478 { 479 EventHandler<CgSerialPortEventArgs> h = HeaderRecvError; 480 if (h != null) 481 { 482 h(this, e); 483 } 484 m_headerIndex = -1; 485 m_sbHdr = null; 486 DataRcvdCb = ReadMessage; 487 } 488 489 //********************************************************************** 490 /// <summary> 491 /// Raise footer received notification event for registered listeners. 492 /// </summary> 493 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 494 /// associated with this notification event.</param> 495 private void OnFooterReceived(CgSerialPortEventArgs e) 496 { 497 EventHandler<CgSerialPortEventArgs> h = FooterReceived; 498 if (h != null) 499 { 500 h(this, e); 501 } 502 m_footerIndex = -1; 503 m_sbFtr = null; 504 } 505 506 //********************************************************************** 507 /// <summary> 508 /// Raise footer receive error notification event for registered listeners. 509 /// </summary> 510 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 511 /// associated with this notification event.</param> 512 private void OnFooterRecvError(CgSerialPortEventArgs e) 513 { 514 EventHandler<CgSerialPortEventArgs> h = FooterRecvError; 515 if (h != null) 516 { 517 h(this, e); 518 } 519 m_footerIndex = -1; 520 m_sbFtr = null; 521 DataRcvdCb = ReadHeader; 522 } 523 524 //********************************************************************** 525 /// <summary> 526 /// Raise message received notification event for registered listeners. 527 /// </summary> 528 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 529 /// associated with this notification event.</param> 530 private void OnMessageReceived(CgSerialPortEventArgs e) 531 { 532 EventHandler<CgSerialPortEventArgs> h = MessageReceived; 533 if (h != null) 534 { 535 h(this, e); 536 } 537 m_headerIndex = -1; 538 } 539 540 //********************************************************************** 541 /// <summary> 542 /// Raise message receive error notification event for registered listeners. 543 /// </summary> 544 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 545 /// associated with this notification event.</param> 546 private void OnMessageRecvError(CgSerialPortEventArgs e) 547 { 548 EventHandler<CgSerialPortEventArgs> h = MessageRecvError; 549 if (h != null) 550 { 551 h(this, e); 552 } 553 m_headerIndex = -1; 554 m_footerIndex = -1; 555 DataRcvdCb = ReadFooter; 556 } 557 558 //********************************************************************** 559 /// <summary> 560 /// Raises port open errors to registered listeners. 561 /// </summary> 562 /// <param name="e">The <see cref="CgSerialPortEventArgs"/> instance 563 /// associated with this notification event.</param> 564 private void OnPortError(CgSerialPortEventArgs e) 565 { 566 EventHandler<CgSerialPortEventArgs> h = PortError; 567 if (h != null) 568 { 569 h(this, e); 570 } 571 } 572 573 #endregion Message data receive handling 574 575 } // end class CgSerialPort 576 } // end namespace SerialProto 577 // No Copyright © . Use it anywhere you want. 578 579 using System; 580 581 namespace SerialProto 582 { 583 // ************************************************************************* 584 /// <summary> 585 /// An eventargs class to cater to the <see cref="CgSerialPort"/> class needs. 586 /// </summary> 587 /// <remarks> 588 /// <para><seealso cref="System.IO.Ports.SerialPort"/></para> 589 /// <author>Authors:Praveen K. Jha</author> 590 /// </remarks> 591 public class CgSerialPortEventArgs : EventArgs 592 { 593 private string m_message; 594 595 // ********************************************************************* 596 /// <summary> 597 /// Initializes a new instance of the <see cref="CgSerialPortEventArgs"/> 598 /// class. 599 /// </summary> 600 /// <param name="message"> The message that is received.</param> 601 public CgSerialPortEventArgs(string message) 602 { 603 m_message = message; 604 } 605 606 // ********************************************************************* 607 /// <summary> 608 /// Gets the message associated with this eventargs. 609 /// </summary> 610 /// <value> The message string.</value> 611 public string Message 612 { 613 get { return m_message; } 614 } 615 616 } // end class CgSerialPortEventArgs 617 } // end namespace SerialProto 618 using System; 619 using System.Collections.Generic; 620 using System.IO.Ports; 621 622 using SerialProto; 623 624 public class PortChat 625 { 626 static bool _continue; 627 static CgSerialPort _serialPort; 628 629 public static void Main() 630 { 631 string name; 632 string message; 633 StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; 634 635 // Create a new SerialPort object with default settings. 636 _serialPort = new CgSerialPort(); 637 638 // Allow the user to set the appropriate properties. 639 _serialPort.PortName = SetPortName(_serialPort.PortName); 640 _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); 641 _serialPort.Parity = SetPortParity(_serialPort.Parity); 642 _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); 643 _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); 644 _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); 645 646 // Set the read/write timeouts 647 _serialPort.ReadTimeout = 500; 648 _serialPort.WriteTimeout = 500; 649 650 _serialPort.MessageReceived += 651 new EventHandler<CgSerialPortEventArgs>(_serialPort_MessageReceived); 652 _serialPort.PortError += 653 new EventHandler<CgSerialPortEventArgs>(_serialPort_PortError); 654 _serialPort.MessageRecvError += 655 new EventHandler<CgSerialPortEventArgs>(_serialPort_MessageRecvError); 656 657 // Uncomment these if you have header/footer requirements 658 //_serialPort.HeaderReceived += 659 // new EventHandler<CgSerialPortEventArgs>(_serialPort_HeaderReceived); 660 //_serialPort.FooterReceived += 661 // new EventHandler<CgSerialPortEventArgs>(_serialPort_FooterReceived); 662 //List<char> expHdr = new List<char>(); 663 //expHdr.Add('?'); 664 //expHdr.Add('?'); 665 //List<char> expFtr = new List<char>(); 666 //expFtr.Add('?'); 667 //expFtr.Add('?'); 668 //_serialPort.ExpectedHeaders = expHdr; 669 //_serialPort.ExpectedFooters = expFtr; 670 //_serialPort.HeaderRecvError += 671 // new EventHandler<CgSerialPortEventArgs>(_serialPort_HeaderRecvError); 672 //_serialPort.FooterRecvError += 673 // new EventHandler<CgSerialPortEventArgs>(_serialPort_FooterRecvError); 674 675 if (_serialPort.Start()) 676 { 677 _continue = true; 678 679 Console.Write("Name: "); 680 name = Console.ReadLine(); 681 682 Console.WriteLine("Type QUIT to exit"); 683 684 while (_continue) 685 { 686 message = Console.ReadLine(); 687 688 if (stringComparer.Equals("quit", message)) 689 { 690 _continue = false; 691 } 692 else 693 { 694 Console.WriteLine("XMIT:" + message); 695 _serialPort.WriteLine(message); 696 } 697 } 698 699 _serialPort.Stop(); 700 } 701 else 702 { 703 Console.ReadLine(); 704 } 705 } 706 707 static void _serialPort_MessageRecvError(object sender, CgSerialPortEventArgs e) 708 { 709 Console.WriteLine("Msg RECV error" + e.Message); 710 } 711 712 static void _serialPort_FooterRecvError(object sender, CgSerialPortEventArgs e) 713 { 714 Console.WriteLine("Ftr RECV error" + e.Message); 715 } 716 717 static void _serialPort_HeaderRecvError(object sender, CgSerialPortEventArgs e) 718 { 719 Console.WriteLine("Hdr RECV error" + e.Message); 720 } 721 722 static void _serialPort_PortError(object sender, CgSerialPortEventArgs e) 723 { 724 Console.WriteLine( e.Message); 725 } 726 727 static void _serialPort_MessageReceived(object sender, CgSerialPortEventArgs e) 728 { 729 Console.WriteLine("RECVMSG:" + e.Message); 730 } 731 732 static void _serialPort_FooterReceived(object sender, CgSerialPortEventArgs e) 733 { 734 Console.WriteLine("RECVFTR:" + e.Message); 735 } 736 737 static void _serialPort_HeaderReceived(object sender, CgSerialPortEventArgs e) 738 { 739 Console.WriteLine("RECVHDR:" + e.Message); 740 } 741 742 743 public static string SetPortName(string defaultPortName) 744 { 745 string portName; 746 747 Console.WriteLine("Available Ports:"); 748 foreach (string s in SerialPort.GetPortNames()) 749 { 750 Console.WriteLine(" {0}", s); 751 } 752 753 Console.Write("COM port({0}): ", defaultPortName); 754 portName = Console.ReadLine(); 755 756 if (portName == "") 757 { 758 portName = defaultPortName; 759 } 760 return portName; 761 } 762 763 public static int SetPortBaudRate(int defaultPortBaudRate) 764 { 765 string baudRate; 766 767 Console.Write("Baud Rate({0}): ", defaultPortBaudRate); 768 baudRate = Console.ReadLine(); 769 770 if (baudRate == "") 771 { 772 baudRate = defaultPortBaudRate.ToString(); 773 } 774 775 return int.Parse(baudRate); 776 } 777 778 public static Parity SetPortParity(Parity defaultPortParity) 779 { 780 string parity; 781 782 Console.WriteLine("Available Parity options:"); 783 foreach (string s in Enum.GetNames(typeof(Parity))) 784 { 785 Console.WriteLine(" {0}", s); 786 } 787 788 Console.Write("Parity({0}):", defaultPortParity.ToString()); 789 parity = Console.ReadLine(); 790 791 if (parity == "") 792 { 793 parity = defaultPortParity.ToString(); 794 } 795 796 return (Parity) Enum.Parse(typeof(Parity), parity); 797 } 798 799 public static int SetPortDataBits(int defaultPortDataBits) 800 { 801 string dataBits; 802 803 Console.Write("Data Bits({0}): ", defaultPortDataBits); 804 dataBits = Console.ReadLine(); 805 806 if (dataBits == "") 807 { 808 dataBits = defaultPortDataBits.ToString(); 809 } 810 811 return int.Parse(dataBits); 812 } 813 814 public static StopBits SetPortStopBits(StopBits defaultPortStopBits) 815 { 816 string stopBits; 817 818 Console.WriteLine("Available Stop Bits options:"); 819 foreach (string s in Enum.GetNames(typeof(StopBits))) 820 { 821 Console.WriteLine(" {0}", s); 822 } 823 824 Console.Write("Stop Bits({0}):", defaultPortStopBits.ToString()); 825 stopBits = Console.ReadLine(); 826 827 if (stopBits == "") 828 { 829 stopBits = defaultPortStopBits.ToString(); 830 } 831 832 return (StopBits) Enum.Parse(typeof(StopBits), stopBits); 833 } 834 835 public static Handshake SetPortHandshake(Handshake defaultPortHandshake) 836 { 837 string handshake; 838 839 Console.WriteLine("Available Handshake options:"); 840 foreach (string s in Enum.GetNames(typeof(Handshake))) 841 { 842 Console.WriteLine(" {0}", s); 843 } 844 845 Console.Write("Handshake({0}):", defaultPortHandshake.ToString()); 846 handshake = Console.ReadLine(); 847 848 if (handshake == "") 849 { 850 handshake = defaultPortHandshake.ToString(); 851 } 852 853 return (Handshake) Enum.Parse(typeof(Handshake), handshake); 854 } 855 }
The CgSerialPort class uses and EventArgs class to notify the subscribers. It just has a property which contains the message that is received (or partial/error message in case of error). And here is the code for the CgSerialPortEventArgs:
Finally here is the sample project file which will demonstrate the use of the above classes. Just copy paste the codes here in your project and you should be good to go.
Let me know how you think the codes helped you ... :)
Thursday, April 2, 2009
Serial Port Communication in C#
Stumble
del.icio.us
Reddit
MyWeb!
Facebook
Google bookmark
Subscribe to:
Post Comments (Atom)
which compiler should I use to successfully use this code? I have MS Visual C/C++ v.1.52 for DOS and Windows. Can I use the code and make an exe file with my compiler? Or should I go and get MS Visual Studio .Net 2003 Professional?
ReplyDeletemy e-mail: gk1@onet.eu
You will need Visual studio 2005 or above to compile this code. Check http://www.microsoft.com/exPress/download/.
ReplyDeleteDear Sir,
ReplyDeleteWhich is better for this project:
Visual Studio 2005 Standard or Visual Studio 2005 Professional?
Best regards
Greg Krupinski
Greg,
ReplyDeleteYou could use any of these editions. They are equally good. VS 2005 Pro just gives you a few more options. See http://msdn.microsoft.com/en-us/vstudio/aa700921.aspx for comparison.
Thx
Dear Praveen,
ReplyDeleteDo you have any simple C/C++ program for RS232 port that could be compiled with MS VC/C++ ver.1.52 for DOS/Windows.
I prefer Microsoft, since this was my first compiler, and I still use it for simple programming under DOS and Windows 98.
There must be a way of using either simple assembler code with direct register handling, or making simple functions to control the serial ports without much of a headache.
=====================================================================================================
Have you ever tried to do it with Borland Turbo Pascal, Borland Pascal 7.0, Borland Delphi or Borland C++ 4.2 all for DOS/Win'98?
I will appreciate any suggestions from your experience.
All I need is a simple connection between the screen (DOS/Win'98)) or Windows Form(Windows XP) and the RS232 port with writing all bytes to a text datafile as long as the port is open and data is received - all written in C/C++ (MS Visual C/C++ 5.0 or MSVC/C++ 1.52)
I have bought the MS Visual Studio 2003 .Net Professional a year ago, but I could not find any SerialPort Component in it, and they told me it was included with Visual Studio 2005 Professional. So now I either use old DOS machine with good old compiler for DOS?Win'98 or I need to buy the whole MSVS 2005 Pro.
Next I will need to receive, send confirmation character (or string) to the port and then receive the next record from the serial device connected to the serial port.
I had many modules like this in the past, but they told me they were obsolete, and the old computer was scrapped.
After many years of working with ready made applications I see the need to recover old programming solutions for simple dataloggers etc. with RS232 ports.
Many old programs written with MSVC/C++ 1.52 for Windows 98 are running successfully under Windows XP, so I would very much tru to continue with the simple compiler and use it for RS232 programming (under Windows XP).
Is this possible?
Thank you for you help
Greg
Hi Greg,
ReplyDeleteI am sure, at some point I had written a small piece of code for VS 2003 when there was no serial port support in .Net. I can't find it right now. If I do, I'll send it to you or publish it on my blog. I would suggest at this time to see the following links which I think might help you:
For VS2003:
* http://msdn.microsoft.com/en-us/magazine/cc301786.aspx
* http://www.lvr.com/serport.htm
For Borland C++:
* http://www.activexperts.com/activcomport/howto/cppbuilder/
* http://www.daniweb.com/forums/thread56329.html#
* http://simpleserial.com/
Hope this helps. Good luck!
-Praveen
Unfortunate the .NET 2.0/3.4 seems to have lots of known problems with handling the serial!
ReplyDeleteI found this article:
http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm
Thats really sad.
Im not sure how it would work with the old WIN32 API calls and than write an wrapper class ??
Im planning to use serial-232 for a datalogger, but im not sure anymore if it can be trusted in WIN32 at all!