c++串列埠操作
0. 前言
做串列埠方面的程式,使用CreateFile開啟串列埠通訊埠。在對串列埠操作之前,需要首先開啟串列埠。使用C++進行串列埠程式設計,如果採用VS開發,則可以直接藉助於串列埠通訊控制元件來操作,其次,直接呼叫Windows的底層API函式來控制串列埠通訊。
在Window 32bit 的作業系統上, 將串列埠(通訊裝置)作為檔案來處理,所以串列埠的開啟、關閉、讀寫所使用的API函式與檔案操作一樣。所以開啟串列埠使用CreateFile函式,讀寫串列埠使用ReadFile、WriteFile,函式。關閉串列埠使用CloseHandle函式。
1. 檢視通訊串列埠裝置,可以在裝置管理器中檢視;
2.
-------------------------------
1. CreateFile
這個函式的功能是建立或者開啟一個檔案或者I/O裝置,通常使用的I/O形式有檔案、檔案流、目錄、物理磁碟、卷、終端流等。如執行成功,則返回檔案控制代碼。 INVALID_HANDLE_VALUE 表示出錯,會設定 GetLastError 。
函式的宣告定義:
HANDLE WINAPI CreateFile( _In_ LPCTSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile );
引數列表:
部分引數Tips:
1. lpFileName:指定要開啟的串列埠邏輯名,用字串來表示。如COM1, COM2,分別表示串列埠1,和串列埠2.
如果要確定工控機上有那些串列埠,可以使用裝置管理器檢視。如下圖:
檢視方式如下圖:我的電腦,右鍵, 開發“裝置管理器”即可。
2. dwDesiredAccess:埠屬性的訪問型別,
3. dwShareMode:指定埠的共享屬性。
該引數是由那些應用程式共享的檔案提供。對於串列埠來說,是不能共享的,因此,必須設定為0,這是通訊裝置與檔案的特殊差別
。如果當前的應用程式呼叫CreateFile開啟一個串列埠,另外一個程式如果已經打開了該串列埠,此時CreateFile會返回一個錯誤程式碼。
然而,同一個應用程式的多個執行緒是可以共享CreateFile返回的埠控制代碼。並且根據安全屬性設定,該控制代碼可以開啟埠的應用程式的子程式來繼承。
4. lpSecurityAttributes:安全屬性,一般該引數為NULL,即該埠被設定為預設的安全屬性。預設安全屬性下,埠的控制代碼是不能繼承的。
5. dwCreationDisposition:指定此埠正在被其他程式佔用採取的動作,因為串列埠總是存在的,因此必須設定為OPEN_EXISTing, 該標誌高速Windows不要建立新的埠。而是開啟一個已經存在的埠。
, 6. dwFlagsAndSttributes:描述了埠的各種屬性,對於檔案來說有很多屬性,但是對於串列埠來說,唯一的意義是FILE_FLAG _OVERLAPPED 屬性,當設定該屬性時,埠IO可以在後臺進行,稱為非同步IO重疊結構。
7. hTemplateFile: 指定模板的檔案控制代碼,對於串列埠來說,此引數必須設定為0;
關閉串列埠
關閉串列埠,使用CloseHandle,函式宣告為:
函式很簡單,引數是使用CreateFile開啟的埠控制代碼。呼叫這個函式可以實現串列埠關閉。
示例如下:
2. ReadFile
從檔案指標指向的位置(裝置檔案,通訊)開始將資料讀出到一個檔案中, 且支援同步和非同步操作,如果檔案開啟方式沒有指明FILE_FLAG_OVERLAPPED的話,當程式呼叫成功時,它將實際讀出檔案的位元組數儲存到lpNumberOfBytesRead指明的地址空間中。FILE_FLAG_OVERLAPPED 允許對檔案進行重疊操作。
函式宣告定義:
BOOL WINAPI ReadFile( __in HANDLE hFile, // 檔案控制代碼 __out LPVOID lpBuffer, // 接收資料用的 buffer __in DWORD nNumberOfBytesToRead, // 要讀取的位元組數 __out LPDWORD lpNumberOfBytesRead, // 實際讀取到的位元組數 __in LPOVERLAPPED lpOverlapped // OVERLAPPED 結構,一般設定為 NULL );
程式碼示例:、
1 BOOL Read(char *filePath) 2 { 3 HANDLE pFile; 4 DWORD fileSize; 5 char *buffer,*tmpBuf; 6 DWORD dwBytesRead,dwBytesToRead,tmpLen; 7 8 pFile = CreateFile(filePath,GENERIC_READ, 9 FILE_SHARE_READ, 10 NULL, 11 OPEN_EXISTING, //開啟已存在的檔案 12 FILE_ATTRIBUTE_NORMAL, 13 NULL); 14 // 建立裝置檔案,返回檔案的位置 15 if ( pFile == INVALID_HANDLE_VALUE) 16 { 17 printf("open file error!\n"); 18 CloseHandle(pFile); 19 return FALSE; 20 } 21 22 fileSize = GetFileSize(pFile,NULL); //得到檔案的大小 23 24 buffer = (char *) malloc(fileSize); 25 ZeroMemory(buffer,fileSize); 26 dwBytesToRead = fileSize; 27 dwBytesRead = 0; 28 tmpBuf = buffer; 29 30 do{ //迴圈讀檔案,確保讀出完整的檔案 31 32 ReadFile(pFile,tmpBuf,dwBytesToRead,&dwBytesRead,NULL); 33 34 if (dwBytesRead == 0) 35 break; 36 37 dwBytesToRead -= dwBytesRead; 38 tmpBuf += dwBytesRead; 39 40 } while (dwBytesToRead > 0); 41 42 // TODO 處理讀到的資料 buffer 43 44 free(buffer); 45 CloseHandle(pFile); 46 47 return TRUE; 48 }
3. WriteFile
將資料寫入一個檔案(裝置檔案,通訊)。該函式比fwrite函式要靈活的多。也可將這個函式應用於對通訊裝置、管道、套接字以及郵槽的處理。返回時,TRUE(非零)表示成功,否則返回零。會設定GetLastError。
函式宣告定義:
BOOL WINAPI WriteFile( __in HANDLE hFile, // 檔案控制代碼 __in LPCVOID lpBuffer, // 要寫入的資料 __in DWORD nNumberOfBytesToWrite, // 要寫入的位元組數 __out LPDWORD lpNumberOfBytesWritten, // 實際寫入的位元組數 __in LPOVERLAPPED lpOverlapped // OVERLAPPED 結構,一般設定為 NULL );
示例程式碼:
1 BOOL Write(char *buffer, DWORD contentLen) 2 { 3 HANDLE pFile; 4 char *tmpBuf; 5 DWORD dwBytesWrite,dwBytesToWrite; 6 7 pFile = CreateFile(filePath,GENERIC_WRITE, 8 0, 9 NULL, 10 CREATE_ALWAYS, //總是建立檔案 11 FILE_ATTRIBUTE_NORMAL, 12 NULL); 13 14 if ( pFile == INVALID_HANDLE_VALUE) 15 { 16 printf("create file error!\n"); 17 CloseHandle(pFile); 18 return FALSE; 19 } 20 21 dwBytesToWrite = contentLen; 22 dwBytesWrite = 0; 23 24 tmpBuf = buffer; 25 26 do{ //迴圈寫檔案,確保完整的檔案被寫入 27 28 WriteFile(pFile,tmpBuf,dwBytesToWrite,&dwBytesWrite,NULL); 29 30 dwBytesToWrite -= dwBytesWrite; 31 tmpBuf += dwBytesWrite; 32 33 } while (dwBytesToWrite > 0); 34 35 CloseHandle(pFile); 36 37 return TRUE; 38 }