C#의 직렬 포트에서 읽기 및 쓰기

Aimen Fatima 2023년10월12일
  1. 직렬 포트
  2. C#을 사용하는 직렬 포트 채팅 애플리케이션
C#의 직렬 포트에서 읽기 및 쓰기

이 자습서는 C# 언어의 직렬 포트 개념과 데이터 읽기 및 쓰기 용도를 이해하는 데 도움이 됩니다. 예제 프로젝트를 통해 C#으로 구현된 SerialPort 클래스를 시연합니다.

직렬 포트

당사의 컴퓨터 시스템에는 다양한 목적으로 데이터를 전송할 수 있는 여러 포트가 있습니다. 직렬 포트는 여러 비트를 병렬로 공유하는 것이 아니라 한 번에 한 비트의 데이터를 전송하여 데이터를 순차적으로 전송하는 인터페이스입니다.

C#의 직렬 포트

C#은 프로그램에서 직렬 포트 기능을 구현하기 위한 기본 제공 클래스를 제공합니다. 시스템의 직렬 포트에 연결된 장치로 데이터를 주고받을 수 있습니다.

직렬 포트 클래스를 구현하는 네임스페이스는 System.IO.Ports입니다.

프로그램에서 System.IO.Ports 네임스페이스를 가져오고 정적 클래스 SerialPort의 개체를 생성해야 합니다.

SerialPort 클래스는 기본 생성자를 제공하며 생성자는 오버로드되어 다른 매개변수가 필요합니다. 다음은 기본값과 오버로드된 생성자 중 하나를 사용하여 개체를 초기화하는 예입니다.

다음 코드의 두 번째 줄은 오버로드된 생성자를 사용하여 PortName, BaudRate, Parity, DataBitsStopBits를 초기화합니다.

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

SerialPort 클래스에는 BaudRate, BytesToWrite, BytesToRead, DataBits, Encoding, PortName, Parity 등과 같은 속성이 포함되어 있습니다. 통신을 위한 완전한 기능을 제공하기 위해 수많은 공개 메서드가 구현되었습니다. 예: Close(), GetPortNames(), Open(), Read(), Write()

ReadTimeOutWriteTimeOut과 같은 속성도 다음과 같이 설정할 수 있습니다.

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

필요한 모든 매개변수 값을 설정한 후 Open() 메서드를 사용하여 통신용 포트를 열도록 컴파일러에 알려야 합니다.

_serialPort.Open();

ReadLine() 메서드는 직렬 포트를 통해 수신된 메시지를 읽을 수 있습니다.

string message = _serialPort.ReadLine();

C#을 사용하는 직렬 포트 채팅 애플리케이션

이 섹션에서는 통신을 위해 직렬 포트를 사용하는 채팅 응용 프로그램을 위한 완전한 C# 프로그램을 제시합니다. 이 코드 스니펫은 데이터를 송수신하기 위해 연결된 두 시스템 모두에서 실행되어야 합니다.

참고: null 모뎀 케이블을 사용하여 시스템을 연결하십시오.

Visual Studio에서 C# 프로젝트를 만들고 코드 스니펫을 Program.cs 파일에 붙여넣고 실행합니다.

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);
  }
}

위의 코드 스니펫은 먼저 SerialPort 객체를 생성하고 선택적 속성을 설정하기 위해 setter를 구현합니다. BaudRateDataBits의 기본값은 공통이므로 사용자가 설정할 필요가 없습니다.

Read() 함수는 직렬 포트에서 입력을 읽습니다. 프로그램은 사용자에게 입력 텍스트를 입력하라는 메시지를 표시하고 사용자가 exit를 입력할 때까지 직렬 포트로 보냅니다.

SetPort(), SetParity(), SetStopBits()SetHandshake()는 속성 값을 설정하는 설정자입니다.

출력:

사용자는 사용 가능한 옵션을 선택하여 필요한 값을 설정하라는 메시지가 표시됩니다. 예를 들어 다음 출력에서 Com3, Parity 값을 Odd, StopBitsTwo로 선택했습니다. 핸드셰이크 값은 없음입니다.

매개변수 값을 설정한 후 사용자가 exit를 입력하여 프로그램을 종료할 때까지 직렬 포트를 사용하여 통신이 시작됩니다.

채팅 앱 출력