国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

在VC++下用Win32 API函數(shù)編寫多線程串口通信程序

2009-02-01 03:29
關(guān)鍵詞:多線程串口通信

金 劍

[摘 要]介紹了使用32位Windows API函數(shù)編寫串口通信程序的方法,采用多線程和事件驅(qū)動技術(shù),使所編寫的程序運(yùn)行效率較高,對于CPU任務(wù)比較繁重的PC機(jī)—單片機(jī)工業(yè)控制系統(tǒng)的性能提高有很大意義。

[關(guān)鍵詞]VC++ Win32 API 串口通信 多線程

[中圖分類號][文獻(xiàn)標(biāo)識碼]A[文章編號]1007-9416(2009)12-0024-02

1 引言

Windows環(huán)境下編程的最大特點(diǎn)就是設(shè)備無關(guān)性,通過驅(qū)動程序?qū)?yīng)用程序與外部設(shè)備相隔離。Windows封裝了通信機(jī)制,稱為通信API,程序員可以利用它間接控制通信端口,不必對硬件進(jìn)行直接操作。目前采用Microsoft公司提供的ActiveX控件MSComm實(shí)現(xiàn)串口通信的實(shí)例相當(dāng)多,使用也非常簡單,但是由于只能在對話框應(yīng)用程序中使用,應(yīng)用范圍有限,而采用API函數(shù)編程就完全避免了這個(gè)問題。

線程是操作系統(tǒng)分配CPU時(shí)間的基本單位,系統(tǒng)不停地在各個(gè)線程之間切換,一個(gè)線程只有在分配的時(shí)間片內(nèi)才對CPU有控制權(quán)。利用Win32系統(tǒng)的多線程特性,主線程負(fù)責(zé)與用戶進(jìn)行交互,設(shè)置輔助線程專門負(fù)責(zé)通信I/O,程序員就可以編寫出準(zhǔn)實(shí)時(shí)的“兩不誤”通信程序。

很多工業(yè)控制系統(tǒng)中常常通過串口連接外設(shè),而各外設(shè)發(fā)送數(shù)據(jù)重復(fù)的頻率不同,要求應(yīng)用程序后臺實(shí)時(shí)無差錯(cuò)地捕捉和處理各端口數(shù)據(jù),同時(shí)前臺仍舊可以與用戶進(jìn)行交互,我們可以在VC++環(huán)境下,用Win32通信API及多線程技術(shù)編寫高效率的通信程序來完成這一任務(wù),開發(fā)過程如下。

2 打開串口

Win32系統(tǒng)中,串口是作為文件處理的,其打開、關(guān)閉、讀取和寫入所用的函數(shù)與文件操作函數(shù)完全一致。通信會話以調(diào)用CreateFile()函數(shù)開始,描述如下。

HANDLE hCom;//定義端口句柄

hCom=CreateFile(“Com1”,//以字符串形式指定要打開的串口名

GENERIC_READ|GENERIC_WRITE,//指定訪問類型,允許讀和寫

0,//指定共享屬性。對于串口,必須設(shè)置為0,表示獨(dú)占

NULL,//引用安全屬性結(jié)構(gòu)。設(shè)為NULL為串口分配缺省的安全屬性

OPEN_EXISTING,//告訴Windows打開已經(jīng)存在的端口

FILE_FLAG_OVERLAPPED,//指定端口I/O可以在后臺進(jìn)行,即異步I/O

NULL//設(shè)定指向模板文件的句柄,對于串口,必須設(shè)置成NULL);

If(hCom==INVALID_HANDLE_VALUE){…}//未成功打開串口,編寫異常處理程序。

3 配置串口

在CreateFile()成功調(diào)用打開串口后,Windows將根據(jù)上次打開串口時(shí)的設(shè)置來初始化端口,如果是首次打開,系統(tǒng)將使用缺省的配置。

3.1 為端口分配緩沖區(qū)

SetupComm(hCom,//已經(jīng)打開的端口句柄,下同

1024,//以字節(jié)數(shù)指定輸入緩沖區(qū)大小

1024,//以字節(jié)數(shù)指定輸入緩沖區(qū)大小);

3.2 清空緩沖區(qū)

PurgeComm(hCom,

PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

PurgeComm()函數(shù)的第二個(gè)參數(shù)指定動作,其設(shè)定值如表1所示:

3.3 設(shè)置驅(qū)動事件類型

SetCommMask(hCom,

EV_RXCHAR//設(shè)定被監(jiān)視的通信事件,見表2);

3.4 定義并設(shè)置超時(shí)結(jié)構(gòu)變量

COMMTIMEOUTS CommTimeOuts;

……//填寫超時(shí)結(jié)構(gòu)

SetCommTimeOuts(hCom, &CommTimeOuts;);//應(yīng)用設(shè)置好的超時(shí)結(jié)構(gòu)

超時(shí)結(jié)構(gòu)是Windows針對串口讀寫引入的數(shù)據(jù)結(jié)構(gòu),直接影響讀和寫的操作行為,定義如下:

typedef struct_COMMTIMEOUTS{

DWORD ReadIntervalTimeout;//以ms為單位指定兩個(gè)字符到達(dá)的最大時(shí)間間隔

DWORD ReadTotalTimeoutMultiplier;//以ms為單位指定計(jì)算讀操作總超時(shí)時(shí)間的系數(shù)

DWORD ReadTotalTimeoutConstant; //以ms為單位指定常數(shù),也用于計(jì)算讀操作超時(shí)時(shí)間

DWORD WriteTotalTimeoutMultiplier;//以ms為單位指定計(jì)算寫操作總超時(shí)時(shí)間的系數(shù)

DWORD WriteTotalTimeoutConstant; //以ms為單位指定常數(shù),也用于計(jì)算寫操作超時(shí)時(shí)間

}COMMTIMEOUTS,*LPCOMMTIMEOUTS;

Windows按如下式子計(jì)算總超時(shí)時(shí)間,可根據(jù)具體應(yīng)用情況設(shè)定超時(shí)結(jié)構(gòu)的參數(shù):

ReadTotalTimeout=ReadTotalTimeoutMultiplier*bytes_to_read+ReadTotalTimeoutConstant;

WriteTotalTimeout=WriteTotalTimeoutMultiplier*bytes_to_write+WriteTotaltimeoutConstant;

3.5 定義并設(shè)置設(shè)備控制塊DCB

DCB dcb;

GetCommState(hCom,&dcb;);//獲取當(dāng)前的DCB狀態(tài)參數(shù)

dcb.BaudRate=9600;//設(shè)定波特率

dcb.ByteSize=8;//設(shè)定端口使用的數(shù)據(jù)位數(shù)

dcb.Parity=NOPARITY;//設(shè)定奇偶校驗(yàn)方法,此處設(shè)為無校驗(yàn)

dcb.StopBits=ONESTOPBIT;//設(shè)定端口使用的停止位位數(shù),此處設(shè)為1位停止位

dcb.fBinary=TRUE;//允許二進(jìn)制。Win32不支持非二進(jìn)制傳輸,此處必須設(shè)為TRUE

dcb.fParity=FALSE;//指定是否允許奇偶校驗(yàn),此處設(shè)為禁止奇偶校驗(yàn)

SetCommState(hCom,&dcb;);//應(yīng)用配置好的參數(shù)

4 啟動輔助線程

CWinThread*m_pThread;//定義線程類變量

……//啟動輔助線程

m_pThread=AfxBeginThread(CommWatchProc,//指定線程處理函數(shù)名

this,//設(shè)置要傳遞給線程函數(shù)的參數(shù)

THREAD_RPIORITY_NORMAL,//設(shè)定優(yōu)先級微調(diào)值

0,//設(shè)置默認(rèn)的堆棧大小(1MB)

CREATE_SUPSPENDED,//掛起創(chuàng)建好的線程

NULL//安全防護(hù)屬性,NULL表示這一屬性與其產(chǎn)生者相同);

if(m_pThread= =NULL)CloseHandle(m_hCom);//未成功創(chuàng)建,關(guān)閉串口

elsem_pThread ->ResumeThread();//成功創(chuàng)建,恢復(fù)線程的運(yùn)行

//線程函數(shù)

UNIT CommWatchProc(HWND hSendWnd)//傳入的參數(shù)是欲投放消息的目的窗口的句柄

{ OVERLAPPED os;

DWORD dwEvtMask=0;//用于記錄事件掩模

COMSTAT ComStat;//COMSTAT結(jié)構(gòu)存放通信設(shè)備的當(dāng)前信息,由ClearCommError函數(shù)填寫

DWORD dwErrorFlag;

BOOL fReadStat;//記錄返回的讀狀態(tài)

while(TRUE){//循環(huán)監(jiān)測串口事件

WaitCommEvent(hCom, &dwEvtMask;,&os;);//等待串口通信事件的發(fā)生

//檢測返回的dwEvtMask,從而判定發(fā)生了何種串口事件

if((dwEvtMask & EV_RXCHAR)==EV_RXCHAR){//緩沖區(qū)有數(shù)據(jù)到達(dá)

ClearCommError(hCom, &dwErrorFlag;, &ComStat;);//清除錯(cuò)誤條件,確定串口狀態(tài)

if(ComStat.cbInQue){//如果串口接收到的字節(jié)數(shù)不為0,就讀取數(shù)據(jù)

fReadStat=ReadFile(hCom,

buffer,//指向一個(gè)緩沖區(qū)

length,//指定要從串口讀取的字節(jié)數(shù)

&length;,//指向調(diào)用該函數(shù)讀出的字節(jié)數(shù)

&os;_Read//指向一個(gè)OVERLAPPED結(jié)構(gòu));

if(!fReadStat)//函數(shù)返回時(shí)I/O操作尚未完成

//等待重疊操作結(jié)果,直到完成異步I/O

GetOverlappedResult(hCom,&os;,&length;,TRUE);

else

return(UNIT)-1;

}

}

PostMessage(hSendWnd,WM_COMMNOTIFY,EV_RXCHAR,0);//發(fā)送消息

}

}

5 編寫發(fā)送命令

BOOL fWriteStat;

char szBuffer[SENDBLOCK];

……//將待發(fā)送的數(shù)據(jù)放在szBuffer[ ]中

//將數(shù)據(jù)寫入串口

fWriteStat=WriteFile(hCom,szBuffer, dwBytesToWrite,&dwBytesToWrite;,os_WRITE);

if(!fWriteStat)

if(GetLastError( )==ERROR_IO_PENDING)

//等待重疊操作結(jié)果

GetOverlappedResult(hCom,&os;_WRITE,&length;,TRUE);

在整個(gè)程序中,OVERLAPPED是個(gè)非常重要的結(jié)構(gòu),用于設(shè)置異步I/O。要使用OVERLAPPED結(jié)構(gòu),CreatFile( )函數(shù)的第六個(gè)參數(shù)必須設(shè)置FILE_FLAG_OVERLAPPED標(biāo)識,同時(shí)串口讀寫函數(shù)ReadFile( )和WriteFile( )的第五個(gè)參數(shù)也必須指定VOERLAPPED結(jié)構(gòu),否則函數(shù)不會正確地報(bào)告I/O操作已經(jīng)完成。

串口使用完畢后必須調(diào)用CloseHandle( )函數(shù)將其關(guān)閉,否則串口會繼續(xù)保持打開狀態(tài),其它程序?qū)o法使用。最后還要編寫WM_COMMNOTIFY消息的處理函數(shù),可根據(jù)具體的工程應(yīng)用情況靈活處理,在此就不贅述了。

6 結(jié)語

Windows為串口通信提供了完善的接口函數(shù),再利用VC++這個(gè)強(qiáng)大的編程開發(fā)環(huán)境,就使得廣大工程技術(shù)人員可以輕松地編寫出界面友好而高效的通信程序,來解決工業(yè)控制領(lǐng)域的許多技術(shù)問題。

參考文獻(xiàn)

[1] 李現(xiàn)勇.Visual C++串口通信技術(shù)與工程實(shí)踐.人民郵電出版社,2002年5月.

[2] Charles Wright著,鄧勁生,張曉明譯.Visual C++程序員使用大全.中國水利水電出版社,2001年10月.

[3] 伍紅兵.Visual C++編程深入引導(dǎo).中國水利水電出版社,2002年3月.

猜你喜歡
多線程串口通信
基于Qt和Flash的嵌入式Linux軟件架構(gòu)設(shè)計(jì)
Java并發(fā)工具包對并發(fā)編程的優(yōu)化
基于MSP430單片機(jī)的窄帶無線數(shù)據(jù)傳輸模塊的設(shè)計(jì)
便攜式數(shù)傳電臺測試系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
福贡县| 勐海县| 额尔古纳市| 阜城县| 唐海县| 衡东县| 霍林郭勒市| 吴旗县| 于都县| 策勒县| 怀宁县| 宜城市| 崇州市| 麻阳| 印江| 荃湾区| 忻州市| 奉化市| 朝阳县| 南陵县| 青阳县| 富阳市| 屯门区| 重庆市| 洛川县| 望城县| 济宁市| 上犹县| 眉山市| 沙湾县| 罗源县| 北碚区| 赤峰市| 福鼎市| 砚山县| 河北省| 民县| 营山县| 南充市| 房产| 包头市|