Visual Studio를 이용하여 작성을 시작하겠습니다.
프로젝트 실행하시고 Window Forms 앱(.NET Framework) 선택하고 이름 입력하고 [확인] 버튼 누르면 프로젝트가 생성됩니다.
C#에서는 도구 상자에서 SerialPort를 가져오는 방법과 System.IO.Port를 기입하여 관련 네임스페이스에 정의된 내용들을 가져오는 방법이 있습니다.
저는 System.IO.Port를 통해 작성하도록 하겠습니다.
Using문을 통해 해당 네임스페이스를 등록하도록 하겠습니다.
Serial Port를 열기 위해 가장 중요한 파라미터는
- 포트 번호
- buadrate : 전송 속도
- Data Bit
- Parity Bit
- Stop Bit
위의 파라미터가 설정되어 객체를 인스턴스하면 통신이 됩니다.
대략적으로 UI 는 다음과 같이 작성하였습니다.
Find Port 버튼을 누르면 [ Port ] 라고 적힌 옆 콤보박스에 검색된 포트가 입력됩니다.
열고자 하는 포트를 선택하고 하단에 있는 파라미터들을 확인해서 [ Connect ] 클릭을 하면 포트가 열립니다.
메세지란에 원하고자 하는 메세지를 적고 Send 버튼을 누르면 데이타가 전송이 됩니다.
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;
namespace RS_232_Demo
{
public partial class Form1 : Form
{
string portName = string.Empty;
Parity parity = Parity.None;
StopBits StopBits = StopBits.None;
int buadrate = 9600;
int databit = 8;
SerialPort sp;
public Form1()
{
InitializeComponent();
Init();
}
void Init()
{
Cbox_Baudrate.SelectedIndex = 0;
Cbox_Parity.SelectedIndex = 0;
Cbox_StopBit.SelectedIndex = 1;
}
private void Btn_Find_Click(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames();
for (int i = 0; i < portNames.Length; i++)
{
Cbox_Port.Items.Add(portNames[i]);
}
}
private void Btn_Connect_Click(object sender, EventArgs e)
{
try
{
int.TryParse(Cbox_Baudrate.SelectedItem.ToString(), out buadrate);
parity = (Parity)((int)Cbox_Parity.SelectedIndex);
StopBits = (StopBits)((int)Cbox_StopBit.SelectedIndex);
int.TryParse(Tbox_DataBit.Text, out databit);
sp = new SerialPort(Cbox_Port.SelectedItem.ToString(), buadrate, parity, databit, StopBits);
sp.Open();
if(sp.IsOpen)
{
Update($"{Cbox_Port.SelectedItem.ToString()} 포트 열림 성공");
}
else
{
Update($"{Cbox_Port.SelectedItem.ToString()} 포트 열림 실패");
}
}
catch(Exception es)
{
MessageBox.Show("Port 에러", "Port Error");
}
}
private void Btn_Send_Click(object sender, EventArgs e)
{
if(sp != null)
{
sp.WriteLine(Tbox_Msg.Text);
Update(Tbox_Msg.Text, true);
byte[] sendBytes = new byte[20];
sp.Write(sendBytes, 0, sendBytes.Length);
string msg = sp.ReadLine();
Update(msg, false);
}
else
{
MessageBox.Show("Port 에러", "Port Error");
}
}
void Update(string msg, bool tx)
{
string status = tx? "tx" : "rx";
Tbox_Log.AppendText($"{DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss")} {status} : {msg}");
}
void Update(string msg)
{
Tbox_Log.AppendText($"{DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss")} : {msg}");
}
}
}
대략적인 방식은 위와 같습니다.
전송되는 데이타는 ASCII 라고 생각하고 기입하였습니다.
byte[] sendBytes = new byte[20];
sp.Write(sendBytes, 0, sendBytes.Length);
만약에 Byte배열로 전송시에는 위와 같은 방식으로 하시면 됩니다.
Byte 배열의 길이는 일단 임의로 입력하였는데 전송하시려는 데이타의 수에 맞추어 배열을 생성하시면 됩니다.
그리고 위의 메인코드는 폴링방식으로 작성이 되었습니다.
보내고 받고 하게 되어 있습니다.
위의 방식보다는 인터럽트 이벤트 방식이 더 쓰시기에 좋을 것 입니다.
인터럽트 방식은
{
sp = new SerialPort(Cbox_Port.SelectedItem.ToString(), buadrate, parity, databit, StopBits);
sp.DataReceived += Sp_DataReceived;
}
private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = sp.ReadLine();
}
시리얼 포트 객체 인스턴스 이후 이벤트 핸들러를 등록하여서 이벤트 발생시 데이타를 읽도록 수정하면 됩니다.
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;
namespace RS_232_Demo
{
public partial class Form1 : Form
{
string portName = string.Empty;
Parity parity = Parity.None;
StopBits StopBits = StopBits.None;
int buadrate = 9600;
int databit = 8;
SerialPort sp;
public Form1()
{
InitializeComponent();
Init();
}
void Init()
{
Cbox_Baudrate.SelectedIndex = 0;
Cbox_Parity.SelectedIndex = 0;
Cbox_StopBit.SelectedIndex = 1;
}
private void Btn_Find_Click(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames();
for (int i = 0; i < portNames.Length; i++)
{
Cbox_Port.Items.Add(portNames[i]);
}
}
private void Btn_Connect_Click(object sender, EventArgs e)
{
try
{
int.TryParse(Cbox_Baudrate.SelectedItem.ToString(), out buadrate);
parity = (Parity)((int)Cbox_Parity.SelectedIndex);
StopBits = (StopBits)((int)Cbox_StopBit.SelectedIndex);
int.TryParse(Tbox_DataBit.Text, out databit);
sp = new SerialPort(Cbox_Port.SelectedItem.ToString(), buadrate, parity, databit, StopBits);
sp.DataReceived += Sp_DataReceived;
sp.Open();
if(sp.IsOpen)
{
Update($"{Cbox_Port.SelectedItem.ToString()} 포트 열림 성공");
}
else
{
Update($"{Cbox_Port.SelectedItem.ToString()} 포트 열림 실패");
}
}
catch(Exception es)
{
MessageBox.Show("Port 에러", "Port Error");
}
}
private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = sp.ReadLine();
}
private void Btn_Send_Click(object sender, EventArgs e)
{
if(sp != null)
{
sp.WriteLine(Tbox_Msg.Text);
Update(Tbox_Msg.Text, true);
byte[] sendBytes = new byte[20];
sp.Write(sendBytes, 0, sendBytes.Length);
//string msg = sp.ReadLine();
//Update(msg, false);
}
else
{
MessageBox.Show("Port 에러", "Port Error");
}
}
void Update(string msg, bool tx)
{
string status = tx? "tx" : "rx";
Tbox_Log.AppendText($"{DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss")} {status} : {msg}");
}
void Update(string msg)
{
Tbox_Log.AppendText($"{DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss")} : {msg}");
}
}
}
위의 방식이 수신 이벥트 발생시 동작하게 하는 방법입니다.
간단하지만 많이 쓰이는 방식이라 작성하여 봤습니다.
여기까지 읽어주셔서 감사합니다.
'개발' 카테고리의 다른 글
C#으로 하는 TCP/IP 통신 -1- (101) | 2024.11.22 |
---|---|
ASP.net core SignalR 해보면서 (47) | 2024.11.21 |
C#으로 하는 RS-232 -1- (92) | 2024.11.19 |
C#으로 하는 GPIB 통신 Fin (97) | 2024.11.18 |
C#으로 하는 GPIB 통신 -10- (83) | 2024.11.17 |