본문 바로가기
C++ 200제/코딩 IT 정보

C++ serial timeout 해결, MFC 시리얼 read write 통신 공통

by vicddory 2017. 2. 20.

C++ serial timeout 해결, MFC 시리얼 read write 통신 공통


Serial timeout

통신 제어 C++ 프로그램은 상대 장치의 상태에 따라 통신이 도중에 끊어질 수 있다. 만약 100바이트가 올것이 데이터 수신 중에 송신 쪽의 문제로 80바이트만 송신한 경우 수신을 도중에 멈추고 알람을 표시할 필요가 있다.


타이머는 이런 목적으로 사용한다. (serial timeout 제어)

■ 시리얼 통신 타이머의 설정 (serial timeout set)

  • SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)를 사용하고


■ 설정된 데이터를 읽을 때

  • GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)를 사용한다.



1
SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
cs



■ hFile

C++ CreateFile()이 반환한 핸들


■ lpCommTimeouts

타이머의 값이 들어있는 COMMTIMEOUTS 구조체의 포인터



C++ serial timeout 해결, MFC 시리얼 read write 통신 공통



■ MFC _COMMTIMEOUTS 반환값

함수가 성공하면 0이 아니고 실패하면 0



1
2
3
4
5
6
7
typedef struct _COMMTIMEOUTS{
    DWORD ReadIntervalTimeout;
    DWORD ReadTotalTimeoutMultiplier;
    DWORD ReadTotalTimeoutConstant;
    DWORD WriteTotalTimeoutMultiplier;
    DWORD WriteTotalTimeoutConstant;
}COMMTIMEOUTS、*LPCOMMTIMEOUTS;
cs



■ ReadIntervalTimeout

시리얼 데이터를 수신할 때 한문자를 수신한 후 다음 문자를 수신할 때까지의 대기 시간으로 밀리초 단위로 설정한다. 이 대기 시간 만큼 기다린 후 입력이 없을 경우 수신한 데이터를 반환한다. 이 값이 0인 경우, 타이머는 사용하지 않는다.


이 값이 MAXDWORD로 ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant가 0인 경우 지정한 수신 수를 수신 전이라도 읽기 작업에서 빠져서 수신 데이터를 반환한다.


■ ReadTotalTimeoutMultiplier

읽기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정.

■ ReadTotalTimeoutConstant

읽기 작업을 위한 토탈 serial timeout 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로 사용된다.


ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant는 읽기 작업에 걸리는 총시간을 설정하는 변수들로 이 두변수가 0인 경우 읽기 작업에는 토탈 타임아웃 타이머가 사용하지 않는다.


■ WriteTotalTimeoutMultiplier

쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정한다.


■ WriteTotalTimeoutConstant

쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로 사용된다.


WriteTotalTimeoutMultiplier와 WriteTotalTimeoutConstant는 쓰기 작업에 걸리는 C++ 시리얼 통신 총시간을 설정하는 변수들로 이 두변수가 0인 경우 쓰기 작업에는 토탈 타임아웃 타이머가 사용하지 않는다.


어플리케이션이 ReadIntervalTimeout과 ReadTotalTimeoutMultilier를 MAXDWORD로 설정하고 MAXDWORD > ReadTotalTimeoutConstant > 0으로 설정하면 ReadFile함수가 사용될 때 아래와 같이 된다.


  • 입력 버퍼에 수신 데이터가 있으면 ReadFile은 바로 버퍼의 문자를 반환.
  • 입력 버퍼에 수신 데이터가 없으면 ReadFile은 수신할 때까지 기다렸다가 반환.
  • ReadTotalTimeoutConstant에 의해 지정된 시간 이내에 1바이트라도 수신하지 않으면 ReadFile은 serial timeout.



serial 타임아웃 read write




타이머의 시간 설정

구체적으로 어떻게 타이머 시간을 설정하면 좋을까?


COMMTIMEOUTS 구조체의 변수를 보면 알 수 있는 것처럼 감시하는 대상은 2종류가 있다. 하나는 인터벌 시간이고 다른 하나는 토탈 시간이다.


인터벌 시간은 수신할 데이터 별로 타이머 감시를 하기 위한 것이기 때문에 예를들면 9600bps로 수신할 경우 1케릭터는 1ms정도이기 때문에 여유를 봐서 10ms이면 충분하다. (단 상대가 연속해서 데이터를 송신하는 경우이다.)


토털 시간은 이하의 계산식으로 계산된다. 이 두개의 감시시간을 넘으면 타임아웃이 발생한다. 타임아웃의 결과 수신 동작이나 송신 동자은 도중에 중단되고 수신일 때는 C++ 시리얼 통신 타임아웃이 발생한 시점까지의 데이터를 읽는다.

■ 수신

ReadIntervalTimeout은 다음에 수신할 때 까지의 최대 대기 시간을 msec로 지정한다.

ReadTotalTimeoutMuliplier와 ReadTotalTimeoutConstant로 수신 토탈 시간을 이하의 식으로 계산한다.


  1. 수신 인터벌 시간 = ReadIntervalTimeout(msec)
  2. 수신 토탈 시간 = (ReadTotalTimeoutMuliplier * 수신할 Byte수) + ReadTotalTimeoutConstant(msec)


■ 송신

송신에는 데이터 간격 타이머는 없다. WriteTotalTimeoutMuliplier와 WriteTotalTimeoutConstant로 송신 토탈 시간을 이하의 식으로 계산한다.


송신 토탈 시간 = (WriteTotalTimeoutMuliplier * 송신할 Byte수) + WriteTotalTimeoutConstant(msec)





serial timeout read write mfc


타이머의 시간 설정 예제


전체 프로젝트 다운로드CommTimeout.zip


소스는 VS2005용이고 컴포트를 COM1에서 COM4로 고정으로 되어있음. 타임아웃을 설정에 따라 어떻게 데이터를 수신하는지를 보여주는 예제.


출처 - [시리얼 통신] 타임아웃 MFC TIP [클릭]

C++ serial timeout 해결, MFC 시리얼 read write 통신 공통






댓글