·串口操縱的基本方法·
在Win32下,對串口的操作就如同對文件一樣打開或關閉,對串行數據的讀寫可在用戶定義的讀寫緩沖區中進行。具體使用的函數為:
首先用CreateFile( )打開通信串口,其中參數lpFileName指向串口邏輯名,如“COM1”或“COM2”等,參數dwDesiredAclearcase/" target="_blank" >ccess定義文件的讀寫權限,一般設為GENERIC—READ|GENERIC—WRITE;參數dwShareMode定義資源共享方式,此處必須設為0,為獨占方式;lpSecurityAttributes定義安全屬性,Win
95下為NULL;dwCreationDistribution定義文件創建方式;dwFlagsAndAttributes定義文件屬性和標記,應設為FILE—FLAG—OVERLAPPED,表示異步通信方式;hTemplateFile
指向一個模板文件的句柄,在 Windows 95下為NULL。
然后用BuildCommDCB( )和SetCommState( )函數通過通信設備控制塊DCB(Device
Control Block)設置串口通信參數(如波特率、停止位、數據位、校驗位等),其中BuildCommDCB(
)中的字符串參數lpDef 定義同DOS命令中MODE的參數格式,關于DCB更具體的設置需要根據用戶對數據流定義、握手信號及通信控制要求具體定義,參見有關Windows技術資料。用GetCommState()可以得到當前的DCB參數值。如果需要還可通過SetCommTimeouts()和GetCommTomeouts()重新設置讀寫的超時參數;讀寫緩沖區的設置使用SetupComm(),參數dwInQueue和
dwOutQueue分別定義為輸入和輸出緩沖區的大小。
在串口初始化完畢后,還要建立與通信有關的事件對象。一般使用CreateEvent()函數,它返回一事件句柄,其中參數lpEventAttributes指向安全屬性結構地址,在Win
95(無安全屬性)中為NULL;布爾參數bManualReset 定義事件重置方式,true
表示手工重置,false表示自動重置(相關函數為SetEvent()和ResetEvent());參數bInitialState定義事件初始狀態,true表示發信號,否則為不發信號;lpName是為多進程設置的事件名,對于單進程定義為NULL。然后用SetCommMask()定義用戶程序可監視的通信事件類別。
以上設置完成后,用戶程序就可以等待通信事件的產生,一般調用函數WaitCommEvent()監視通信事件,其中參數lpEvtMask指向產生事件的掩碼地址,用于判斷事件產生的性質,lpOverlapped指向重疊結構地址,可簡單定義為NULL。對于串口事件的響應一般有四種方式:查詢、同步I/O、異步I/O和事件驅動I/O,需要根據用戶不同控制要求而定。查詢方式占用較長的計算機時間,同步I/O方式直到讀取完指定的字節數或超時時才返回,容易造成線程阻塞,異步I/O用于后臺處理,事件驅動是由系統通知用戶程序發生的事件并進行串口操作。
比較而言事件驅動I/O方式較靈活。
當有通信事件產生時,就可用函數ReadFile()和WriteFile()直接對串口緩沖區進行讀寫操作了。其中lpBuffer
指向讀寫緩沖區,nNumberOfBytes為要讀寫的字節數,lpNumberOfBytes為實際讀寫的字節數,lpOverlapped指定同步或異步操作。通信結束后,調用函數CloseHandle()將串口關閉。
·應用實例說明·
使用以上的API函數,筆者給出了簡化后的串口初始化的實例。圖1為使用C++
Builder 組件生成的串口通信基本參數設置的界面實例。
HANDLE hcom; //定義句柄
DCB dcb;
OVERLAPPED e; //定義重疊結構
void —fastcall TForm1::OkBtnClick(TObject?Sender)
{ hcom=CreateFile("COM2",GENERIC—READ|GENERIC—WRITE,0,NULL,OPEN—EXISTING,FILE—ATTRIBUTE—NORMAL|FILE—FLAG—OVERLAPPED,NULL);
//打開通訊口
BuildCommDCB("9600,O,8,1",&dcb);
//第一個字符串參數實際使用時由圖1選擇后組合,這里僅簡單說明其格式
SetCommState(hcom,&dcb);
SetupComm(hcom,512,512);//設置讀寫緩沖區
e.hEvent=CreateEvent(NULL,false,false,NULL); //設置事件
SetCommMask(hcom,EV—RXCHAR| EV—TXEMPTY); //設置事件掩碼
OkBtn-〉Enabled=false;}