生活随笔
收集整理的這篇文章主要介紹了
串口通讯编程一日通1(整合资料) .
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文以VC++為平臺進行串口通信編程
串口通訊在VC++下實現方式有很多,控件自然是最簡單話的方式了,但由于控件只支持對話框程序,有些場合又不需要對話框,所以用Windows API實現是比較好的方式
串行通信的操作方式
1.同步方式
同步方式中,讀串口的函數試圖在串口的接收緩沖區中讀取規定數目的數據,直到規定數目的數據全部被讀出或設定的超時時間已到時才返回
[cpp] view plaincopyprint?
COMMTIMEOUTS?timeOver;??memset(&&timeOver,0,sizeof(timeOver));??DWORD?timeMultiplier,timeConstant;??timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;??timeOver.ReadTotalTimeoutConstant=timeConstant;??SetCommTimeouts(hComport,&&timeOver);??……??ReadFile(hComport,?????????????inBuffer,?????????????nWantRead, ?????????????&&nRealRead,???????????????NULL);??
COMMTIMEOUTS timeOver;//COMMTIMEOUTS結構用于設置讀寫函數的等待時間。
memset(&&timeOver,0,sizeof(timeOver));
DWORD timeMultiplier,timeConstant;
timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;
timeOver.ReadTotalTimeoutConstant=timeConstant;
SetCommTimeouts(hComport,&&timeOver);
……
ReadFile(hComport,//串口句柄inBuffer,//緩沖nWantRead,//每次調用ReadFile時,函數試圖讀出的字節數&&nRealRead,//實際讀出的字節數NULL);//代表ReadFile將采用同步文件讀寫的方式
如果所規定的待讀取數據的數目nWantRead較大且設定的超時時間也較長,而接收緩沖區中數據較少,則可能引起線程阻塞。解決這一問題的方法是檢查COMSTAT結構的cbInQue成員,該成員的大小即為接收緩沖區中處于等待狀態的數據的實際個數。如果令nWantRead的值等于COMSTAT.cbInQue,就能較好地防止線程阻塞。
?
2.查詢方式
查詢方式,即一個進程中的某一線程定時地查詢串口的接收緩沖區,如果緩沖區中有數據,就讀取數據;若緩沖區中沒有數據,該線程將繼續執行,因此會占用大量的CPU時間,它實際上是同步方式的一種派生。
[cpp] view plaincopyprint?
COMMTIMEOUTS?timeOver;??memset(&&timeOver,0,sizeof(timeOver));??timeOver.ReadIntervalTimeout=MAXWORD;??SetCommTimeouts(hComport.&&timeOver);??……??ReadFile(hComport.??????????inBuffer.??????????nWantRead.???????????&&nRealRead,????????????NULL);??
COMMTIMEOUTS timeOver;
memset(&&timeOver,0,sizeof(timeOver));
timeOver.ReadIntervalTimeout=MAXWORD;//注意和同步方式不同的地方
SetCommTimeouts(hComport.&&timeOver);
……
ReadFile(hComport.inBuffer.nWantRead.&&nRealRead,NULL);//代表ReadFile將采用同步文件讀寫的方式
除了COMMTIMEOUTS結構的變量timeOver設置不同外,查詢方式與同步方式在程序代碼方面很類似,但二者的工作方式卻差別很大。盡管ReadFile采用的也是同步文件讀寫方式,但由于timeOver的區間超過時間設置為MAXWORD,所以ReadFile每次將讀出接收隊列中的所有處于等待狀態的數據,一次最多可讀出nWantRead個字節的數據。
?
3.異步方式
異步方式中,利用Windows的多線程結構,可以讓串口的讀寫操作在后臺進行,而應用程序的其他部分在前臺執行。
[cpp] view plaincopyprint?
OVERLAPPED?wrOverlapped;??COMMTIMEOUTS?timeOver;??memset(&&timeOver.0.sizeof(timeOver));??DWORDtimeMultiplier,timeConstant;??timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;??timeOver.ReadTotalTimeoutConstant=timeConstant;??SetCommTimeouts(hComport,&&timeOver);??wrOverlapped.hEvent=CreateEvent(NULL.TRUE,FALSE,NULL);??……??ReadFile(hComport,?????????????nBuffer,?????????????nWantRead,?????????????&&nRealRead,?????????????&&wrOverlapped);?????? ??GetOverlappedResult(hComport,??????????????????&&wrOverlapped,??????????????????&&?nRealRead,??????????????????????TRUE);????……??ResetEvent(wrOverlapped.hEvent);??
OVERLAPPED wrOverlapped;
COMMTIMEOUTS timeOver;
memset(&&timeOver.0.sizeof(timeOver));
DWORDtimeMultiplier,timeConstant;
timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;
timeOver.ReadTotalTimeoutConstant=timeConstant;
SetCommTimeouts(hComport,&&timeOver);
wrOverlapped.hEvent=CreateEvent(NULL.TRUE,FALSE,NULL);//創建事件句柄
……
ReadFile(hComport,nBuffer,nWantRead,&&nRealRead,&&wrOverlapped);//異步方式并且與事件聯系上
/*由于采用了異步方式,所以它只返回數據是否已開始讀入的狀態,并不返回實際的讀入數據,即ReadFile中的nRealRead無效*///實際讀入的數據是由GetOverlappedResult函數返回的
GetOverlappedResult(hComport,&&wrOverlapped,&& nRealRead,TRUE);
/*表示它等待異步操作結束后才返回到應用程序,此時,GetOverlappedResult函數與WaitForSingleObject函數等效。*/
……
ResetEvent(wrOverlapped.hEvent);//釋放事件句柄
當采用異步方式時,在用CreateFile打開串口設備時,CreateFile函數的參數fdwAttrsAndFlags必須設為FILE_FLAG_ OVERLAPPED。在Windows中,只有在串行設備上才支持異步文件讀寫,并且,GetOverlappedResult函數也只支持串行設備或用DeviceloControl函數打開的文件。
4.事件驅動
若對端口數據的響應時間要求較嚴格,可采用事件驅動方式。事件驅動方式通過設置事件通知,當所希望的事件發生時,Windows發出該事件已發生的通知,這與DOS環境下的中斷方式很相似。Windows定義了9種串口通信事件,較常用的有以下三種:
EV_RXCHAR:接收到一個字節,并放入輸入緩沖區;
EV_TXEMPTY:輸出緩沖區中的最后一個字符,發送出去;
EV_RXFLAG:接收到事件字符(DCB結構中EvtChar成員),放入輸入緩沖區。
在用SetCommMask()指定了有用的事件后,應用程序可調用WaitCommEvent()來等待事件的發生。SetCommMask(hComm,0)可使WaitCommEvent()中止。
?
[cpp] view plaincopyprint?
COMSTAT?comStat;??DWORD?dwEvent;??SetCommMask(hComport,EV_RXCHAR); ????……??if(WaitCommEvent(hComport,&&dwEvent,NULL))?? if((dwEvent&&EV_RXCHAR)&&&&comstat.cbInQue)?? ReadFile(hComport,????????????????inBuffer,?????????????????comstat.cbInQue,????????????????&&nRealRead,??????????????????NULL);??
總結
以上是生活随笔為你收集整理的串口通讯编程一日通1(整合资料) .的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。