vc串口編程指導(dǎo)報告_第1頁
vc串口編程指導(dǎo)報告_第2頁
vc串口編程指導(dǎo)報告_第3頁
vc串口編程指導(dǎo)報告_第4頁
已閱讀5頁,還剩32頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、深入淺出 VC+ 串口編程之基本概念引言在 PC 機的主板上,有一種類型的接口可能為我們所忽視,那就是Windows系統(tǒng)中稱其為COM 。我們可以通過設(shè)備管理器來查看COMRS-232C 串行接口,在微軟的的硬件參數(shù)設(shè)置,如圖1。圖 1在 Windows上查看PC 串口設(shè)置迄今為止,幾乎每一臺PC 都包含 COM 。本質(zhì)而言, COM 是 PC 為和外界通信所提供的一種串行數(shù)據(jù)傳輸?shù)慕涌?。作為一種物理通信的途徑和設(shè)備,它和目前風靡的另一種串行接口USB所提供的功能是一致的。不過RS-232C顯然已經(jīng)開始被后起之秀USB 趕超,因為USB 的傳輸速率已經(jīng)遠遠超過了RS-232C。盡管如此,RS-

2、232C仍然具有非常廣泛的應(yīng)用,在相對長的一段時間里,難以被USB等接口取代。RS-232C接口(又稱EIA RS-232C), 1970年由美國電子工業(yè)協(xié)會(EIA )聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定,全名是"數(shù)據(jù)終端設(shè)備(DTE )和數(shù)據(jù)通訊設(shè)備(DCE )之間串行二進制數(shù)據(jù)交換接口技術(shù)標準"。本文將對這一接口進行硬件原理的介紹,隨后我們將逐章學(xué)習DOS 平臺的串口編程,及Windows平臺下基于 API 、控件和第三方類的串口編程,最后本文將給出一個綜合實例。在本文的連載過程中,您可以通過如下方式聯(lián)系作者(熱忱歡迎讀者朋友對本文的內(nèi)容提出質(zhì)疑或

3、給出修改意見):作者 email : 21cnbao(可以來信提問,筆者將力求予以回信解答,并摘取其中的典型問題,在本系列文章最后一次連載的讀者反饋中予以闡述);硬件原理眾所周知, CPU 與存儲芯片和I/O 芯片的通信是并行的(并行傳輸?shù)淖畲笪粩?shù)依賴于CPU 的字長、數(shù)據(jù)總線的寬度),一種叫做UART (通用異步收發(fā)器,Universal Asynchronous Receiver/Transmitter)的芯片提供了并行數(shù)據(jù)傳輸和RS-232C串行數(shù)據(jù)傳輸方式的轉(zhuǎn)換。這樣的設(shè)備通常有如圖2 所示的管腳分布,當其向外傳輸數(shù)據(jù)時,CPU 并行的將數(shù)據(jù)寫入這類芯片的寄存器,UART 再將寄存器中

4、的數(shù)據(jù)一位一位地移動并向外傳輸;當外界向其傳輸數(shù)據(jù)時,UART 一位一位地接收數(shù)據(jù),并將其移位組合為并行數(shù)據(jù), CPU 再并行地讀取這些數(shù)據(jù)。實際上,由于UART 芯片一般以TTL/CMOS電平工作,在UART 連接接口之前, 還要經(jīng)過一個TTL/CMOS和 RS-232C 電平的轉(zhuǎn)換。 RS-232C 規(guī)定了其標準的電氣特性,邏輯1 對應(yīng)的電壓必須在-5 -15V 之間;邏輯0 對應(yīng)的的電壓必須在+5 +15V 之間。圖 2 UART 并 /串轉(zhuǎn)換一個常見的 TTL/CMOS 和 RS-232C 電平轉(zhuǎn)換芯片如圖 3 。圖 3 常見的 TTL/CMOS 和 RS-232C 電平轉(zhuǎn)換芯片RS-

5、232C通常以兩類接插件與外界相連,分別稱為DB9 和 DB25 ,如圖 4 所示。圖 4 DB9 和 DB25而接插件中各個針的定義則如表1 :表 1 DB9 和 DB25 引腳定義DB9DB25針號功能說明縮寫針號功能說明縮寫1數(shù)據(jù)載波檢測DCD8數(shù)據(jù)載波檢測DCD2接收數(shù)據(jù)RXD3接收數(shù)據(jù)RXD3發(fā)送數(shù)據(jù)TXD2發(fā)送數(shù)據(jù)TXD4數(shù)據(jù)終端準備DTR20數(shù)據(jù)終端準備DTR5信號地GND7信號地GND6數(shù)據(jù)設(shè)備準備好DSR6數(shù)據(jù)準備好DSR7請求發(fā)送RTS4請求發(fā)送RTS8清除發(fā)送CTS5清除發(fā)送CTS9振鈴指示DELL22振鈴指示DELLRS-232C定義為數(shù)據(jù)通信設(shè)備(DCE )和數(shù)據(jù)終端

6、設(shè)備(究竟一個設(shè)備屬于DCE 還是屬于 DTE 已經(jīng)沒有明顯的界限,互連,連接方法主要有二:DTE )之間的互連,實現(xiàn)上,到現(xiàn)在為止,PC 即可作為 DCE ,又可作為DTE 。兩串口一種方法是,數(shù)據(jù)的發(fā)送和接收由軟件控制,不進行硬件握手,其連接方法如圖5(最常用DB9連接示意)和表2 ( DB9 、DB25 三線連接表),真正需要互相連接的是RXD 、TXD和GND;圖 5 無硬件握手時兩串口連接表 2 DB9 、 DB25 三線連接9針9針5 針25 針29 針25針233222322333557757軟件握手又稱為XON/XOFF ,通常以CTRL-S (0x13 )和 CTRL-Q (

7、0x11 )兩個字符來實現(xiàn)流控制。前者用于請求對方暫停發(fā)送,后者用于清除暫停傳送的請求,繼續(xù)發(fā)送數(shù)據(jù)。另一種方法是,數(shù)據(jù)的發(fā)送和接收由硬件控制,進行硬件握手,其連接方法如圖6(最常用DB9連接示意),需要連接的信號除RXD 、 TXD 和 GND 外,還包括DTR 、 DSR 、 RTS和 CTS。硬件握手依賴于接收設(shè)備準備好后,置RTS 和 CTS 信號,當發(fā)送設(shè)備欲發(fā)送數(shù)據(jù)時,將CTS 信號有效,接著發(fā)送設(shè)備通過信號線TXDRTS 信號置為有效表示請求發(fā)送,開始發(fā)送串行數(shù)據(jù)。這里我們聯(lián)想開來, RTS/CTS 模式在許多領(lǐng)域里都出現(xiàn)過。 回憶一下 IEEE 802.11 無線局域網(wǎng)協(xié)議標準

8、,在其 MAC 協(xié)議中就使用了 RTS/CTS ,RTS/CTS 抽象開來就是一種請求 /應(yīng)答。筆者曾經(jīng)在拙作中多次以實例論證計算機領(lǐng)域里許多知識的相通性,這又是一個明證。圖 6 有硬件握手時兩串口連接實際上,目前我們經(jīng)常使用的是方法一,即只連接RXD 、 TXD 和 GND ,簡單靈活。另外,串口之間互連還有諸多途徑,如圖7 所示。圖 7 其它互連方式Win32串口編程作者:韓耀旭下載源代碼在 工 業(yè) 控 制 中 , 工 控 機 ( 一 般 都 基 于 Windows平 臺 ) 經(jīng) 常 需 要 與 智 能 儀 表通過串口進行通信。串口通信方便易行,應(yīng)用廣泛。一般情況下,工控機和各智能儀表通過

9、 RS485 總線進行通信。RS485 的通信方式是半雙工的,只能由作為主節(jié)點的工控 PC 機依次輪詢網(wǎng)絡(luò)上的各智能控制單元子節(jié)點。每次通信都是由 PC 機通過串口向智能控制單元發(fā)布命令,智能控制單元在接收到正確的命令后作出應(yīng)答。在 Win32 下 ,可 以 使 用 兩 種 編 程 方 式 實 現(xiàn) 串 口 通 信 ,其 一 是 使 用 ActiveX 控件 , 這 種 方 法 程 序 簡 單 , 但 欠 靈 活 。 其 二 是 調(diào) 用 Windows 的 API 函數(shù) , 這 種 方法可以清楚地掌握串口通信的機制,并且自由靈活。本文我們只介紹 API 串口通信部分。串口的操作可以有兩種操作方式

10、:同步操作方式和重疊操作方式(又稱為異步操作方式)。同 步操作時,API 函數(shù)會阻塞直到操作完成以后才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監(jiān)聽線程);而重疊操作方式,API 函數(shù)會立即返回,操作在后臺進行,避免線程的阻塞。無論那種操作方式,一般都通過四個步驟來完成:( 1) 打開串口( 2) 配置串口( 3) 讀寫串口( 4) 關(guān)閉串口( 1) 打開串口Win32 系 統(tǒng) 把 文 件 的 概 念 進 行 了 擴 展 。 無 論 是 文 件 、 通 信 設(shè) 備 、 命 名 管 道 、郵 件槽 、磁 盤 、還 是 控 制 臺 ,都 是 用 API 函 數(shù) CreateFile

11、 來 打 開 或 創(chuàng) 建 的 。該 函數(shù)的原型為:HANDLE CreateFile( LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTESlpSecurityAttributes,DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);lpFileName:將要打開的串口邏輯名,如“COM1”;dwDesiredAccess :指 定 串 口 訪 問 的 類 型 ,可 以 是 讀 取

12、、寫 入 或 二 者 并 列 ; dwShareMode : 指 定 共 享 屬 性 , 由 于 串 口 不 能 共 享 , 該 參 數(shù) 必 須 置 為 0 ;lpSecurityAttributes:引用安全性屬性結(jié)構(gòu),缺省值為 NULL ;dwCreationDistribution:創(chuàng)建標志,對串口操作該參數(shù)必須置為OPEN_EXISTING;dwFlagsAndAttributes : 屬 性 描 述 , 用 于 指 定 該 串 口 是 否 進 行 異 步 操 作 ,該 值 為 FILE_FLAG_OVERLAPPED ,表 示 使 用異 步 的 I/O ;該 值 為 0 ,表 示同步

13、 I/O 操作;hTemplateFile:對串口而言該參數(shù)必須置為 NULL ;同步 I/O方式打開串口的示例代碼:HANDLE hCom; /全局 變量 ,串 口句 柄hCom=CreateFile("COM1",/COM1口GENERIC_READ|GENERIC_WRITE, / 允許 讀 和寫0, /獨占 方式NULL,OPEN_EXISTING, /打開 而不 是創(chuàng) 建0, /同步 方式NULL);if(hCom=(HANDLE)-1)AfxMessageBox("打開 COM失敗 !");return FALSE;return TRUE;重

14、疊 I/O打開串口的示例代碼:HANDLE hCom; /全局 變量 ,串 口句 柄hCom =CreateFile("COM1",/COM1口GENERIC_READ|GENERIC_WRITE, / 允許 讀和 寫0,/獨占 方式NULL,OPEN_EXISTING,/打 開而 不是 創(chuàng)建FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, /重疊 方式NULL);if(hCom =INVALID_HANDLE_VALUE)AfxMessageBox("打開 COM失敗 !");return FALSE;return

15、 TRUE;( 2)、配置串口在打開通訊設(shè)備句柄后,常常需要對串口進行一些初始化配置工作。這需要通過一個 DCB 結(jié)構(gòu)來進行。DCB 結(jié)構(gòu)包含了諸如波特率、數(shù)據(jù)位數(shù)、奇偶校驗和停止位數(shù)等信息。在查詢或配置串口的屬性時,都要用 DCB 結(jié)構(gòu)來作為緩沖區(qū) 。一 般 用 CreateFile打 開 串 口 后 ,可 以 調(diào) 用 GetCommState函 數(shù) 來 獲 取 串 口 的初 始配 置 。要 修 改 串 口 的 配 置 ,應(yīng) 該 先 修 改 DCB 結(jié) 構(gòu) ,然 后 再 調(diào) 用 SetCommState函數(shù)設(shè)置串口。DCB 結(jié)構(gòu)包含了串口的各項參數(shù)設(shè)置,下面僅介紹幾個該結(jié)構(gòu)常用的變量:typ

16、edef struct _DCB/ 波特率,指定通信設(shè)備的傳輸速率。這 個成員可以是實際波特率值或者下面的常量值之一:DWORD BaudRate;CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, CBR_38400,CBR_56000, CBR_57600, CBR_115200 , CBR_128000, CBR_256000 , CBR_14400DWORD fParity; /指定奇偶校驗使能。若此成員為1,允許 奇偶 校驗檢查BYTE ByteSize; /通信 字節(jié) 位數(shù) , 4 8BYTE

17、 Parity; /指 定奇 偶校 驗方 法。 此成員 可以 有下 列值 :EVENPARITY 偶校 驗NOPARITY 無校驗MARKPARITY 標記 校 驗ODDPARITY 奇校驗BYTE StopBits; /指定 停止 位的 位數(shù) 。 此成 員可 以有 下列 值:ONESTOPBIT 1 位停 止位TWOSTOPBITS 2位停止 位ONE5STOPBITS1.5位停 止位 DCB;winbase.h文件中定義了以上用到的常量。如 下:#define NOPARITY0#define ODDPARITY1#define EVENPARITY2#define ONESTOPBIT0

18、#define ONE5STOPBITS1#define TWOSTOPBITS2#define CBR_110110#define CBR_300300#define CBR_600600#define CBR_12001200#define CBR_24002400#define CBR_48004800#define CBR_96009600#define CBR_1440014400#define CBR_1920019200#define CBR_3840038400#define CBR_5600056000#define CBR_5760057600#define CBR_115

19、200115200#define CBR_128000128000#define CBR_256000256000GetCommState函 數(shù) 可 以 獲 得 COM 口 的 設(shè) 備 控 制 塊 , 從 而 獲 得 相 關(guān) 參 數(shù) :BOOL GetCommState(HANDLE hFile, /標識通訊端口的句柄LPDCB lpDCB /指向 一個 設(shè)備 控制 塊( DCB結(jié)構(gòu) )的 指針);SetCommState函數(shù) 設(shè)置 COM口的 設(shè)備 控制塊 :BOOL SetCommState(HANDLE hFile,LPDCB lpDCB);除了在 BCD 中的設(shè)置外,程序一般還需要設(shè)置

20、 I/O緩沖區(qū)的大小和超時。Windows 用 I/O 緩 沖 區(qū) 來 暫 存 串 口 輸 入 和 輸 出 的 數(shù) 據(jù) 。 如 果 通 信 的 速 率 較 高 ,則 應(yīng) 該 設(shè) 置 較 大 的 緩 沖 區(qū) 。調(diào) 用 SetupComm 函 數(shù) 可 以 設(shè) 置 串 行 口 的 輸 入 和 輸 出緩沖區(qū)的大小。BOOL SetupComm(HANDLE hFile,/DWORD dwInQueue,DWORD dwOutQueue通信設(shè)備的句柄/輸入緩沖區(qū)的大小(字節(jié)數(shù))/輸出緩沖區(qū)的大?。ㄗ止?jié)數(shù)));在 用 ReadFile和 WriteFile讀 寫 串 行 口 時 ,需 要 考 慮 超 時

21、問 題 。超 時 的 作 用是 在 指 定 的 時 間 內(nèi) 沒 有 讀 入 或 發(fā) 送 指 定 數(shù) 量 的 字 符 , ReadFile或 WriteFile的 操作仍然會結(jié)束。要 查 詢 當 前 的 超 時 設(shè) 置 應(yīng) 調(diào) 用 GetCommTimeouts函 數(shù) ,該 函 數(shù) 會 填 充 一 個COMMTIMEOUTS結(jié) 構(gòu) 。調(diào) 用 SetCommTimeouts可 以 用 某 一 個 COMMTIMEOUTS結(jié)構(gòu)的內(nèi)容來設(shè)置超時。讀寫串口的超時有兩種:間隔超時和總超時。間隔超時是指在接收時兩個字符之間的最大時延??偝瑫r是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時

22、均支持。用 COMMTIMEOUTS 結(jié)構(gòu)可以規(guī)定讀寫操作的超 時 。COMMTIMEOUTS結(jié)構(gòu)的定義為:typedef struct _COMMTIMEOUTS DWORD ReadIntervalTimeout; /讀間隔 超時DWORD ReadTotalTimeoutMultiplier; /讀時 間系 數(shù)DWORD ReadTotalTimeoutConstant; /讀時間 常量DWORD WriteTotalTimeoutMultiplier; /寫時 間系 數(shù)DWORD WriteTotalTimeoutConstant; /寫時 間常 量 COMMTIMEOUTS,*LPC

23、OMMTIMEOUTS;COMMTIMEOUTS結(jié)構(gòu)的成員都以毫秒為單位。總超時的計算公式是:總超時時間系數(shù)×要求讀/寫的字符數(shù)時間常量例如,要讀入 10 個字符,那么讀操作的總超時的計算公式為:讀 總 超 時 ReadTotalTimeoutMultiplier×10 ReadTotalTimeoutConstant可以看出:間隔超時和總超時的設(shè)置是不相關(guān)的,這可以方便通信程序靈活地設(shè)置各種超時。如 果 所 有 寫 超 時 參 數(shù) 均 為 0 , 那 么 就 不 使 用 寫 超 時 。 如 果 ReadIntervalTimeout為 0 , 那 么 就 不 使 用 讀

24、間 隔 超 時 。 如 果 ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都 為 0 , 則 不 使 用 讀 總 超 時 。 如 果 讀 間 隔 超 時 被 設(shè)置成 MAXDWORD 并且讀時間系數(shù)和讀時間常量都為 0,那么在讀一次輸入緩沖區(qū)的內(nèi)容后讀操作就立即返回,而不管是否讀入了要求的字符。在 用 重 疊 方 式 讀 寫 串 口 時 ,雖 然 ReadFile和 WriteFile在 完 成 操 作以 前 就 可能返回,但超時仍然是起作用的。在這種情況下,超時規(guī)定的是操作的完成時間,而 不 是 ReadFile和 WriteFi

25、le的 返 回 時 間 。配置串口的示例代碼:SetupComm(hCom,1024,1024); /輸入 緩沖區(qū) 和輸 出緩 沖區(qū) 的大小都 是 1024COMMTIMEOUTS TimeOuts;/ 設(shè)定讀超時TimeOuts.ReadIntervalTimeout=1000;TimeOuts.ReadTotalTimeoutMultiplier=500;TimeOuts.ReadTotalTimeoutConstant=5000;/ 設(shè)定寫超時TimeOuts.WriteTotalTimeoutMultiplier=500;TimeOuts.WriteTotalTimeoutConsta

26、nt=2000;SetCommTimeouts(hCom,&TimeOuts); /設(shè)置 超時DCB dcb;GetCommState(hCom,&dcb);dcb.BaudRate=9600; /波特率 為 9600dcb.ByteSize=8; /每個 字節(jié) 有 8 位dcb.Parity=NOPARITY; /無奇 偶校 驗位dcb.StopBits=TWOSTOPBITS; /兩個停 止位SetCommState(hCom,&dcb);PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);在 讀 寫 串 口 之 前 , 還 要

27、用 PurgeComm()函 數(shù) 清 空 緩 沖 區(qū) , 該 函 數(shù) 原 型 :BOOL PurgeComm(HANDLE hFile,/ 串口句 柄DWORD dwFlags/需要 完成 的操 作);參 數(shù) dwFlags指 定 要 完 成 的 操 作 , 可 以 是 下 列 值 的 組 合 :PURGE_TXABORT 中斷 所有 寫操 作并立 即返 回, 即使 寫操作 還沒 有完成。PURGE_RXABORT 中斷 所有 讀操 作并立 即返 回, 即使 讀操作 還沒 有完成。PURGE_TXCLEAR清除 輸出 緩沖 區(qū)PURGE_RXCLEAR 清除 輸入 緩沖 區(qū)( 3)、讀寫串口我

28、 們 使 用 ReadFile和 WriteFile讀 寫 串 口 , 下 面 是 兩 個 函 數(shù) 的 聲 明 :BOOL ReadFile(HANDLE hFile,/ 串口的 句柄/ 讀入的數(shù)據(jù)存儲的地址,/ 即讀入的數(shù)據(jù)將存儲在以該指針的值為首地址的一片內(nèi)存區(qū)LPVOID lpBuffer,DWORD nNumberOfBytesToRead,/要讀 入的 數(shù)據(jù) 的字節(jié) 數(shù)/ 指向 一個 DWORD數(shù)值, 該數(shù) 值返 回讀 操作 實際 讀入 的 字節(jié) 數(shù)LPDWORD lpNumberOfBytesRead,/ 重疊 操作 時,該 參數(shù) 指向 一個 OVERLAPPED結(jié)構(gòu) ,同 步操

29、作時,該參 數(shù)為 NULL。LPOVERLAPPED lpOverlapped);BOOL WriteFile(HANDLE hFile,/ 串口的 句柄/ 寫入的數(shù)據(jù)存儲的地址,/ 即以 該指 針的值 為首 地址 的 nNumberOfBytesToWrite/ 個字節(jié)的數(shù)據(jù)將要寫入串口的發(fā)送數(shù)據(jù)緩沖區(qū)。LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,/ 要寫入 的數(shù) 據(jù)的 字節(jié)數(shù)/ 指向 指向 一個 DWORD數(shù)值 ,該 數(shù) 值返 回實 際寫 入的 字節(jié)數(shù)LPDWORD lpNumberOfBytesWritten,/ 重疊 操作 時,該 參數(shù) 指

30、向 一個 OVERLAPPED結(jié)構(gòu) ,/ 同步 操作 時,該 參數(shù) 為 NULL。LPOVERLAPPED lpOverlapped);在 用 ReadFile 和 WriteFile 讀 寫 串 口 時 ,既 可 以 同 步 執(zhí) 行 ,也 可 以 重 疊 執(zhí) 行 。在同步執(zhí)行時,函數(shù)直到操作完成后才返回。這意味著同步執(zhí)行時線程會被阻塞,從而導(dǎo)致效率下降。在重疊執(zhí)行時,即使操作還未完成,這兩個函數(shù)也會立即返回,費時的 I/O操作在后臺進行。ReadFile和 WriteFile函 數(shù) 是 同 步 還 是 異 步 由 CreateFile函 數(shù) 決 定 , 如 果 在調(diào) 用 CreateFile

31、創(chuàng) 建 句 柄 時 指 定 了 FILE_FLAG_OVERLAPPED標 志 , 那 么 調(diào) 用ReadFile和 WriteFile對 該 句 柄 進 行 的 操 作 就 應(yīng) 該 是 重 疊 的 ; 如 果 未 指 定 重 疊 標志 , 則 讀 寫 操 作 應(yīng) 該 是 同 步 的 。 ReadFile和 WriteFile函 數(shù) 的 同 步 或 者 異 步 應(yīng) 該和 CreateFile 函 數(shù) 相 一 致 。ReadFile函數(shù)只要在串口輸入緩沖區(qū)中讀入指定數(shù)量的字符,就算完成操作 。 而 WriteFile函 數(shù) 不 但 要 把 指 定 數(shù) 量 的 字 符 拷 入 到 輸 出 緩 沖

32、區(qū) , 而 且 要 等 這些字符從串行口送出去后才算完成操作。如 果 操 作 成 功 , 這 兩 個 函 數(shù) 都 返 回 TRUE 。 需 要 注 意 的 是 , 當 ReadFile和WriteFile返 回 FALSE 時 , 不 一 定 就 是 操 作 失 敗 , 線 程 應(yīng) 該 調(diào) 用 GetLastError函數(shù)分析返回的結(jié)果。例 如,在重疊操作時如果操作還未完成函數(shù)就返回,那么函數(shù) 就 返 回 FALSE , 而 且 GetLastError 函 數(shù) 返 回 ERROR_IO_PENDING 。 這 說 明 重疊操作還未完成。同步方式讀寫串口比較簡單,下面先例舉同步方式讀寫串口的代

33、碼:/ 同步讀串口char str100;DWORD wCount;/ 讀 取的 字節(jié) 數(shù)BOOL bReadStat;bReadStat=ReadFile(hCom,str,100,&wCount,NULL);if(!bReadStat)AfxMessageBox("讀串口 失敗 !");return FALSE;return TRUE;/ 同步寫串口char lpOutBuffer100;DWORD dwBytesWrite=100;COMSTAT ComStat;DWORD dwErrorFlags;BOOL bWriteStat;ClearCommError

34、(hCom,&dwErrorFlags,&ComStat);bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,&dwBytesWrite,NULL);if(!bWriteStat)AfxMessageBox("寫串口 失敗 !");PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);在重疊操作時,操作還未完成函數(shù)就返回。重疊 I/O非常靈活,它也可以實現(xiàn)阻塞(例如我們可以設(shè)置一定要讀取到一個數(shù)據(jù)才能進行到下

35、一步操作)。有兩種方法可以等待操作完成:一種方法是用象 WaitForSingleObject這 樣 的 等 待 函 數(shù) 來 等 待 OVERLAPPED結(jié) 構(gòu)的 hEvent成員 ; 另 一 種 方 法 是 調(diào) 用 GetOverlappedResult函 數(shù) 等 待 , 后 面 將 演 示 說 明 。下 面 我 們 先 簡 單 說 一 下 OVERLAPPED結(jié) 構(gòu) 和 GetOverlappedResult函 數(shù) :OVERLAPPED結(jié) 構(gòu)OVERLAPPED結(jié)構(gòu)包含了重疊 I/O的一些信息,定義如下:typedef struct _OVERLAPPED / oDWORD Intern

36、al;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;HANDLE hEvent; OVERLAPPED;在 使 用 ReadFile和 WriteFile重 疊 操 作 時 ,線 程 需 要 創(chuàng) 建 OVERLAPPED結(jié) 構(gòu)以供這兩個函數(shù)使用。線程通過 OVERLAPPED結(jié)構(gòu)獲得當前的操作狀態(tài),該結(jié)構(gòu) 最 重 要 的 成 員 是 hEvent 。 hEvent是 讀 寫 事 件 。 當 串口 使 用 異 步 通 訊 時 , 函 數(shù)返回時操作可能還沒有完成,程序可以通過檢查該事件得知是否讀寫完畢。當 調(diào) 用 ReadFile, WriteF

37、ile函 數(shù) 的 時 候 , 該 成 員 會 自 動 被 置 為 無 信 號 狀 態(tài) ;當重疊操作完成后,該成員變量會自動被置為有信號狀態(tài)。GetOverlappedResult函數(shù)BOOL GetOverlappedResult(HANDLE hFile,/串口的句柄/ 指向 重疊 操作開 始時 指定 的 OVERLAPPED結(jié)構(gòu)LPOVERLAPPED lpOverlapped,/ 指向一個 32 位變量,該變量的值返回實際讀寫操作傳輸?shù)淖止?jié)數(shù) 。LPDWORD lpNumberOfBytesTransferred,/ 該參數(shù)用于指定函數(shù)是否一直等到重疊操作結(jié)束。/ 如果 該參 數(shù)為 TR

38、UE,函數(shù) 直到 操作 結(jié)束 才返 回。/ 如果 該參 數(shù)為 FALSE,函 數(shù)直 接返回 ,這 時如 果操 作沒有 完成,/ 通過 調(diào)用 GetLastError()函數(shù) 會 返回 ERROR_IO_INCOMPLETE。BOOL bWait);該函數(shù)返回重疊操作的結(jié)果,用來判斷異步操作是否完成,它是通過判斷 OVERLAPPED 結(jié) 構(gòu) 中 的 hEvent 是 否 被 置 位 來 實 現(xiàn) 的 。異步讀串口的示例代碼:char lpInBuffer1024;DWORD dwBytesRead=1024;COMSTAT ComStat;DWORD dwErrorFlags;OVERLAPPE

39、D m_osRead;memset(&m_osRead,0,sizeof(OVERLAPPED);m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);ClearCommError(hCom,&dwErrorFlags,&ComStat); dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue); if(!dwBytesRead)return FALSE;BOOL bReadStatus;bReadStatus=ReadFile(hCom,lpInBuffer,dwBytesR

40、ead,&dwBytesRead,&m_osRead);if(!bReadStatus) /如果 ReadFile函數(shù)返回 FALSEif(GetLastError()=ERROR_IO_PENDING)/GetLastError()函 數(shù)返 回 ERROR_IO_PENDING,表明串 口正 在進行讀操作WaitForSingleObject(m_osRead.hEvent,2000);/成或延時已達到2/使用 WaitForSingleObject秒鐘當串口讀操作進行完畢后,函數(shù) 等待 ,直到 讀操 作完m_osRead 的 hEvent 事件會變 為有 信號PurgeCo

41、mm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return dwBytesRead;return 0;PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);return dwBytesRead;對 以 上 代 碼 再 作 簡 要 說 明 : 在 使 用 ReadFileClearCommError函 數(shù) 清 除 錯 誤 。 ClearCommError函數(shù)進行讀操作前,應(yīng)先使用函數(shù)的原型如下:BOOL ClearCo

42、mmError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat/串口 句柄/指向接收錯誤碼的變量/指向通訊狀態(tài)緩沖區(qū));該函數(shù)獲得通信錯誤并報告串口的當前狀態(tài),同時,該函數(shù)清除串口的錯誤標志以便繼續(xù)輸入、輸出操作。參 數(shù) lpStat指 向 一 個 COMSTAT結(jié) 構(gòu) ,該 結(jié) 構(gòu) 返 回 串 口 狀 態(tài) 信 息 。COMSTAT結(jié)構(gòu) COMSTAT 結(jié)構(gòu)包含串口的信息,結(jié)構(gòu)定義如下:typedef struct _COMSTAT / cstDWORD fCtsHold : 1;/ Tx waiting for CTS signalDWORD

43、 fDsrHold : 1;/ Tx waiting for DSR signalDWORD fRlsdHold : 1;/ Tx waiting for RLSD signalDWORD fXoffHold : 1;/ Tx waiting, XOFF char rec''dDWORD fXoffSent : 1;/ Tx waiting, XOFF char sentDWORD fEof : 1;/ EOF character sentDWORD fTxim : 1;/ character waiting for TxDWORD fReserved : 25; / rese

44、rvedDWORD cbInQue;/ bytes in input bufferDWORD cbOutQue;/ bytes in output buffer COMSTAT, *LPCOMSTAT;本 文 只 用 到 了 cbInQue成 員 變 量 , 該 成 員 變 量 的 值 代 表 輸 入 緩 沖 區(qū) 的 字 節(jié) 數(shù) 。最 后 用 PurgeComm函 數(shù) 清 空 串 口 的 輸 入 輸 出 緩 沖 區(qū) 。這 段 代 碼 用 WaitForSingleObject函 數(shù) 來 等 待 OVERLAPPED結(jié) 構(gòu) 的 hEvent成 員,下 面 我 們 再 演 示 一 段 調(diào) 用 Ge

45、tOverlappedResult函 數(shù) 等 待 的 異 步 讀 串 口 示例代碼:char lpInBuffer1024;DWORD dwBytesRead=1024;BOOL bReadStatus;DWORD dwErrorFlags;COMSTAT ComStat;OVERLAPPED m_osRead;ClearCommError(hCom,&dwErrorFlags,&ComStat);if(!ComStat.cbInQue)return 0;dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);bReadStatu

46、s=ReadFile(hCom, lpInBuffer,dwBytesRead,&dwBytesRead,&m_osRead);if(!bReadStatus) /如果ReadFile函數(shù)返回FALSEif(GetLastError()=ERROR_IO_PENDING)GetOverlappedResult(hCom,&m_osRead,&dwBytesRead,TRUE);/ GetOverlappedResult函數(shù) 的最 后一 個參 數(shù)設(shè)為 TRUE,/ 函數(shù)會一直等待,直到讀操作完成或由于錯誤而返回。return dwBytesRead;return

47、0;return dwBytesRead;異步寫串口的示例代碼:char buffer1024;DWORD dwBytesWritten=1024;DWORD dwErrorFlags;COMSTAT ComStat;OVERLAPPED m_osWrite;BOOL bWriteStat;bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,&dwBytesWritten,&m_OsWrite);if(!bWriteStat)if(GetLastError()=ERROR_IO_PENDING)WaitForSingleObject(m_osWrite.hEvent,1000);return dwBytesWritten;return 0;retu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論