가상 포트를 만들어 Serial 통신 기능을 구현해보고자 한다.
특정 장비와 Serial 통신을 하고자 한다면 해당 장비가 제공하는 통신 프로토콜을 파악해야 하는데 이 프로토콜을 파악한 것이 맞는지 어떤지 처음에는 확인이 되지 않을수가 있다.
따라서 가상 포트를 만드는 이유는 실제 장비와 Serial 통신을 함에 있어서 정상적으로 데이터 송/수신이 되는지을 확인한다거나 할 때 유용하기 때문에 가상 포트를 통해서 구현해 보고자 한다.
미션 수행은 다음과 같은 단계로 처리가 된다.
-. VSPE(Virtual Serial Port Emulator)를 이용한 가상 포트 만듦
-. Hyper Terminal을 이용해 VSPE가 만든 가상 포트에 연결 해 둠
-. C#에서 VSPE가 만든 가상 포트를 열어 해당 포트에 연결되어 있는 하이퍼터미널과 통신
먼저 VSPE를 설치한다.
SetupVSPE.zip
그리고 가상 포트에 연결될 장비로 여기서는 하이퍼터미널을 사용할 것이다.
역시 하이퍼 터미널을 설치한다.
HyperTerminal_Kor.zip
VSPE를 실행해 보자. 64bit를 사용해 달라는 창이 뜨면 '아니요'를 선택한다.
위의 적색 박스안의 아이콘을 클릭해서 가상 포트를 만들어 보자.
위의 창에서 Device Type을 Connector 상태에서 '다음' 버튼 클릭한다.
위의 창에서 이제 원하는 포트를 선택해서 가상 포트를 하나 만든다. 여기서는 COM9을 선택했다.
이렇게 만들어진 가상 포트에 하이퍼터미널을 연결해서 C# 응용프로그램에서 COM9에 연결된 장비(하이퍼터미널)과 시리얼 통신을 할 것이다.
이제 하이퍼터미널을 실행한다.
새 연결 이름을 포트의 이름과 같이 명명했다. 확인 버튼을 클릭한다.
위의 창에서 '연결에 사용할 모뎀' 항목에 앞에서 만들었던 가상포트(COM9)를 선택한 후 확인 버튼 클릭
포트의 속성 정보를 설정한다. 여기서 속도(비트/초(B)와 '흐름 제어'를 위와 같이 설정한 후 확인을 클릭한다.
파일 - 속성 메뉴를 클릭해서 뜨는 창에서 '설정' 탭을 클릭한다. 그리고 적색 박스 부분의 'ASCII 설정' 버튼을 클릭한다.
ASCII 설정 창이 뜨면 위와 같이 항목들을 체크한다.
이렇게 하는 이유는 하이퍼터미널에서 송/수신 데이터를 화면에 보이도록 하기 위함이다.
이제 통신을 위한 준비 작업은 끝났다.
C#에서 만든 시리얼 통신 프로그램을 실행해서 통신을 해보자.
앞에서 만든 가상 포트에 연결된 하이퍼터미널로 위와 같은 데이터를 전송해 보았다.
이렇게 시리얼 통신이 잘 되고 있다.
아래는 시리얼 통신용 C# 쪽의 소스 코드이다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExSerialCom
{
public partial class Form1 : Form
{
private SerialPort sPort;
private string portName = "Select Port";
private string rxText = "";
public Form1()
{
InitializeComponent();
string[] ptNum = SerialPort.GetPortNames();
for (int i=0; i<ptNum.Length; i++)
{
cmbPort.Items.Add(ptNum[i]);
}
}
private void btnOpen_Click(object sender, EventArgs e)
{
sPort = new SerialPort();
if(portName.Contains("Select"))
{
MessageBox.Show("포트를 선택해 주세요");
return;
}
if(sPort.IsOpen)
{
MessageBox.Show("포트가 이미 열려있습니다");
return;
}
sPort.PortName = portName;
sPort.BaudRate = 9600;
sPort.DataBits = 8;
sPort.Parity = Parity.None;
sPort.DataReceived += Port_DataReceived;
//sPort.ErrorReceived += new SrialErrorReceivedEventHandler(serialPort_ErrorReceived);
sPort.Open();
if(sPort.IsOpen == true)
{
MessageBox.Show("포트 열기 성공");
} else
{
MessageBox.Show("포트 열기 실패");
}
}
private void btnClose_Click(object sender, EventArgs e)
{
if(sPort != null && sPort.IsOpen)
{
sPort.Close();
}
}
private void btnSend_Click(object sender, EventArgs e)
{
if(richTextBox1.Text.Length > 0)
{
//포트 오픈 여부 체크
if(sPort == null || sPort.IsOpen == false)
{
MessageBox.Show("포트를 열어 주세요");
return;
} else
{
sPort.Write(richTextBox1.Text);
}
}
}
private void cmbPort_SelectedIndexChanged(object sender, EventArgs e)
{
portName = cmbPort.SelectedItem.ToString();
}
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
rxText = sPort.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
}
private void DisplayText(object sender, EventArgs s)
{
richTextBox1.Text += rxText;
}
}
}