C/C++編寫一個定時往串列埠(虛擬串列埠)傳送資料的程式
利用C/C++來設計一個定時往串列埠(虛擬串列埠)傳送資料的程式,包括虛擬串列埠的配置與串列埠的接收顯示資料:
程式如下:
程式中用到的一些函式說明如下:#include<iostream> #include<windows.h> using namespace std; int main() { HANDLE hcom; hcom = CreateFile("COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL,NULL); if (hcom == INVALID_HANDLE_VALUE) { fprintf(stderr, "開啟串列埠失敗!\n"); exit(0); } SetupComm(hcom,1024,1024); DCB dcb; GetCommState(hcom,&dcb); dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = 0; dcb.StopBits = 1; SetCommState(hcom,&dcb); char data[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; DWORD dwWrittenLen = 0; int k=0; for (;;) { if(!WriteFile(hcom,data,8,&dwWrittenLen,NULL)) { fprintf(stderr, "傳送資料失敗!\n"); } k++; printf("往串列埠傳送資料成功!第%d次\n" ,k); Sleep(10*1000); //10s傳送一次 } return 0; }
HANDLE CreateFile(
LPCTSTR lpFileName
DWORD dwDesiredAccess
DWORD dwSharedMode
LPSECURITY_ATTRIBUTES lpSecurityAttributes
DWORD dwCreationDisposition
DWORD dwFlagsAndAttributes
HANDLE hTemplateFile
);
在呼叫成功時,CreateFile返回開啟檔案的控制代碼,該控制代碼將在以後與該串列埠相關的各個呼叫函式中使用。如果呼叫失敗,則CreateFile返回INVALID_HANDLE_VALUE。
獲取序列口當前狀態:
windows系統使用GetCommState函式獲取序列口的當前配置,GetCommState的宣告如下:
BOOL GetCommState(
HANDLE hFile
LPDCB lpDCB
);
GetCommState函式的第一個引數hFile是由CreateFile函式返回指向已開啟序列口的控制代碼。第二個引數指向裝置控制塊DCB。DCB是一個非常重要的資料結構,幾乎所有的序列口屬性和狀態都儲存在該結構的成員變數中。
對串列埠進行設定:
windows系統利用SetCommState函式修改序列口的當前引數配置。SetCommState函式宣告如下:
BOOL SetCommState(
HANDLE hFile
LPDCB lpDCB
);
GetCommState函式的第一個引數hFile是由CreateFile函式返回指向已開啟序列口的控制代碼。第二個引數指向裝置控制塊DCB。如果函式呼叫成功,則返回值為非0;若函式呼叫失敗,則返回值為0。當應用程式僅僅需要修改一部分序列口的配置值時,可以通過GetCommState函式獲得當前的DCB結構,然後更改引數,再呼叫SetCommState函式設定修改過的DCB來配置序列口。
為串列埠分配接收和傳送緩衝區:
當一個序列口開啟時,可以為該串列埠分配一個傳送緩衝區和一個接收緩衝區。序列口傳送緩衝區和接收緩衝區的配置可以由函式SetupComm實現。如果不呼叫SetupComm,系統會為該串列埠分配預設的傳送緩衝區和接收緩衝區。但是為了保證緩衝區的大小與實際需要的一致,最好呼叫該函式進行設定。SetupComm函式原型如下:
BOOL SetupComm(
HANDLE hFile
DWORD dwInQueue
DWORD dwOutQueue
);
其中hFile是由CreateFile函式返回指向已開啟序列口的控制代碼。引數dwInQueue和dwOutQueue分別指定應用程式推薦使用的接收緩衝區和傳送緩衝區的大小。
序列資料的傳送利用WriteFile函式可以向序列口寫入資料。WriteFile函式原型如下:
BOOL WriteFile(
HANDLE hFile
LPVIOD lpBuffer
DWORD nNumberOfBytesToWrite
LPDWORD lpNumberOfBytesWritten
LPOVERLAPPED lpOverlapped
);
其中引數hFile指向已經開啟的序列口控制代碼;lpBuffer指向一個傳送資料緩衝區;nNumberOfBytesToWrite指定要從序列裝置中傳送的位元組數;lpNumberOfBytesWritten指明實際從序列口中傳送的位元組數;lpOverlapped指向一個OVERLAPPED結構變數,該結構變數中包含一個同步事件。
通常如果呼叫成功,WriteFile返回非0值;否則返回值為0。但是對於傳送操作在後臺進行的串列埠來說,返回值為0不一定說明函式呼叫失敗。此時可以呼叫GetLastError函式獲取進一步的資訊。如果GetLastError返回值為ERROR_IO_PENDING,則說明該寫入串列埠的操作仍然處於後臺等待狀態,而非一個真正意義上的錯誤。
接收資料是會用到:
序列資料的接收
利用ReadFile函式可以讀取將序列口接收到的資料。ReadFile函式原型如下:
BOOL ReadFile(
HANDLE hFile
LPVIOD lpBuffer
DWORD nNumberOfBytesToRead
LPDWORD lpNumberOfBytesRead
LPOVERLAPPED lpOverlapped
);
其中引數hFile指向已經開啟的序列口控制代碼;lpBuffer指向一個讀取資料緩衝區;nNumberOfBytesToRead指定要從序列裝置中讀取的位元組數;lpNumberOfBytesRead指明實際從序列口中讀出的位元組數;lpOverlapped指向一個OVERLAPPED結構變數,該結構變數中包含一個同步事件。
通常如果呼叫成功,ReadFile返回非0值;否則返回值為0。但是對於接收操作在後臺進行的串列埠來說,返回值為0不一定說明函式呼叫失敗。此時可以呼叫GetLastError函式獲取進一步的資訊。如果GetLastError返回值為ERROR_IO_PENDING,則說明該讀取串列埠的操作仍然處於後臺等待狀態,而非一個真正意義上的錯誤。
下面開始測試:
(1)首先下載虛擬串列埠vsdp,安裝後新增兩個串列埠COM3和COM4:
(2)下載一個串列埠除錯工具:由於程式中選擇的串列埠為COM3,而虛擬串列埠中COM3和COM4是相通的,所以串列埠除錯工具應該選擇COM4來顯示程式往COM3傳送的資料,如下:
(3)執行程式,結果如下:
到此,成功!