1. 程式人生 > >C/C++編寫一個定時往串列埠(虛擬串列埠)傳送資料的程式

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)執行程式,結果如下:


 到此,成功!