1. 程式人生 > >CreateFile系類非同步、並行(同一個串列埠傳送接收)

CreateFile系類非同步、並行(同一個串列埠傳送接收)

在Windows系統下,串列埠資料收發CreateFile系類方法對於我來說是最好用的方法,採用非同步機制保證了串列埠讀或寫入不會使程式碼停在串列埠函式內(停在串列埠函式內原因可能是串列埠線的原因,或者串列埠沒開啟(這個是猜測)),並且可以達到同一個串列埠既傳送並接收(測試方法:串聯串列埠線)。

下面說下CreateFile函式串列埠建立開啟、初始化串列埠以及串列埠關閉:
函式定義如下:

WINBASEAPI
__out
HANDLE
WINAPI
CreateFile(
    __in     LPCWSTR lpFileName,
    __in     DWORD dwDesiredAccess,
    __in
DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile );

函式使用如下:

 串列埠非同步開啟:

    m_hWriteFile = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0, NULL
, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if ((HANDLE)0 == m_hWriteFile || (HANDLE)-1 == m_hWriteFile) { MessageBox("沒有開啟串列埠,或者串列埠被佔用!"); } 串列埠初始化配置: SetupComm(m_hWriteFile,4096,1);//設定輸入輸出緩衝區 DCB dcb; GetCommState(m_hWriteFile,&dcb); dcb.
BaudRate = 115200;//位元率 dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = /*TWOSTOPBITS*/ONESTOPBIT;//停止位 SetCommState(m_hWriteFile,&dcb);//設定串列埠狀態 PurgeComm(m_hWriteFile,PURGE_TXCLEAR | PURGE_RXCLEAR); 串列埠關閉: if ((HANDLE)0 != m_hWriteFile && (HANDLE)-1 != m_hWriteFile) { CloseHandle(m_hWriteFile); m_hWriteFile = NULL; }

下面說下WriteFile非同步寫入串列埠資料方法:
函式定義如下:

WINBASEAPI
BOOL
WINAPI
WriteFile(
    __in        HANDLE hFile,
    __in_bcount_opt(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    __in        DWORD nNumberOfBytesToWrite,
    __out_opt   LPDWORD lpNumberOfBytesWritten,
    __inout_opt LPOVERLAPPED lpOverlapped
    );

函式使用如下:

OVERLAPPED ov;//非同步資料儲存的結構體
OMSTAT comstat;//串列埠結構體 ,用來清除串列埠錯誤 建議每次寫資料前都清除一下
memset(&comstat,0,sizeof(comstat));
ClearCommError(collet->m_hWriteFile,&dwError,&comstat);

DWORD dwBytesRead = 0;
memset(&ov,0,sizeof(OVERLAPPED));
ov.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//建立一個事件
BOOL bGetRead = WriteFile(collet->m_hWriteFile,SendFileStr,1,&dwBytesRead,&ov);
DWORD wait = WaitForSingleObject(ov.hEvent,1000);//設定一個事件超時時間 
if (0 != ov.InternalHigh)//資料實際接收位元組數
{
    nGetFilelength -= ov.InternalHigh;
}
else if (0 != dwBytesRead)
{
    nGetFilelength -= dwBytesRead;
}

下面說下ReadFile非同步讀取串列埠方法:
函式定義如下:

WINBASEAPI
BOOL
WINAPI
ReadFile(
    __in        HANDLE hFile,
    __out_bcount_part_opt(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
    __in        DWORD nNumberOfBytesToRead,
    __out_opt   LPDWORD lpNumberOfBytesRead,
    __inout_opt LPOVERLAPPED lpOverlapped
    );

函式使用如下:

DWORD dwError = 0;
COMSTAT comstat;//串列埠結構體 用來清除串列埠錯誤 ,建議每次讀資料時都要先清除一下
memset(&comstat,0,sizeof(comstat));
ClearCommError(collet->m_hWriteFile,&dwError,&comstat);
if (0 == comstat.cbInQue)//判讀是否有資料需要接收
{
    continue;
}
DWORD dwBytesRead = 0;
memset(&ov,0,sizeof(OVERLAPPED));
ov.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//建立事件
BOOL bGetRead = ReadFile(collet->m_hWriteFile,WriteFileStr,1,&dwBytesRead,&ov);
DWORD wait = WaitForSingleObject(ov.hEvent,1000);//設定事件超時時間
if (0 != ov.InternalHigh)
{
    nWriteTextLen += ov.InternalHigh;
}
else if (0 != dwBytesRead)
{
    nWriteTextLen += dwBytesRead;
}

使用說明:
1.ReadFile與WriteFile方法使用同一個串列埠控制代碼(同一個串列埠)可以達到同一個串列埠邊傳送邊接收。
2.建議每次讀或寫串列埠的時候,先清空一下串列埠錯誤。
3.建議專門做個函式用來管理串列埠的開啟與關閉,方便’並行’的使用。