이전에 올린 포스트에서 어떻게 시리얼 COM 포트를 여는지, 또 어떻게 OVERLAPPED 구조체를 만드는지와 포트를 이용한 읽기 쓰기 작업에 타임아웃을 거는 방법에 대해 알아보았다. 그런데 뭔가 허전하지 않은가? 맞다. 시리얼 COM 포트를 열긴 열었는데 실제로 이 시리얼 통신이 어떤 특성을 가질 것인지는 설정하지 않았다.
그래서 요번에는 DCB (Device Control Block)를 이용한 COM 포트의 시리얼 통신 특성을 설정해 볼 것이다.
먼저 시리얼 통신 특성 설정에는 DCB 구조체가 사용된다. 시리얼 통신에 사용되는 여러가지 통신특성들이 설정되어 있는 구조체로 자세한 사항은 아래를 참조하면 되겠다.
typedefstruct_DCB {
DWORD DCBlength;
DWORD BaudRate;
DWORD fBinary :1;
DWORD fParity :1;
DWORD fOutxCtsFlow :1;
DWORD fOutxDsrFlow :1;
DWORD fDtrControl :2;
DWORD fDsrSensitivity :1;
DWORD fTXContinueOnXoff :1;
DWORD fOutX :1;
DWORD fInX :1;
DWORD fErrorChar :1;
DWORD fNull :1;
DWORD fRtsControl :2;
DWORD fAbortOnError :1;
DWORD fDummy2 :17;
WORD wReserved;
WORD XonLim;
WORD XoffLim;
BYTE ByteSize;
BYTE Parity;
BYTE StopBits;
char XonChar;
char XoffChar;
char ErrorChar;
char EofChar;
char EvtChar;
WORD wReserved1;
} DCB, *LPDCB;
DCBlength
Byte 단위로 DCB 구조체 길이 지정
BaudRate
통신장치가 사용하는 전송 속도(Baud rate) 지정
실제 baud rate 를 입력 하거나 다음 baud rate 인덱스 중 하나 선택
┣━━━━━━━━━━━━┓
┣> CBR_110 ┣> CBR_19200
┣> CBR_300 ┣> CBR_38400
┣> CBR_600 ┣> CBR_56000
┣> CBR_1200 ┣> CBR_115200
┣> CBR_2400 ┣> CBR_128000
┣> CBR_4800 ┗> CBR_256000
┣> CBR_9600
┗> CBR_14400
fBinary
바이너리 모드 활성화를 지정
Win32 API는 이진이 아닌 모드는 전송을 지원하지 않기 때문에 반드시 TRUE로 지정 해 줘야 함
FAULSE이면 작업을 할 수 없음
fParity
패리티체크 활성화를 지정
만약 TRUE이면, 패리티체크는 실행되고 에러 보고도 됨
fOutxCtsFlow
출력을 CTS(clear-to-send)신호로 제어할 것인가를 지정
TRUE이면 CTS신호로 송신 흐름 제어를 하며,
CTS신호가 off이면, 데이터를 보낼 수 없음
fOutxDsrFlow
출력을 DSR(data-set-ready)신호로 제어 할 것인가를 지정
TRUE이면 DSR신호로 송신 흐름 제어를 하며,
DSR신호가 off이면, 데이터를 보낼 수 없음
fDtrControl
DTR(data-terminal-ready) 조절 컨트롤 지정.
다음 값 중에 하나를 지정할 수 있음
┃
┣>DTR_CONTROL_DISABLE
┃ ┗ 장치를 열 때 DTR 라인의 비활성화하고 계속 비활성화 유지
┃
┣>DTR_CONTROL_ENABLE
┃ ┗ 장치를 열 때 DTR 라인의 활성화하고 계속 활성화 유지
┃
┗>DTR_CONTROL_HANDSHAKE
┗ 수신버퍼의 데이터 양에 따라 시리얼 드라이버가 DTR 라인을 토글 할 때(ON/OFF)
fDsrSensitivity
통신 장치가 DSR 신호의 상태를 감지 할 것인지 지정
만약 이 값이 TRUE 일 경우 DSR라인이 활성화 될때까지 들어 오는 모든 바이트들을 무시
fTXContinueOnXoff
입력버퍼가 꽉차고 드라이버가 XoffChar 문자가 전송될 경우 전송을 멈출 것인지 지정
만약 이 값이 TRUE일 경우 수신 버퍼가 한계에 다다른 후 드라이버가 XOFF 문자를 송신할 경우 문자 전송을 멈춤
fOutX
전송을 할 동안 XON/XOFF흐름 제어를 사용할 것인지 지정
만약 이 값을 TRUE일 경우 XonChar 문자를 받았을 경우 송신 / Xoffchar 문자를 받았을 경우 송신 중지
fInX
수신이 되는 동안 XON/XOFF흐름 제어를 사용할 것인지 지정
만약 이 값을 TRUE일 경우 XoffLim 바이트로 입력버퍼가 가득찼을 때 XoffChar 문자가 보내지고
입력버퍼가 XonLim 바이트 이하로 비었을 때 XonChar 문자가 보내짐
fErrorChar
패리티 에러가 수신된 바이트들은 ErrorChar 멤버로 지정된 문자로 대치할 것인가를 지정
만약 이 값이 TRUE이면서 fParity 멤버가 TRUE이면 변환이 일어남
fNull
null 바이트를 삭제 시킬지 지정
만약 이 값이 TRUE이면 받은 null 바이트들은 삭제 됨
fRtsControl
RTS (request-to-send)흐름제어를 사용할 것인지 지정
만약 이 값이 0이면 디폴트 RTS_CONTROL_HANDSHAKE
다음 값 중 하나를 지정할 수 있음.
┃
┣> RTS_CONTROL_DISABLE
┃ ┗ 장치를 열 때 RTS 라인의 비활성화하고 계속 비활성화 유지
┃
┣> RTS_CONTROL_ENABLE
┃ ┗ 장치를 열 때 RTS 라인의 활성화하고 계속 활성화 유지
┃
┣> RTS_CONTROL_HANDSHAKE
┃ ┗ RTS 흐름제어를 자동으로 함 입력버퍼가 절반이하일 경우 켜고 절반이상일 경우 끔
┃
┗> RTS_CONTROL_TOGGLE
┗ 출력 버퍼 안에 전송 대기 중인 바이트가 있으면 RTS 라인을 켜고 반대 일 경우 끔
fAbortOnError
에러가 발생할 때 읽기 쓰기 작업을 종료 할 것인지 정함
만약 이 값이 TRUE이면, 에러가 발생할 경우 모든 읽기 쓰기 작업과 에러 상태가 종료 됨
fDummy2
사용안함
wReserved
사용안함 : 항상 0이어야 함
XonLim
XON 문자를 자동으로 전송하기 위해 입력 버퍼 안에 있어야 하는 최소한의 바이트 개수를 설정
XoffLim
XOFF 문자가 전송되게 하는 최대한의 바이트 개수를 설정
허용되는 최대 바이트 = 입력버퍼 - XoffLim
ByteSize
바이트당 비트 수(4~8bit, 보통 7~8 사용)
Parity
사용될 패리티를 지정
다음 값 중 하나 지정 할 수 있음
┃
┣> EVENPARITY = 짝수
┃
┣> MARKPARITY = 마크
┃
┣> NOPARITY = 없음
┃
┣> ODDPARITY = 홀수
┃
┗> SPACEPARITY = 간격
StopBits
사용될 STOP 비트 수를 설정
다음 값 중 하나 지정 할 수 있음
┃
┣> ONESTOPBIT = 1비트
┃
┣> -NE5STOPBITS = 1.5비트
┃
┗> TWOSTOPBITS = 2비트
XonChar
송, 수신에 사용될 XON문자 지정
XoffChar
송, 수신에 사용될 XOFF문자 지정
ErrorChar
패리티 에러를 받은 바이트에 대체할 문자
EofChar
데이터 끝을 나타내는데 사용하는 문자 지정
EvtChar
이벤트 신호에 사용할 문자
wReserved1
사용안함
매우 많은 필드와 설명이 있지만, 알아야 되는 필드는 몇개 되지 않는다. 대부분의 설정값은 시스템이 초기에 설정해 놓은 값을 그대로 사용한다. 사용자는 GetCommState함수를 이용해 시스템이 설정해 놓은 COM 포트의 설정값을 가지고 오고 몇몇 변수를 고친다음에 SetCommState로 다시 COM 포트의 설정값을 변경하면 된다.
BOOL GetCommState (HANDLE hFile, LPDCB lpDCB)
BOOL SetCommState (HANDLE hFile, LPDCB lpDCB)
실제 사용은 아래와 같이 한다.
Get으로 가지고 와서 버드레이트, 패리티, 바이트로 뭉쳐서 쓰기 위해 받는 비트 수, 그리고 스톱 비트를 몇개 사용할 것인지를 결정하여 Set으로 설정했다.
(코드를 그대로 복사하다보니..-_- 위에 접어놓은 DCB 설명을 참조하여 설정할 것)
이제 거의 모든 설정이 다 끝났다. 마지막으로 아래 SetupComm 함수를 이용하여 읽기 쓰기에 사용할 큐의 크기를 지정하고 각 큐를 깔끔하게 비워낸다.