본문으로 바로가기
반응형

오늘은 C#을 이용한 시리얼 통신을 구현하는 방법에 대해 포스팅을 하려고 합니다. C# 도구 상자에 Serial port가 있기 때문에 윈폼에 추가하고 MS 홈페이지에 있는 예제를 이용해 시리얼 통신을 간단하게 구현할 수 있으며, 방법을 모르더라도 구글링을 통해 쉽게 구현 가능합니다. 시리얼은 디버깅 용도로도 많이 사용하고 응용할 곳이 많기 때문에 알아두면 좋을 것 같습니다. 시리얼 포트를 만들기 위해서 어떤게 필요한지 COM목록을 가져오기 위해서 어떻게 해야되는지 위주로 보시면 될것 같습니다.

 

간단한 구현을 위해서 우선 디자인 탭 왼쪽에서 도구상자에 있는 폼을 이용해 위와 같이 만들어 줍니다. 첫 번째 콤보 박스는 COM 포트, 두 번째 콤보 박스는 Baud Rate를 선택하기 위해 추가를 하였습니다. 우측에 텍스트 박스는 통신 상태를 디버깅하기 위해 추가를 하였습니다.

 

Form을 다 추가하였다면 도구 상자에서 SerialPort를 추가합니다. 

 

 

Baud Rate 콤보 박스를 클릭하여 항목 편집을 클릭 후 Baud Rate를 추가합니다. COM 콤보 박스는 장치 관리자에서 찾은 포트를 검색하여 자동으로 추가 되게 구현을 할 것이라 따로 추가하지 않습니다.

 

항목 편집을 클릭하면 위에 와 같은 창이 뜨는데 저는 간단하게 115200bps, 19200bps를 추가했습니다.

 

사용하고 있는 COM 포트는 장치 관리자를 통해서 확인 가능합니다. 포트는 COM9, COM10 2개입니다. 이제 소스 코드 구성을 살펴보겠습니다.

 

소스 코드 구성

 

 

1
2
3
4
5
6
7
8
9
10
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

시리얼 통신을 하기 위해서는 using System.IO.Ports를 추가해야 합니다. 여기에는 직렬 포트를 제어하는 클래스가 포함되어 있습니다.
 
1
2
3
4
5
SerialPort.PortName = Port_Combox.SelectedItem.ToString();                        
SerialPort.BaudRate = int.Parse(Baud_Combox.SelectedItem.ToString());
SerialPort.DataBits = 8;
SerialPort.StopBits = StopBits.One;
SerialPort.Parity = Parity.None;
 

시리얼 통신을 하기 위해서 필요한 통신 규약들입니다. int.Parse는 이전에 BaudRate 콤보 박스에 입력한 스트링 값 115200, 19200을 int형으로 변환하기 위해서 추가를 하였습니다.

 

1
2
3
4
5
6
string[] PortNames = SerialPort.GetPortNames();
 
foreach (string portnumber in PortNames)
{
    Port_Combox.Items.Add(portnumber);
}

GetPortName을 이용하면 현재 사용하고 있는 COM의 목록을 가져옵니다. 이는 장치 관리자에서 확인하였던 포트와 동일합니다. 이제 전체 코드를 확인하겠습니다.

 

소스 코드 전체

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
sing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports; // 직렬 포트 제어 클래스 포함
 
namespace Port_Open
{
    public partial class Form1 : Form
    {
        string str;
 
        public Form1()
        {
            InitializeComponent();
            string[] PortNames = SerialPort.GetPortNames();  // 포트 검색.
 
            foreach (string portnumber in PortNames)
            {
                Port_Combox.Items.Add(portnumber);          // 검색한 포트를 콤보박스에 입력. 
            }
 
        }
 
        private void Close_btn_Click(object sender, EventArgs e)
        {
            if (SerialPort1.IsOpen == true)
            {
               SerialPort1.Close();
               //Timer1.Stop();             // Timer Stop
                textBox1.Text += "해제되었습니다." + Environment.NewLine;
            }
            else textBox1.Text += "해제되어 있습니다 ." + Environment.NewLine;           
        }
 
        private void Open_btn_Click(object sender, EventArgs e)
        {
            if (SerialPort1.IsOpen == false)
            {
               SerialPort1.PortName = Port_Combox.SelectedItem.ToString();                     //콤보 박스에서 선택.
               SerialPort1.BaudRate = int.Parse(Baud_Combox.SelectedItem.ToString());          //콤보 박스에서 Baud Rate 선택.
               SerialPort1.DataBits = 8;
               SerialPort1.StopBits = StopBits.One;
               SerialPort1.Parity = Parity.None;
               SerialPort1.Open();
               //Timer1.Start();            // Timer Stop
               SerialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); //데이터 받기.
                textBox1.Text += "연결되었습니다." + Environment.NewLine;
 
               SerialPort1.WriteLine("abcd\r\n");                                                    // abcd\r\n Send
            }
            else
            {
                textBox1.Text += "연결되어 있습니다." + Environment.NewLine;
            }
        }
        /*
         * SerialPort.DataReceived Event
         */
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
             str = SerialPort1.ReadExisting();
 
            if (str.Length > 0)
            {
                textBox1.SelectedText += str + Environment.NewLine;
            }
        }
        /*
         * Serial 통신 Setting Box
         */
        private void Port_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Baud_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Databits_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Stopbits_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Parity_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
        /*
         * Send/Receive 데이터 표시
         */
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            textBox1.SelectionStart = textBox1.TextLength;     //스크롤 자동으로 내린다.
            textBox1.ScrollToCaret();
        }
    }
}
 
 

포트를 검색해서 COM 콤보 박스에 입력을 하고 연결을 하면 Port가 Open 되고 해제를 하면 Port가 Close가 되게 됩니다. 그리고 현재 연결 상태 혹은 연결된 Device에서 받은 데이터를 Text Box에 입력을 해주고 있습니다. SerialPort1.DataRecevied Event 예제는 아래의 URL을 통해서 확인 가능합니다.

 

https://docs.microsoft.com/ko-kr/dotnet/api/system.io.ports.serialport.datareceived?view=netframework-4.7.2

 

 

COM 콤보 박스에 정확하게 장치 관리자에 있는 COM9, COM10 포트만 읽어왔습니다. 연결/해제 및 스크롤도 자동으로 잘 내려주고 제대로 동작을 하고 있습니다. 이전에 포스팅 했던 Zedgraph와도 연동해서 사용할 수 있겠네요.

 

 

<Zedgraph 실시간 그래프 그리기>

https://hubbleconstant.tistory.com/2

 

반응형