자료 참고 안내 1. 본 자료실의 모든 자료 저작권은 ㈜에이치앤에스에 있습니다.

본 자료는 개발하시는데 참고자료 용도로 사용하실 수 있으며 저작권 표시 없이 복사,게재, 출판 하실 수 없습니다. 외부 게재 사용 시 반드시 출처 항목에 회사명과 사이트 주소를 반드시 명시해 주시기 바랍니다.
[표기 예] 출처 : ㈜에이치앤에스(www.hnsts.co.kr) 또는 ㈜HNS(www.hnsts.co.kr)

2. 제품 개발 시 내용과 예제 코드는 수정 및 검증작업을 직접 하셔야 하며 문제 발생에 대한 책임은 ㈜HNS사와 무관합니다.

본사는 자료를 최신내용으로 유지하기 위해 노력하고 있으며 제공되는 정보의 오류 및 내용이 정확하지 않을 경우 사전 공지 없이 업데이트 될 수 있습니다. 자료의 문제점 발견 시 본사로 문의주시면 검토하여 자료를 수정하도록 하겠습니다.

[C#, VB.NET] 시리얼(SerialPort) 통신 예제
작성일 2018-08-28 수정일 2022-10-06 조회수 2384
분류 Knowhow
적용
플랫폼
키워드 시리얼(Serial), 통신, 232
첨부파일 TechNote46_Example.zip

본 자료는
1. 시리얼 컴포넌트(SerialPort Component) 간략 설명
2. 스레드 생성 및 제어(수신 스레드)
3. 스레드에서 UI 컨트롤 접근하기
순서로 진행합니다.

본 시리얼(Serial) 통신 예제는 C#으로 제작되었으며 수신 처리는 스레드(Thread)로 동작합니다.
Ascii Mode(Text Mode)로 데이터를 송/수신하도록 구성되어 있습니다. 송/수신 프레임(Frame)의 구분은 STX/ETX로 하지 않고 Time Interval을 사용하여 구분합니다. 수신 스레드(Thread)에서 데이터가 ReadTimeOut 설정 시간 동안 입력되지 않는 경우 TimeOut Exception이 발생합니다. ReadTimeOut 시간은 TimeOut Interval 시간보다 같거나 더 작게 설정해서 사용해야 합니다.
데이터를 저장 시에는 스레드(Thread)가 UI 접근을 직접할 수 없으므로 델리게이트(Delegate)를 사용해야 합니다.


주의IEC-Series로 시리얼통신 프로그램을 개발하는 경우 SmartSerialPort의 사용을 적극 권장하고 있습니다.

모든 통신 환경에 쉽고 편리하게 적용할 수 있도록 새롭게 만들어진 컴포넌트입니다. SmartSerialPort를 사용하여 외부의 디바이스와 연동(통신 프로그래밍)시 문제 및 적용에 어려움이 있는 경우 회사로 연락주시면 IEC-Series와 디바이스 연동 작업을 지원하도록 하겠습니다. 지원 시 SmartSerialPort를 기준하여 지원하며 기능 변경 및 추가 지원을 하도록 하겠습니다.

1. 시리얼 컴포넌트(SerialPort Component) 간략 설명

시리얼(Serial) 포트, 다른 이름으로 직렬 포트라고 하며 시리얼 통신을 하는 경우 SerialPort 컴포넌트(Component)를 사용합니다. 생성자는 총 7개이며 사용되는 속성으로는 BaudRate, IsOpen, Parity, PortName, ReadBufferSize, ReadTimeout, RtsEnable, StopBits 등이 있습니다.
다음은 SerialPort Component 간략 설명이며 자세한 사용 방법은 첨부된 소스를 참고 바랍니다.

포트 이름 지정
public string PortName { get; set; }
사용법
C# 예제
// 포트 이름의 종류는 COM1, COM2, COM3, COM4, COM7
// 포트 이름을 COM1으로 설정
serialPort1.PortName = "COM1";
(인자) get; set;
(반환값) string : 포트 이름

시리얼 통신을 위한 통신 속도 설명
public int BaudRate { get; set; }
사용법
C# 예제
// 통신 속도의 종류는 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000이며 256000은 지원하지 않습니다.
// 통신 속도를 9600으로 설정
serialPort1.BaudRate = 9600;
(인자)get; set;
(반환값) int : 통신 속도

데이터 비트 설명
public int DataBits { get; set; }
사용법
C# 예제
// 데이터 비트를 8비트로 설정. 보통 8비트로 사용
serialPort1.DataBits = 8;
(인자) get; set;
(반환값) int : 데이터 비트

시리얼 포트의 상태(Open/Close) 확인 시 사용
public bool IsOpen { get; }
사용법
C# 예제
// 포트가 오픈 되었는지 확인
if (serialPort1.IsOpen == false)
{ return; }
(인자) get;
(반환값) bool : 포트가 오픈 되었으면 True 반환

수신 버퍼 사이즈 설정
public int ReadBufferSize { get; set; }
사용법
C# 예제
// 수신 버퍼 사이즈를 4kbyte로 지정
serialPort1.ReadBufferSize = 4096;
(인자) get; set;
(반환값) int : 수신 버퍼 사이즈

SerialPort 입력 버퍼에서 1바이트를 동기적으로 읽습니다.
public int ReadByte();
사용법
C# 예제
// 수신 버퍼에서 1바이트 읽기
serialPort1.ReadByte();
(인자) 없음
(반환값) int : Int32로 캐스팅된 바이트이며 스트림의 끝을 읽은 경우 -1을 반환

수신 제한 시간 설정.
public int ReadTimeout { get; set; }
Serial통신에서 송/수신 Frame의 구분은 STX/ETX로 하지 않고 Time Interval을 사용하여 구분합니다. 즉 Frame과 Frame사이의 일정 시간 간격(Time Interval)을 두어 데이터 송/수신 시에 Frame을 구분합니다. 이때 ReadTimeOut값은 송/수신 Interval값보다 같거나 작게 설정하여 사용해야 합니다.

① 수신 데이터 Interval이 100ms인 경우


② 수신 데이터 Interval이 10ms인 경우


사용법
C# 예제
try
{
for (i = 0; i < serialPort1.ReadBufferSize; i++)
{
// ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
recBuff[i] = Convert.ToByte(serialPort1.ReadByte());
}
}
// ReadTimeout 시간 내에 데이터가 입력되지 않는 경우 TimeoutException 발생
catch (TimeoutException tExp)
{
// 입력된 데이터 개수 카운트
iRecCnt = i;
}
(인자) get; set;
(반환값) int : 읽기 작업을 마쳐야 하는 제한 시간(밀리초)

RTS(Request to Send) 신호를 사용할 수 있는지를 나타내는 값을 가져오거나 설정
public bool RtsEnable { get; set; }
사용법
C# 예제
// IEC667를 사용하는 경우 RtsEnable 속성값을 반드시 TRUE로 설정하여 사용
해야 합니다. IEC266, IEC1000은 해당하지 않음

// RTS 신호를 사용.
serialPort1.RtsEnable = true;
(인자) get; set;
(반환값) bool : RTS 속성을 사용하는 경우 TRUE로 설정

바이트 당 정지 비트의 표준 개수를 가져오거나 설정
public StopBits StopBits { get; set; }
사용법
C# 예제
// 스톱 비트의 종류는 "None", "One", "Two", "OnePointFive"
// 정지 비트를 One으로 설정. 보통 One으로 사용
serialPort1.StopBits = System.IO.Ports.StopBits.One;
(인자) get; set; (반환값) StopBits

2. 스레드 생성 및 제어(수신 스레드) 2-1. ReadByte() 를 통해서 읽은 데이터를 수신 버퍼에 저장

시리얼(Serial) 통신에 관련된 모든 기능을 담당하는 CSerialPort클래스로서 세부 내용은 다음과 같이 이루어져 있습니다.

// Client 연결 및 수신 스레드 함수
private void ComPortReadFunc()
{

// 스레드(Thread)로 동작하기 위해 반복(Loop)문으로 작성
// SerialPortClose()를 호출하는 경우 수신 스레드 동작 종료
while (true)
{
try
{
// ReadBufferSize만큼 반복하면서 ReadByte를 실행하여 데이터 수신
// ReadBufferSize는 Max값으로 고정되며 Max값 이상의 값이 입력되는 경우
// BufferOverRun이 발생하거나 데이터가 단편화됩니다.
// ex) ReadBufferSize가 4096이며 4096초과의 값이 입력
for (i = 0; i < serialPort1.ReadBufferSize; i++)
{
// ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
recBuff[i] = Convert.ToByte(serialPort1.ReadByte());
}
}
// ReadTimeout 시간 안에 데이터가 입력되지 않는 경우
catch (TimeoutException tExp)
{
// 입력된 데이터 개수 카운트
iRecCnt = i;
}
// 입력된 데이터가 존재하면
if (iRecCnt != 0)
{
// 수신된 바이트 데이터를 유니코드 문자열로 변환
}
}
}


스트림에서 바이트를 읽고 스트림 내 위치를 한 바이트씩 앞으로 이동하거나 스트림 끝일 경우 -1을 반환
public int ReadByte();
사용법
C# 예제
// ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
serialPort1.ReadByte()
(인자) 없음
(반환값) Int32 : 캐스팅된 부호 없는 바이트이거나 스트림의 끝에 있는 경우 -1을 반환

2-2. 수신된 바이트 데이터를 유니코드로 변환

시리얼(Serial)통신은 Ascii Mode(Text Mode)만 지원되며 Binary 모드는 지원하지 않으므로 수신 데이터를 아스키(ASCII)로 변환해 주어야 합니다.

// 수신된 바이트 데이터를 유니코드 문자열로 변환
// recBuff의 데이터를 0부터 iRecCnt 바이트 만큼 ASCII 모드로 변환하여 strRecData에 저장
strRecData = Encoding.ASCII.GetString(recBuff, 0, iRecCnt);


ASCIIEncoding.GetString 메서드. 바이트 배열의 바이트 범위를 문자열로 디코딩합니다.
public override string GetString
(
byte[] bytes, int byteIndex, int byteCount
)
사용법
C# 예제
// 수신된 바이트 데이터를 유니코드 문자열로 변환
strRecData = Encoding.ASCII.GetString(recBuff, 0, iRecCnt);
(인자) byte[] bytes : 디코딩할 바이트 시퀀스를 포함하는 바이트 배열입니다.
(인자) int byteIndex : 디코딩할 첫 번째 바이트의 인덱스입니다.
(인자) int byteCount : 디코딩할 바이트 수입니다.
(반환값) string : 지정된 바이트 시퀀스에 대한 디코딩 결과가 포함된 String입니다.

2-3. 스레드를 종료하기 위한 검사

스레드(Thread)의 종료를 검사하는 경우에 AutoResetEvent를 사용하는 목적은 스레드(Thread)처리 루틴에서 플래그(Flag)값을 검사하는 시간이 상황에 따라 다르기 때문에 스레드 STOP을 처리하는 함수에서 스레드 함수가 완전히 종료될 때까지 스레드 STOP 처리를 함수의 Return 즉, Blocking 하도록 처리합니다.

하나 이상의 대기중인 스레드가 계속 진행될 수 있도록 이벤트의 상태를 신호로 설정합니다.
public bool Set()
사용법
C# 예제
m_StopCompletionEvent.Set();
(인자) 없음
(반환값) bool : 동작이 성공하면 TRUE를 반환합니다.

32 비트 부호있는 정수를 사용하여 시간 간격을 지정하고 대기 전에 동기화 도메인을 종료할지 여부를 지정하여 현재 WaitHandle이 신호를 수신할 때까지 현재 스레드를 차단합니다.
public virtual bool WaitOne( int millisecondsTimeout, bool exitContext )
사용법
C# 예제
// 대기 시간은 1초이며 동기화된 컨텍스트의 도메인을 갖고 오지 않음
m_StopCompletionEvent.WaitOne((int)1000, false)
(인자) int millisecondsTimeout : 대기할 시간(밀리초)이거나, 무기한 대기할 경우 Timeout.Infinite(-1)입니다.
(인자) bool exitContext : 대기 전에 컨텍스트에 대한 동기화 도메인을 종료하고(동기화된 컨텍스트에 있는 경우) 이 도메인을 다시 가져오려면 true이고, 그렇지 않으면 false입니다.
(반환값) bool : 현재 인스턴스가 신호를 받으면 true이고, 그렇지 않으면 false입니다.

3. 스레드에서 UI컨트롤 접근하기

스레드는 UI 컴포넌트(Component)에 직접 접근할 수 없으며, 이 경우 스레드는 델리게이트(Delegate)를 사용하여 UI에 접근이 가능합니다.

스레드에서 UI컨트롤 접근의 순서

① 스레드 내부에서 델리게이트 함수를 호출
② Invoke()에서 실제 UI에 접근하는 함수를 인자로 받아 호출
③ 실제 UI에 접근으로 진행됩니다.


// 스레드에서 UI 컨트롤을 접근하기 위한 delegate 함수 선언 및 정의
delegate void ListRecCallback(string strtext);

// 실제 UI에 접근하는 함수. 델리게이트(Delegate)의 인자로 사용
private void RecListAdd(string strRecData)
{

recList.AddItem(strRecData); // ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ③
}

// 수신데이터를 ListBox에 추가하는 함수
private void DelegateRecListAdd(string strRecData)
{
// Invoke 메서드는 델리게이트(Delegate) Type을 파라미터로 받아들임. 컴파일 에러 방지
this.Invoke(new ListRecCallback(RecListAdd), strRecData); // ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ②
}

// Client 연결 및 수신 스레드 함수
private void ComPortReadFunc()
{
int iRecCnt = 0;
string strRecData;

// 바이트 배열 수신 버퍼 선언
byte[] recBuff = new byte[serialPort1.ReadBufferSize];
m_Stop = false;
int i = 0;
try
{
while(true)
{
try
{
for (i = 0; i < serialPort1.ReadBufferSize; i++)
{
// ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
recBuff[i] = Convert.ToByte(serialPort1.ReadByte());
}
}
catch (TimeoutException tExp)
{
iRecCnt = i;
}

if (iRecCnt != 0)
{
// 수신된 바이트 데이터를 유니코드 문자열로 변환
strRecData = Encoding.ASCII.GetString(recBuff, 0, iRecCnt);

// 수신된 데이터를 ListBox에 추가한다.
DelegateRecListAdd(strRecData); // ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ①
}

// 스레드를 종료하기 위한 검사
if (m_Stop == true)
{
break;
}
Thread.Sleep(100);
}

// 스레드에 종료 대기 해제. 다음 문장 진행
m_StopCompletionEvent.Set();
}
catch (Exception exp)
{
if (m_Stop == true)
{
// serial Port를 접근 시 Try~Catch로 항상 처리한다.
// Open이 안되거나 생성이 안 된 경우 무조건 예외를 발생할수있다.
exp.ToString();
// 스레드에 종료 대기 해제. 다음 문장 진행
m_StopCompletionEvent.Set();
return;
}
}
}

C# 예제코드
소스 코드는 참고 및 학습용으로 버그 및 여러 가지 문제가 있을 수 있습니다.

[예제동작순서] C#, VB.NET용 시리얼(SerialPort) 통신 예제 테스트 (IEC1000-Series 기준)
STEP-1. 통신환경 설정(포트 번호, 통신 속도, 패리티비트, 스톱비트)
STEP-2. 포트 오픈 및 수신 스레드 시작
STEP-3. 데이터 자동으로 송신하기
STEP-4. 시리얼 통신 포트 닫기

// STEP-1. 통신환경 설정(포트 번호, 통신 속도, 패리티비트, 스톱비트)
// 포트 번호
private string[] m_iPortNum = { "COM1", "COM2", "COM3", "COM4", "COM7" };

// 통신 속도
private int[] m_iBaudRate = { 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000 };

// 패리티비트
private string[] m_strParity = { "None", "Odd", "Even", "Mark", "Space" };

// 스톱비트
private string[] m_strStopBits = { "None", "One", "Tow", "OnePointFive" };

// 스레드 선언
private Thread m_readThread;
private static bool m_Stop;

// AutoResetEvent 객체. 대기중인 스레드에게 외부에서 신호를 보내 스레드의 흐름을 통제
// 인자로 false를 사용하기 때문에 비신호 상태로 선언. 즉, 이벤트는 대기 상태로 선언
private static AutoResetEvent m_StopCompletionEvent = new AutoResetEvent(false);

// 스레드에서 UI 컨트롤을 접근하기 위한 delegate 함수 선언 및 정의
delegate void ListRecCallback(string strtext);

// 실제 UI에 접근하는 함수. 델리게이트의 인자로 사용
private void RecListAdd(string strRecData)
{
recList.AddItem(strRecData);
}

// 수신 데이터를 ListBox에 추가하는 함수
private void DelegateRecListAdd(string strRecData)
{
// Invoke 메서드는 델리게이트 Type을 파라미터로 받아들임. 컴파일 에러 방지
this.Invoke( new ListRecCallback(RecListAdd), strRecData);
}

// STEP-2. 포트 오픈 및 수신 스레드 시작
private void butOpen_Click(object sender, EventArgs e)
{
// 통신 포트 사용자 선택
// 통신속도 사용자 선택
// 데이터 비트 사용자 선택
// --중략--
// 읽기 작업을 마쳐야 하는 제한 시간(밀리초)을 가져오거나 설정
serialPort1.ReadTimeout = 500;

serialPort1.Open();

// 수신 스레드 시작
m_readThread = new Thread(new ThreadStart(ComPortReadFunc));
m_readThread.Start();
}

// Client 연결 및 수신 스레드 함수
private void ComPortReadFunc()
{
int iRecCnt = 0;
string strRecData;

// 바이트 배열 수신 버퍼 선언
byte[] recBuff = new byte[serialPort1.ReadBufferSize];

m_Stop = false;
int i = 0;

try
{
while(true)
{
//smartTimer1.StartWatch();
try
{
for (i = 0; i < serialPort1.ReadBufferSize; i++)
{
// ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
recBuff[i] = Convert.ToByte(serialPort1.ReadByte());
}
}
catch (TimeoutException tExp)
{
iRecCnt = i;
}
//smartTimer1.StopWatch();
//MessageBox.Show(smartTimer1.StopWatchElapsedMicrosecond.ToString());

if (iRecCnt != 0)
{
// 수신된 바이트 데이터를 유니코드 문자열로 변환
strRecData = Encoding.ASCII.GetString(recBuff, 0, iRecCnt);

// 수신된 데이터를 ListBox에 추가한다.
DelegateRecListAdd(strRecData);
//Application.DoEvents();
}

// 스레드를 종료하기 위한 검사. 시리얼 포트를 닫는 경우 TRUE로 설정됨
if (m_Stop == true)
{
break;
}
Thread.Sleep(100);
}
// 스레드에 대기 해제 신호 발생. 스레드 완벽하게 종료됨
m_StopCompletionEvent.Set();
}
catch (Exception exp)
{
if (m_Stop == true)
{
// serial Port를 접근 시 Try~Catch로 항상 처리한다.
// Open이 안되거나 생성이 안 된 경우 무조건 예외를 발생할 수 있다.
exp.ToString();

// 스레드에 대기 해제 신호 발생. 스레드 완벽하게 종료됨
m_StopCompletionEvent.Set();
return;
}
}
}

// STEP-3. 데이터 자동으로 송신하기
private void timerSend_Tick(object sender, EventArgs e)
{
if (serialPort1.IsOpen == false)
{
smartTimer1.Stop();
return;
}
try
{
byte[] sendBuff = new byte[1024];

// 입력된 Text를 ASCII 코드로 전환
sendBuff = Encoding.ASCII.GetBytes(txtSendData.Text);

// 데이터 전송
serialPort1.Write(sendBuff, 0, txtSendData.Text.Length);

if (chkAutoSend.Checked == false)
{
smartTimer1.Stop();
}
}
catch (Exception exp)
{
// serialPort1의 접근 시 Try~Catch로 항상 처리한다.
// Open이 안되거나 생성이 안 된 경우 무조건 예외를 발생할 수 있다.
exp.ToString();
smartTimer1.Stop();
serialPort1.Close();
m_Stop = true;
}
}
// STEP-4. 시리얼 통신 포트 닫기
private void SerialPortClose()
{
if (serialPort1.IsOpen == false)
{
return;
}

m_Stop = true;

serialPort1.ReadTimeout = 5000;

// 수신 스레드가 종료되기를 기다린다.
Thread.Sleep(1000);

// 스레드 STOP을 처리하는 함수에서 스레드 함수가 완전히 종료될 때까지
// 스레드 STOP 처리를 함수의 Return 즉, Blocking 하도록 처리
if (m_StopCompletionEvent.WaitOne((int)1000, false) == true)
{
try
{
// 시리얼 포트 닫기
serialPort1.Close();
}
catch (Exception exp)
{
exp.ToString();
}
return;
}
// SmartTimer 시작
smartTimer1.Start();
// 시리얼 포트 종료
serialPort1.Close();
}
VB.NET 예제코드
소스 코드는 참고 및 학습용으로 버그 및 여러 가지 문제가 있을 수 있습니다.

[예제동작순서] C#, VB.NET용 시리얼(SerialPort) 통신 예제 테스트 (IEC1000-Series 기준)
STEP-1. 통신환경 설정(포트 번호, 통신 속도, 패리티비트, 스톱비트)
STEP-2. 포트 오픈 및 수신 스레드 시작
STEP-3. 데이터 자동으로 송신하기
STEP-4. 시리얼 통신 포트 닫기

' STEP-1. 통신환경 설정(포트 번호, 통신 속도, 패리티비트, 스톱비트)
' 포트번호
Private m_iPortNum As String() = {"COM1", "COM2", "COM3", "COM4", "COM7"}

' 통신 속도
Private m_iBaudRate As Integer() = {110, 300, 600, 1200, 2400, 4800, _
9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000}

' 패리티비트
Private m_strParity As String() = {"None", "Odd", "Even", "Mark", "Space"}

' 스톱비트
Private m_strStopBits As String() = {"None", "One", "Tow", "OnePointFive"}

' 스레드 선언
Private m_readThread As Thread
Private Shared m_Stop As Boolean

' AutoResetEvent 객체. 대기중인 스레드에게 외부에서 신호를 보내 스레드의 흐름을 통제
' 인자로 false를 사용하기 때문에 비신호 상태로 선언. 즉, 이벤트는 대기 상태로 선언
Private Shared m_StopCompletionEvent As New AutoResetEvent(False)

' 스레드에서 UI 컨트롤을 접근하기 위한 delegate 함수 선언 및 정의
Private Delegate Sub ListRecCallback(ByVal strtext As String)

' 실제 UI에 접근하는 함수. 델리게이트의 인자로 사용
Private Sub RecListAdd(ByVal strRecData As String)
recList.AddItem(strRecData)
End Sub

' 수신 데이터를 ListBox에 추가하는 함수
Private Sub DelegateRecListAdd(ByVal strRecData As String)
' Invoke 메서드는 델리게이트 Type을 파라미터로 받아들임. 컴파일 에러 방지
Me.Invoke(New ListRecCallback(AddressOf RecListAdd), strRecData)
End Sub

' STEP-2. 포트 오픈 및 수신 스레드 시작
Private Sub butOpen_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butOpen.Click
' 통신 포트 사용자 선택
' 통신 속도 사용자 선택
' 데이터 비트 사용자 선택
' 중략
' 읽기 작업을 마쳐야 하는 제한 시간(밀리초)을 가져오거나 설정
serialPort1.ReadTimeout = 500
serialPort1.Open()

' 수신 스레드 시작
m_readThread = New Thread(New ThreadStart(AddressOf ComPortReadFunc))
m_readThread.Start()
End Sub

' Client 연결 및 수신 스레드 함수
Private Sub ComPortReadFunc()
Dim iRecCnt As Integer = 0
Dim strRecData As String

' 바이트 배열 수신 버퍼 선언
Dim recBuff As Byte() = New Byte(serialPort1.ReadBufferSize - 1) {}

m_Stop = False
Dim i As Integer = 0
Try
While True
'smartTimer1.StartWatch();
Try
For i = 0 To serialPort1.ReadBufferSize - 1
' ReadByte()를 통해서 읽은 데이터를 수신 버퍼에 저장
recBuff(i) = Convert.ToByte(serialPort1.ReadByte())
Next
Catch tExp As TimeoutException
iRecCnt = i
End Try
'smartTimer1.StopWatch();
'MessageBox.Show(smartTimer1.StopWatchElapsedMicrosecond.ToString());

If iRecCnt <> 0 Then
' 수신된 바이트 데이터를 유니코드 문자열로 변환
strRecData = Encoding.ASCII.GetString(recBuff, 0, iRecCnt)

' 수신된 데이터를 ListBox에 추가한다.
'Application.DoEvents();
DelegateRecListAdd(strRecData)
End If

' 스레드를 종료하기 위한 검사. 시리얼 포트를 닫는 경우 TRUE로 설정됨
If m_Stop = True Then
Exit While
End If
Thread.Sleep(100)
End While

' 스레드에 대기 해제 신호 발생. 스레드 완벽하게 종료됨
m_StopCompletionEvent.[Set]()
Catch exp As Exception
If m_Stop = True Then
' serial Port를 접근 시 Try~Catch 로 항상 처리한다.
' Open이 안되거나 생성이 안된경우 무조건 예외를 발생할수있다.
exp.ToString()

' 스레드에 대기 해제 신호 발생. 스레드 완벽하게 종료됨
m_StopCompletionEvent.[Set]()
Return
End If
End Try
End Sub

' STEP-3. 데이터 자동으로 송신하기
Private Sub timerSend_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles SmartTimer1.Tick
If serialPort1.IsOpen = False Then
SmartTimer1.[Stop]()
Return
End If

Try
Dim sendBuff As Byte() = New Byte(1023) {}

' 입력된 Text를 ASCII 코드로 전환
sendBuff = Encoding.ASCII.GetBytes(txtSendData.Text)

' 데이터 전송
serialPort1.Write(sendBuff, 0, txtSendData.Text.Length)

If chkAutoSend.Checked = False Then
SmartTimer1.[Stop]()
End If
Catch exp As Exception
' serialPort1의 접근 시 Try~Catch로 항상 처리한다.
' Open이 안되거나 생성이 안 된 경우 무조건 예외를 발생할 수 있다.
exp.ToString()
SmartTimer1.[Stop]()
serialPort1.Close()
m_Stop = True
End Try
End Sub

' STEP-4. 시리얼 통신 포트 닫기
Private Sub SerialPortClose()
If serialPort1.IsOpen = False Then
Return
End If

m_Stop = True

serialPort1.ReadTimeout = 5000

' 수신 스레드가 종료되기를 기다린다.
Thread.Sleep(1000)

' 스레드 STOP을 처리하는 함수에서 스레드 함수가 완전히 종료될 때까지
' 스레드 STOP 처리를 함수의 Return 즉, Blocking 하도록 처리
If m_StopCompletionEvent.WaitOne(CInt(1000), False) = True Then
Try
' 시리얼 포트 닫기
serialPort1.Close()
Catch exp As Exception
exp.ToString()
End Try
Return
End If

' SmartTimer 시작
SmartTimer1.Start()
' 시리얼 포트 종료
serialPort1.Close()
End Sub
맨 위로
팝업닫기

(주)에이치앤에스('http://hnsts.co.kr/'이하 '(주)에이치앤에스 웹사이트')는 개인정보보호법에 따라 이용자의 개인정보 보호 및 권익을 보호하고 개인정보와 관련한 이용자의 고충을 원활하게 처리할 수 있도록 다음과 같은 처리방침을 두고 있습니다.

(주)에이치앤에스 웹사이트는 개인정보처리방침을 개정하는 경우 웹사이트 공지사항(또는 개별공지)을 통하여 공지할 것입니다.

○ 본 방침은 2011년 4월 1일부터 시행됩니다.

1. 개인정보의 처리 목적 (주)에이치앤에스 웹사이트는 개인정보를 다음의 목적을 위해 처리합니다. 처리한 개인정보는 다음의 목적 이외의 용도로는
사용되지 않으며 이용 목적이 변경될 시에는 사전동의를 구할 예정 입니다.
가. 민원사무 처리
민원인의 신원 확인, 민원사항 확인, 사실조사를 위한 연락 · 통지, 처리결과 통보 등을 목적으로 개인정보를 처리합니다.
2. 개인정보 파일 현황
1. 개인정보 파일명 : 고객의 소리
  • - 개인정보 항목 : 이메일, 휴대전화번호, 자택전화번호, 이름, 서비스 이용 기록, 접속 로그, 쿠키, 접속 IP 정보
  • - 수집방법 : 웹사이트
  • - 보유근거 : 이용자 동의
  • - 보유기간 : 3년
3. 개인정보의 제3자 제공에 관한 사항
① (주)에이치앤에스 웹사이트는 원칙적으로 이용자의 개인정보를 제1조에서 명시한 목적 범위 내에서 처리하며, 본래의 범위를 초과하여 처리하거나 제3자에게 제공하지 않습니다.
다만, 다음의 경우에는 개인정보를 제3자에게 제공할 수 있습니다.
  • – 이용자가 사전에 제3자 제공 및 공개에 동의한 경우
  • – 법령 등에 의해 제공이 요구되는 경우
  • – 서비스의 제공에 관한 계약의 이행을 위하여 필요한 개인정보로서 경제적/기술적인 사유로 통상의 동의를 받는 것이 현저히 곤란한 경우
  • – 개인을 식별하기에 특정할 수 없는 상태로 가공하여 이용하는 경우
4. 정보주체의 권리,의무 및 그 행사방법 이용자는 개인정보주체로서 다음과 같은 권리를 행사할 수 있습니다.
① 정보주체는 (주)에이치앤에스 웹사이트에 대해 언제든지 다음 각 호의 개인정보 보호 관련 권리를 행사할 수 있습니다.
  • 1. 개인정보 열람요구
  • 2. 오류 등이 있을 경우 정정 요구
  • 3. 삭제요구
  • 4. 처리정지 요구
② 제1항에 따른 권리 행사는 (주)에이치앤에스 웹사이트에 대해 개인정보 보호법 시행규칙 별지 제8호 서식에 따라 서면, 전자우편, 모사전송(FAX) 등을 통하여 하실 수 있으며 (주)에이치앤에스 웹사이트는
이에 대해 지체 없이 조치하겠습니다.
③ 정보주체가 개인정보의 오류 등에 대한 정정 또는 삭제를 요구한 경우에는 (주)에이치앤에스 웹사이트는 정정 또는 삭제를 완료할 때까지 당해 개인정보를 이용하거나 제공하지 않습니다.
④ 제1항에 따른 권리 행사는 정보주체의 법정대리인이나 위임을 받은 자 등 대리인을 통하여 하실 수 있습니다. 이 경우 개인정보 보호법 시행규칙 별지 제11호 서식에 따른 위임장을
제출하셔야 합니다.
5. 제3자에게의 개인정보 제공
① (주)에이치앤에스 웹사이트는 다음의 개인정보 항목을 처리하고 있습니다.
<민원사무 처리>
– 필수항목 : 이름, 휴대전화번호, 자택전화번호, 이메일, 서비스 이용 기록, 접속로그, 쿠키, 접속IP 정보
6. 개인정보의 파기
(주)에이치앤에스 웹사이트는 원칙적으로 개인정보 처리목적이 달성된 경우에는 지체없이 해당 개인정보를 파기합니다. 파기의 절차, 기한 및 방법은 다음과 같습니다.
  • –파기절차 이용자가 입력한 정보는 목적 달성 후 별도의 DB에 옮겨져(종이의 경우 별도의 서류) 내부 방침 및 기타 관련 법령에 따라 일정기간 저장된 후 혹은 즉시 파기됩니다. 이 때, DB로 옮겨진 개인정보는 법률에 의한 경우가 아니고서는 다른 목적으로 이용되지 않습니다.-파기기한이용자의 개인정보는 개인정보의 보유기간이 경과된 경우에는 보유기간의 종료일로부터 5일 이내에, 개인정보의 처리 목적 달성, 해당 서비스의 폐지, 사업의 종료 등 그 개인정보가 불필요하게 되었을 때에는 개인정보의 처리가 불필요한 것으로 인정되는 날로부터 5일 이내에 그 개인정보를 파기합니다.
  • –파기방법 전자적 파일 형태의 정보는 기록을 재생할 수 없는 기술적 방법을 사용합니다. 종이에 출력된 개인정보는 분쇄기로 분쇄하거나 소각을 통하여 파기합니다.
7. 개인정보의 안전성 확보 조치
(주)에이치앤에스 웹사이트는 개인정보보호법 제29조에 따라 다음과 같이 안전성 확보에 필요한 기술적/관리적 및 물리적 조치를 하고 있습니다.
1. 정기적인 자체 감사 실시
개인정보 취급 관련 안정성 확보를 위해 정기적(분기 1회)으로 자체 감사를 실시하고 있습니다.
2. 개인정보 취급 직원의 최소화 및 교육
개인정보를 취급하는 직원을 지정하고 담당자에 한정시켜 최소화 하여 개인정보를 관리하는 대책을 시행하고 있습니다.
3. 내부관리계획의 수립 및 시행
개인정보의 안전한 처리를 위하여 내부관리계획을 수립하고 시행하고 있습니다.
4. 해킹 등에 대비한 기술적 대책
(주)에이치앤에스 웹사이트는 해킹이나 컴퓨터 바이러스 등에 의한 개인정보 유출 및 훼손을 막기 위하여 보안프로그램을 설치하고 주기적인 갱신·점검을 하며 외부로부터 접근이 통제된 구역에
시스템을 설치하고 기술적/물리적으로 감시 및 차단하고 있습니다.
5. 개인정보의 암호화
이용자의 개인정보는 비밀번호는 암호화 되어 저장 및 관리되고 있어, 본인만이 알 수 있으며 중요한 데이터는 파일 및 전송 데이터를 암호화 하거나 파일 잠금 기능을 사용하는 등의
별도 보안기능을 사용하고 있습니다.
6. 접속기록의 보관 및 위변조 방지
개인정보처리시스템에 접속한 기록을 최소 6개월 이상 보관, 관리하고 있으며, 접속 기록이 위변조 및 도난, 분실되지 않도록 보안기능 사용하고 있습니다.
7. 개인정보에 대한 접근 제한
개인정보를 처리하는 데이터베이스시스템에 대한 접근권한의 부여,변경,말소를 통하여 개인정보에 대한 접근통제를 위하여 필요한 조치를 하고 있으며 침입차단시스템을 이용하여
외부로부터의 무단 접근을 통제하고 있습니다.
8. 문서보안을 위한 잠금장치 사용
개인정보가 포함된 서류, 보조저장매체 등을 잠금장치가 있는 안전한 장소에 보관하고 있습니다.
9. 비인가자에 대한 출입 통제
개인정보를 보관하고 있는 물리적 보관 장소를 별도로 두고 이에 대해 출입통제 절차를 수립, 운영하고 있습니다.
8. 개인정보 보호책임자 작성
① (주)에이치앤에스 웹사이트는 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호책임자를
지정하고 있습니다.
▶ 개인정보 보호책임자
성명 : 김진효
소속 : (주)에이치앤에스
전화번호 : 02-6402-8001
이메일 : hns@hnsts.co.kr
② 정보주체께서는 (주)에이치앤에스 웹사이트의 서비스(또는 사업)을 이용하시면서 발생한 모든 개인정보 보호 관련 문의, 불만처리, 피해구제 등에 관한 사항을 개인정보 보호책임자 및
담당부서로 문의하실 수 있습니다. (주)에이치앤에스 웹사이트는 정보주체의 문의에 대해 지체 없이 답변 및 처리해드릴 것입니다.
9. 개인정보침해 구제방법
정보주체는 개인정보침해로부터 구제받고자 하는 경우 다음과 같은 기관에 도움을 요청할 수 있습니다.
▶ 개인정보 침해신고센터 (한국인터넷진흥원 운영)
– 소관업무 : 개인정보 침해사실 신고, 상담 신청
– 홈페이지 : privacy.kisa.or.kr
– 전화 : (국번없이) 118
– 주소 : (138-950) 서울시 송파구 중대로 135 한국인터넷진흥원 개인정보침해신고센터
▶ 개인정보 분쟁조정위원회 (한국인터넷진흥원 운영)
– 홈페이지 : privacy.kisa.or.kr
– 전화 : (국번없이) 118
– 주소 : (138-950) 서울시 송파구 중대로 135 한국인터넷진흥원 개인정보침해신고센터
10. 개인정보 처리방침 변경
① 이 개인정보처리방침은 시행일로부터 적용되며, 법령 및 방침에 따른 변경내용의 추가, 삭제 및 정정이 있는 경우에는 변경사항의 시행 7일 전부터 공지사항을 통하여 고지할
것입니다.
팝업닫기

본 웹사이트에 게시된 이메일 주소가 전자우편 수집 프로그램이나 그 밖의 기술적 장치를 이용하여 무단으로 수집되는 것을 거부하며, 이를 위반시 정보통신망법에 의해 형사처벌됨을 유념하시기 바랍니다.

게시일 : 2011.4.1