Leer y escribir desde el puerto serie en C#

Aimen Fatima 12 octubre 2023
  1. Puerto serial
  2. Aplicación de chat de puerto serie usando C#
Leer y escribir desde el puerto serie en C#

Este tutorial lo ayudará a comprender el concepto del puerto serie en lenguaje C# y su uso para la lectura y escritura de datos. Demostraremos la clase SerialPort implementada en C# a través de un proyecto de ejemplo.

Puerto serial

Nuestros sistemas informáticos tienen varios puertos para transferir datos para diversos fines. El puerto serie es una interfaz para transferir datos secuencialmente mediante la transferencia de datos de un bit a la vez en lugar de compartir varios bits en paralelo.

Puerto Serie en C#

C# proporciona una clase integrada para implementar la funcionalidad del puerto serie en su programa. Puede recibir y enviar datos al dispositivo conectado al puerto serie de su sistema.

El espacio de nombres que implementa la clase de puerto serie es System.IO.Ports.

Debe importar el espacio de nombres System.IO.Ports en su programa y crear un objeto de la clase estática SerialPort.

La clase SerialPort proporciona un constructor predeterminado, y los constructores están sobrecargados y requieren diferentes parámetros. El siguiente es el ejemplo de cómo inicializar el objeto usando default y uno de los constructores sobrecargados.

La segunda línea del siguiente código utiliza el constructor sobrecargado para inicializar PortName, BaudRate, Parity, DataBits y StopBits.

static SerialPort _serialPort = new SerialPort();
SerialPort _serialPort = new SerialPort("COM3", 9600, Parity.One, 8, StopBits.Two);

La clase SerialPort contiene propiedades como BaudRate, BytesToWrite, BytesToRead, DataBits, Encoding, PortName, Parity, etc. Se han implementado numerosos métodos públicos para proporcionar una funcionalidad completa para la comunicación, por ejemplo, Close(), GetPortNames(), Open(), Read(), Write(), etc.

También se pueden establecer propiedades como ReadTimeOut y WriteTimeOut, como las siguientes:

_serialPort.ReadTimeout = 1000;
_serialPort.WriteTimeout = 1000;

Después de configurar todos los valores de los parámetros necesarios, debemos notificar al compilador que abra el puerto para la comunicación mediante el método Open().

_serialPort.Open();

El método ReadLine() puede leer el mensaje recibido a través del puerto serie.

string message = _serialPort.ReadLine();

Aplicación de chat de puerto serie usando C#

Esta sección presenta un programa C# completo para una aplicación de chat que utiliza el puerto serie para la comunicación. Este fragmento de código debe ejecutarse en ambos sistemas conectados para enviar y recibir datos.

Nota: Utilice un cable de módem nulo para conectar los sistemas.

Cree un proyecto C# en Visual Studio, pegue el fragmento de código en el archivo Program.cs y ejecútelo.

using System;
using System.IO.Ports;
using System.Threading;

public class MyChatBot {
  static bool _resume;

  // Create a new SerialPort object
  static SerialPort _serialPortObj = new SerialPort();

  public static void Main() {
    string userName;
    string inputMessage;
    Thread read_Thread = new Thread(Read);
    StringComparer string_Comparer = StringComparer.OrdinalIgnoreCase;

    // Set the required attributes.
    _serialPortObj.PortName = SetPort(_serialPortObj.PortName);
    _serialPortObj.Parity = SetParity(_serialPortObj.Parity);

    _serialPortObj.StopBits = SetStopBits(_serialPortObj.StopBits);
    _serialPortObj.Handshake = SetHandshake(_serialPortObj.Handshake);

    // Set the read/write timeouts
    _serialPortObj.ReadTimeout = 1000;
    _serialPortObj.WriteTimeout = 1000;

    _serialPortObj.Open();
    _resume = true;
    read_Thread.Start();

    Console.Write("Enter Your Name: ");
    userName = Console.ReadLine();

    Console.WriteLine("Type Exit to exit");

    while (_resume) {
      inputMessage = Console.ReadLine();

      if (string_Comparer.Equals("exit", inputMessage)) {
        _resume = false;
      } else {
        _serialPortObj.WriteLine(String.Format("<{0}>: {1}", userName, inputMessage));
      }
    }

    read_Thread.Join();

    // Close the serial port
    _serialPortObj.Close();
  }

  public static void Read() {
    while (_resume) {
      try {
        // read the received message
        string _recerivedMessage = _serialPortObj.ReadLine();
        Console.WriteLine(_recerivedMessage);
      }

      catch (TimeoutException) {
      }
    }
  }

  // setters for attributes
  public static string SetPort(string defaultPortName) {
    string newPortName;

    Console.WriteLine("Available Ports:");
    foreach (string a in SerialPort.GetPortNames()) {
      Console.WriteLine("   {0}", a);
    }

    Console.Write("Enter COM port value (Default: {0}): ", defaultPortName);
    newPortName = Console.ReadLine();

    if (newPortName == "" || !(newPortName.ToLower()).StartsWith("com")) {
      newPortName = defaultPortName;
    }
    return newPortName;
  }

  public static Parity SetParity(Parity defaultParity) {
    string parityValue;

    Console.WriteLine("Available Parity Values:");
    foreach (string a in Enum.GetNames(typeof(Parity))) {
      Console.WriteLine("   {0}", a);
    }

    Console.Write("Enter Parity value (Default: {0}):", defaultParity.ToString(), true);
    parityValue = Console.ReadLine();

    if (parityValue == "") {
      parityValue = defaultParity.ToString();
    }

    return (Parity)Enum.Parse(typeof(Parity), parityValue, true);
  }

  public static StopBits SetStopBits(StopBits defaultStopBits) {
    string stopBitValue;

    Console.WriteLine("Available StopBits Values:");
    foreach (string a in Enum.GetNames(typeof(StopBits))) {
      Console.WriteLine("   {0}", a);
    }

    Console.Write(
        "Enter a StopBits value (ArgumentOutOfRangeException occurs for None value. Select another. \n (Default Value: {0}):",
        defaultStopBits.ToString());
    stopBitValue = Console.ReadLine();

    if (stopBitValue == "") {
      stopBitValue = defaultStopBits.ToString();
    }

    return (StopBits)Enum.Parse(typeof(StopBits), stopBitValue, true);
  }

  public static Handshake SetHandshake(Handshake defaultHandshake) {
    string handshakeValue;

    Console.WriteLine("Available Handshake Values:");
    foreach (string a in Enum.GetNames(typeof(Handshake))) {
      Console.WriteLine("   {0}", a);
    }

    Console.Write("Enter Handshake value (Default: {0}):", defaultHandshake.ToString());
    handshakeValue = Console.ReadLine();

    if (handshakeValue == "") {
      handshakeValue = defaultHandshake.ToString();
    }

    return (Handshake)Enum.Parse(typeof(Handshake), handshakeValue, true);
  }
}

El fragmento de código anterior primero crea un objeto SerialPort e implementa los configuradores para establecer atributos opcionales. Los valores predeterminados para BaudRate y DataBits son comunes, por lo que no es necesario que el usuario los establezca.

La función Read() lee la entrada del puerto serie. El programa solicita al usuario que ingrese el texto de entrada y lo envía al puerto serie hasta que el usuario ingresa “salir” como entrada.

Los SetPort(), SetParity(), SetStopBits() y SetHandshake() son setters para establecer los valores de los atributos.

Producción:

Se le pedirá al usuario que establezca los valores requeridos seleccionando las opciones disponibles, por ejemplo, en el siguiente resultado, hemos elegido el valor Com3, Paridad para que sea Odd, StopBits para que sea Dos, y El valor de Apretón de manos será Ninguno.

Después de configurar los valores de los parámetros, la comunicación comenzará utilizando el puerto serie hasta que el usuario ingrese la salida para finalizar el programa.

Salida para la aplicación de chat