미친해커

[C] Serial Monitor Step 5 - 시리얼 번호로 핸들 가져오기 본문

C/Serial Monitor

[C] Serial Monitor Step 5 - 시리얼 번호로 핸들 가져오기

미친해커 2021. 12. 28. 19:27
반응형

기본적인 시리얼 포트와의 통신 방법은 다 알아봤다. 이제 배운 지식을 활용해 간단한 모듈을 만들어보는 것이다. 우선 첫번째로 시리얼 통신을 위해서는 시리얼 포트의 핸들이 필요하고 핸들을 얻기 위해서는 통신하고 싶은 시리얼 포트의 번호를 알아야한다. 즉 이번에는 시리얼 번호를 이용해 해당 시리얼 포트의 핸들을 반환해주는 함수를 만들어본다. 사용되는 Windows API와 구조체는 다음과 같다.

 

CreateFileW function (fileapi.h) - Win32 apps

Creates or opens a file or I/O device. The most commonly used I/O devices are as follows:\_file, file stream, directory, physical disk, volume, console buffer, tape drive, communications resource, mailslot, and pipe.

docs.microsoft.com

 

GetCommState function (winbase.h) - Win32 apps

Retrieves the current control settings for a specified communications device.

docs.microsoft.com

 

SetCommState function (winbase.h) - Win32 apps

Configures a communications device according to the specifications in a device-control block (a DCB structure). The function reinitializes all hardware and control settings, but it does not empty output or input queues.

docs.microsoft.com

 

SetCommTimeouts function (winbase.h) - Win32 apps

Sets the time-out parameters for all read and write operations on a specified communications device.

docs.microsoft.com

 

DCB (winbase.h) - Win32 apps

Defines the control setting for a serial communications device.

docs.microsoft.com

 

COMMTIMEOUTS (winbase.h) - Win32 apps

Contains the time-out parameters for a communications device.

docs.microsoft.com

위 함수와 구조체에 대해 잘 모른다면 문서를 읽거나 이전 포스팅을 읽는것을 추천한다.

HANDLE GetCommHandleByComNumber(DWORD ComNumber)
{
    WCHAR CommName[16];

    swprintf(CommName, 16, L"\\\\.\\COM%d", ComNumber);

    HANDLE hComm = CreateFileW(CommName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hComm == INVALID_HANDLE_VALUE)
    {
        printf("CreateFileW Failed\n");
        printf("GetLastError : %d\n", GetLastError());
        return INVALID_HANDLE_VALUE;
    }

    DCB state;

    if (GetCommState(hComm, &state) == FALSE)
    {
        printf("GetCommState Failed\n");
        printf("GetLastError : %d\n", GetLastError());
        CloseHandle(hComm);
        return INVALID_HANDLE_VALUE;
    }

    state.DCBlength = sizeof(DCB);
    state.BaudRate = CBR_115200;
    state.ByteSize = 8;
    state.Parity = NOPARITY;
    state.StopBits = ONESTOPBIT;

    if (SetCommState(hComm, &state) == FALSE)
    {
        printf("SetCommState Failed\n");
        printf("GetLastError : %d\n", GetLastError());
        CloseHandle(hComm);
        return INVALID_HANDLE_VALUE;
    }

    COMMTIMEOUTS timeout = { 0 };
    timeout.ReadIntervalTimeout = 50;
    timeout.ReadTotalTimeoutConstant = 50;
    timeout.ReadTotalTimeoutMultiplier = 10;
    timeout.WriteTotalTimeoutConstant = 50;
    timeout.WriteTotalTimeoutMultiplier = 10;

    if (SetCommTimeouts(hComm, &timeout) == FALSE)
    {
        printf("SetCommTimeouts Failed\n");
        printf("GetLastError : %d\n", GetLastError());
        CloseHandle(hComm);
        return INVALID_HANDLE_VALUE;
    }

    return hComm;
}

위와 같이 ComNumber만 인자로 넘겨주게된다면 해당 시리얼 포트의 핸들을 반환해주는 함수를 정의하였다. 그 외에 해당 핸들의 대한 설정들도 자동으로 해주기때문에 생각보다 많은 작업을 줄일 수 있게되었다.

반응형
Comments