HOWTO · Csharp

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

이 자습서에서는 직렬 포트에 대해 설명하고 C#의 SerialPort 클래스를 사용하여 읽기/쓰기 작업을 시연합니다.

이 페이지의 내용

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

직렬 포트

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

C#의 직렬 포트

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

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

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

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

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

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() 등

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

_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를 구현합니다. BaudRate 및 DataBits의 기본값은 공통이므로 사용자가 설정할 필요가 없습니다.

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

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

출력:

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

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

채팅 앱 출력