using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SerialCommLib
{
public class SerialComm
{
public delegate void DataReceivedHandlerFunc(byte[] receiveData);
public DataReceivedHandlerFunc DataReceivedHandler;
public delegate void DisconnectedHandlerFunc();
public DisconnectedHandlerFunc DisconnectedHandler;
private SerialPort serialPort;
public bool IsOpen
{
get
{
if (serialPort != null) return serialPort.IsOpen;
return false;
}
}
// serial port check
private Thread threadCheckSerialOpen;
private bool isThreadCheckSerialOpen = false;
public SerialComm()
{
}
public bool OpenComm(string portName, int baudrate, int databits, StopBits stopbits, Parity parity, Handshake handshake)
{
try
{
serialPort = new SerialPort();
serialPort.PortName = portName;
serialPort.BaudRate = baudrate;
serialPort.DataBits = databits;
serialPort.StopBits = stopbits;
serialPort.Parity = parity;
serialPort.Handshake = handshake;
serialPort.Encoding = new System.Text.ASCIIEncoding();
serialPort.NewLine = "\r\n";
serialPort.ErrorReceived += serialPort_ErrorReceived;
serialPort.DataReceived += serialPort_DataReceived;
serialPort.Open();
StartCheckSerialOpenThread();
return true;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return false;
}
}
public void CloseComm()
{
try
{
if (serialPort != null)
{
StopCheckSerialOpenThread();
serialPort.Close();
serialPort = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
public bool Send(string sendData)
{
try
{
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Write(sendData);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return false;
}
public bool Send(byte[] sendData)
{
try
{
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Write(sendData, 0, sendData.Length);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return false;
}
public bool Send(byte[] sendData, int offset, int count)
{
try
{
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Write(sendData, offset, count);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return false;
}
private byte[] ReadSerialByteData()
{
serialPort.ReadTimeout = 100;
byte[] bytesBuffer = new byte[serialPort.BytesToRead];
int bufferOffset = 0;
int bytesToRead = serialPort.BytesToRead;
while (bytesToRead > 0)
{
try
{
int readBytes = serialPort.Read(bytesBuffer, bufferOffset, bytesToRead - bufferOffset);
bytesToRead -= readBytes;
bufferOffset += readBytes;
}
catch (TimeoutException ex)
{
Debug.WriteLine(ex.ToString());
}
}
return bytesBuffer;
}
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] bytesBuffer = ReadSerialByteData();
string strBuffer = Encoding.ASCII.GetString(bytesBuffer);
if (DataReceivedHandler != null)
DataReceivedHandler(bytesBuffer);
Debug.WriteLine("received(" + strBuffer.Length + ") : " + strBuffer);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
private void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
Debug.WriteLine(e.ToString());
}
private void StartCheckSerialOpenThread()
{
isThreadCheckSerialOpen = true;
threadCheckSerialOpen = new Thread(new ThreadStart(ThreadCheckSerialOpen));
threadCheckSerialOpen.Start();
}
private void StopCheckSerialOpenThread()
{
if (isThreadCheckSerialOpen)
{
isThreadCheckSerialOpen = false;
if (Thread.CurrentThread != threadCheckSerialOpen)
threadCheckSerialOpen.Join();
}
}
private void ThreadCheckSerialOpen()
{
while (isThreadCheckSerialOpen)
{
Thread.Sleep(100);
try
{
if (serialPort == null || !serialPort.IsOpen)
{
Debug.WriteLine("seriaport disconnected");
if (DisconnectedHandler != null)
DisconnectedHandler();
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
}
}
}
< SerialComm 사용 >
using System.IO.Ports;
using SerialCommLib;
...
SerialComm serial = new SerialComm();
serial.DataReceivedHandler = DataReceivedHandler;
serial.DisconnectedHandler = DisconnectedHandler;
...
serial.OpenComm("COM3", 9600, 8, StopBits.One, Parity.None, Handshake.None);...
serial.CloseComm();
private void DataReceivedHandler(byte[] receiveData)
{
// do something with receiveData here
}
private void DisconnectedHandler()
{
Console.WriteLine("serial disconnected");
}
* 라이브러리 사용은 시리얼 데이터 수신과 연결종료 이벤트 핸들러를 등록해서 콜백으로 받아서 처리하는 방식으로 간단하게 사용할 수 있다.
C# SerialPort 클래스는 이벤트 수신 방식과 쓰레드 방식 두 가지로 사용할 수 있는데 쓰레드 방식보다 이벤트 수신 방식이 더 간단하고 직관적이다.
SerialPort 클래스의 Read 계열 메소드는 블러킹 방식으로 동작하기때문에 데이터 수신 이벤트 발생시 반드시 BytesToRead 에 명시된 모든 바이트를 읽어서 수신버퍼를 비워줘야한다.
안녕하세요. 공개주신 라이브러리 감사히 보았습니다.
답글삭제현재 Readline() 명령에 latency가 있어서 다른 방법을 알아보는 중인데
들어오는 데이터를 line 단위로 처리를 하려할때는 어찌하면 좋을까요?
초면에 질문부터 드립니다. (__)
ReadLine 함수의 문제가 아니라 시리얼통신의 특징입니다.(송신데이터 그대로 수신되지않음) 수신데이터를 버퍼에 저장한후 앞에서부터 개행문자를 찾은다음 라인단위로 끊어서 처리해야합니다
답글삭제사용법에서 (해당 라이브러리를 사용하는 프로그램에서)
답글삭제serial.DataReceivedHandler = DataReceivedHandler; 를 하게 되면
DataReceivedHandler'이(가) 현재 컨텍스트에 없습니다.
serial이 현재 컨텍스트에 없습니다.
오류가 나는지요 ?
컴파일 환경 : vs2017 입니다.
DataReceivedHandler 함수 선언이 없어서입니다..
삭제제가 C# 문법에 대해 많이 모르는 상태에서 하려니 좀 .. 난감하네요..
삭제위 코드를 솔루션에 라이브러리 프로젝트로 하여 입력하였고,
테스트 프로젝트를 새로 생성하여
아래 코드 입력 (참조에는 IrLib 추가)
serial.DataReceivedHandler = DataReceivedHandler;
serial.DisconnectedHandler = DisconnectedHandler;
빨간 밑줄 그어지면서 현재 컨텍스트에 없습니다. 출력됩니다.
serial.DataReceivedHandler 와 DataReceivedHandler 모두 각각요....
-- --------
using System.Threading;
using System.Threading.Tasks;
using System.IO.Ports;
using IrLib;
namespace Test
{
class Program
{
SerialComm serial = new SerialComm();
serial.DataReceivedHandler = DataReceivedHandler;
serial.DisconnectedHandler = DisconnectedHandler;
static void Main(string[] args)
{
string[] comList = System.IO.Ports.SerialPort.GetPortNames();
foreach(string port in comList)
{
Console.WriteLine(port);
}
while(true)
{
Thread.Sleep(100);
}
}
private void DataReceivedHandler(byte[] receiveData)
{
Console.WriteLine("serial DataReceived !!");
}
private void DisconnectedHandler()
{
Console.WriteLine("serial disconnected !!");
}
}
}
serial.DataReceivedHandler = DataReceivedHandler;
삭제serial.DisconnectedHandler = DisconnectedHandler;
부분을 Main 함수 안으로 넣고
DataReceivedHandler, DisconnectedHandler 함수와 SerialComm serial 변수를 static 으로 변경해보세요
제가 포트 연결을 잘못 했는가 봅니다.
삭제현재는 잘 동작하는 것 같습니다.
덕분에 delegate 도 이해하게 되었고 감사합니다.
안녕하세요 Serial Port 구현 하다가 질문이 생겼습니다.
답글삭제private void DataReceivedHandler(byte[] receiveData)
{
// do something with receiveData here
}
여기서 보시면 DataReceivedHandler를 통해 DataReceived 데이터를 Main으로 어떻게 보낼 수 있을까요
해결했습니다. 간단한거였습니다.
삭제String msg= Encoding.ASCII.GetString(receiveData);