1. 程式人生 > >c++串列埠操作

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 }