Friday, November 20, 2009

VC下面使用RS-232

這陣子在搞一些Z-wave的東東,需要透過RS-232跟Z-wave module上面的UART來作溝通,因此寫了一段小程式來連接RS-232與Z-Wave module上面的UART,在這裡作點小紀錄...

//所需要用到的變數宣告
#define BUFF_SIZE 1024*10
HANDLE hSerial;
HANDLE hWaitEvent;
DCB dcbSerialParams = {0};
OVERLAPPED osStatus = {0};
DWORD dwBytesWrite = 0;
DWORD dwBytesRead = 0;
char szBuff[BUFF_SIZE];
char szBuff_R[BUFF_SIZE];

//開啟需要的Serial Port
//com_str = COM1, COM2, ...
hSerial = CreateFile( com_str, GENERIC_READ | GENERIC_WRITE, 0, 0,
                                     OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
//使用GetCommState來取得目前Serial Port的配置
if (!GetCommState(hSerial, &dcbSerialParams)) {
        //error getting state
}
dcbSerialParams.BaudRate=CBR_115200;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
//使用SetCommState來設定所要的Serial Port的配置
if(!SetCommState(hSerial, &dcbSerialParams)){
       //error setting serial port state
}


//對Serial Port來說,必須配置timeout值,
//否則可能陷入到無窮循環來等待來自Serial Port的資料
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts)){
     //error occureed. Inform user
}
hWaitEvent = CreateEvent( NULL, true, false, NULL );
ZeroMemory( &osStatus, sizeof( OVERLAPPED ) );
osStatus.hEvent = hWaitEvent;

//開個thread來執行下面的迴圈收取Serial Port過來的資料
while(1)
{
    retCode=ReadFile(hSerial, szBuff_R, BUFF_SIZE, &dwBytesRead, &osStatus);
    if (!retCode)
    {
        DWORD lasterror=GetLastError();
        switch(lasterror)
        {
            // 假使IO Pending 中,則等待直到被通知可讀為止,
            //換句話說 , block 在這裡的 thread 會先交出控制權 , 避免 busy-loop
            case ERROR_IO_PENDING:
                  WaitForSingleObject ( hWaitEvent , -1 ); //  -1 = no timw-out
                  break;
            default:
                  WaitForSingleObject ( hWaitEvent , -1 );
                  break;
         }
     }
     retCode = GetOverlappedResult ( hSerial , &osStatus , &dwBytesRead, FALSE );
     if(retCode)
     {
        //收到資料在szBuff_R中,收到的資料長度為dwBytesRead
     }
}

//如果要寫資料到Serical Port,可以透過下面的函數在任何地方呼叫
WriteFile(hSerial, szBuff, dwBytesWrite, &dwBytesWrite, &osStatus);

No comments:

Post a Comment