COMMCONFIG进行配置的WIN32 API
??? 掌握串行通信API函數(shù)的用法是掌握串行通信編程技術(shù)的關(guān)鍵。
??? 在Win32中,系統(tǒng)將串行口與文件統(tǒng)一了起來, 對它們的打開、讀寫、關(guān)閉等操作都使用相同的API函數(shù),但是它們之間又有差別,這些差別主要體現(xiàn)在API函數(shù)中部分參數(shù)的設(shè)置上。有關(guān)通信的API主要包括打開串口、關(guān)閉串口、配置串口、設(shè)置緩沖區(qū)、設(shè)置超時、 事件驅(qū)動、讀串口、寫串口等。下面結(jié)合GPS的具體情況對串口操作函數(shù)的使用方法進(jìn)行詳細(xì)的介紹和分析。
???? 一:串口的打開和關(guān)閉
?????? 1:串口的打開。由于在Windows環(huán)境中,串口作為一種文件來使用,打開串口用打開文件同樣的API函數(shù) CreateFile()。
?????????? 函數(shù)原型為:? HANDLE CreateFile( LPCTSTR lpFileName,
???????????????????????????????????????????????????????????????????? DWORD dwDesiredAccess,
?????????????????????????????????????????????????????????????????????DWORD dwShareMode,
???????????????????????????????????????????????????????????????????? LPSECURITY_ATTRIBUTES lpSecurityAttributes,
???????????????????????????????????????????????????????????????????? DWORD dwCreationDisposition,
???????????????????????????????????????????????????????????????????? DWORD dwFlagsAndAttributes,
???????????????????????????????????????????????????????????????????? HANDLE hTemplateFile
?????????????????????????????????????????????????????????????????? );
??????????其中幾個參數(shù)的含義分別為: lpFileName 指定文件名或設(shè)備名,串口通訊時,它必須是“COMx”,其中的“x”為串口編號,如第一個串口則為“COM1”;
??????????dwDesiredAccess 為串口讀寫屬性; dwShareMode指定該端口的共享屬性,串行口不能作為共 享設(shè)備,故參數(shù)值必須為0;lpSecurityAttributes為安全屬性,對于串口應(yīng)該為0 ; dwCreationDisposition指文件的創(chuàng)建模式,對于串口必須為OPEN—EXISTING; dwFlagsAndAttributes描述了創(chuàng)建文件的其它屬性,對于串行口,有效的設(shè)置只能是FILE-FLAG-OVERLAPPED 或者0,分別表示異步或同步讀寫; 參數(shù)hTemplateFile必須為NULL。
??????????返回值:若成功,返回創(chuàng)建的句柄;否則返回INVALID—HANDLE—VALUE。
??????? 2:串口的關(guān)閉。 關(guān)閉串口相對簡單,通過關(guān)閉句柄BOOL CloseHandle(HANDLE hObject )函數(shù)進(jìn)行, hObject為打開串口時所得到的句柄。句柄關(guān)閉后,串口資源即釋放,其它程序可以使用。
????? 二:配置串口
?????????? 串行口在打開后,將保持上一次使用的配置,要使之和外設(shè)進(jìn)行通信,必須對串口進(jìn)行配置,使之和外設(shè)保持相同的串口配置,這樣才能有效地配置外設(shè)并接收數(shù)據(jù)。
?????????? 在WIN32中,串口的配置主要通過一個稱之為 COMMCONFIG的結(jié)構(gòu)來實(shí)現(xiàn),此結(jié)構(gòu)包含了一個DCB結(jié)構(gòu),在DCB中,有波特率、數(shù)據(jù)位數(shù)、停止位、校驗(yàn)位等串
行口通信參數(shù),對串口的配置主要即是對這些參數(shù)的配置。
????????? 對COMMCONFIG進(jìn)行配置的WIN32 API 主要有一下幾 個:
???????? 1:獲取默認(rèn)配置函數(shù)。其原型為: BOOL GetDefaultCommConfig( LPCSTR lpszName,
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? LPCOMMCONFIG lpCC,
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? LPDWORD lpdwSize)
???????????? 其參數(shù)如下: LpszName為設(shè)備名,如“COM1”; lpCC為COMMCONFIG結(jié)構(gòu)體的指針。 LpdwSize是lpCC的大小。
???????????? 通過使用此函數(shù)可以得到某串口的默認(rèn)配置,此函數(shù)與機(jī)器硬件相關(guān),在不同的機(jī)器上會有不同的結(jié)果,因而容易出錯,所以建議用戶自己重寫此函數(shù),分別對COMMCONFIG的成員進(jìn)行賦值,這樣才穩(wěn)定可靠。
????????? 2:得到串口的當(dāng)前配置,原形如下: BOOL GetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize )
??????????????? 其參數(shù)同GetDefaultCommConfig();
????????? 3:配置串口 BOOL SetCommConfig( HANDLE hCommDev,LPCOMMCONFIG lpCC, DWORD dwSize);
?????????????? 此函數(shù)將由hCommDev指定的串口按lpCC結(jié)構(gòu)體中的內(nèi)容進(jìn)行配置。LPCOMMCONFIG結(jié)構(gòu)體中的主要成員是設(shè)備控制塊結(jié)構(gòu)DCB,在DCB中指定了設(shè)備的波特率,奇偶校驗(yàn)位,流控,停止位等參數(shù)。
????????? 4:配置串口的對話框 BOOL CommConfigDialog(LPCSTR lpszName,HWND hWnd,LPCOMMCONFIG lpCC )
?????????????? 此函數(shù)提供了一個用戶熟悉的串口配置對話框,其句柄為hWnd。用戶可在此對話框中進(jìn)行對lpszName指示的串口配置,配置結(jié)果存放在lpCC所指向的COMMCONFIG結(jié)構(gòu)體中。
??????????5:設(shè)置緩沖區(qū) WIN32環(huán)境下讀寫串口已經(jīng)不是傳統(tǒng)方式下針對串口的UART進(jìn)行,而是提供一緩沖區(qū),串口的讀寫都是針對于此緩沖區(qū)進(jìn)行。
??????????????? 確定緩沖區(qū)的大小比較重要,太大浪費(fèi)資源,太小又會使有效數(shù)據(jù)丟失。用戶必須在串口讀寫前計(jì)算出外設(shè)流量的大小,按照寧大勿小、有所冗余的原則確定合適大小的緩沖區(qū),再使用SetupComm()函數(shù)對串口進(jìn)行設(shè)置。
?????????????? 其原型如下: BOOL SetupComm(HANDLE hFile,DWORD dwInQueue,DWORD dwOutQueue);
?????????????? hFile為打開串口時所得到的句柄; dwInQueue為輸入緩沖區(qū)的大小,以字節(jié)為單位; dwOutQueue為輸出緩沖區(qū)的大小。
??????????6:設(shè)置超時??
?????????????? 數(shù)據(jù)通信過程中可能會發(fā)生的不可預(yù)測的事件,如數(shù)據(jù)傳輸電纜損壞、外設(shè)意外失效中斷,或者發(fā)送數(shù)據(jù)突然停止等等。通信應(yīng)用程序的一個關(guān)鍵問題就是如何處理通信中的不可預(yù)測的事件,處理錯誤事件的能力是一個通信應(yīng)用程序優(yōu)劣的重要標(biāo)志。這些問題處理的不好可能會引起I/O線程掛起或者線程被無限阻塞。
?????????????? Windows對于這類問題提供了安全措施,用戶可以通過超時設(shè)置來決定通信是否異常并作相應(yīng)處理。因此超時設(shè)置在串行通信中顯得尤為重要。
?????????????? 在Win32中提供了SetCommTimeouts()函數(shù)設(shè)置串口的超時值。
?????????????? BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);?
?????????????? hFile為打開串口時所得到的句柄; lpCommTimeouts為指向超時結(jié)構(gòu)體的指針。
???????
????????三:讀寫串口
????????????在打開串口并對其進(jìn)行正確地和必要的配置后就可以用它進(jìn)行通信即讀寫數(shù)據(jù)。讀數(shù)據(jù)就是接收輸入,寫數(shù)據(jù)就是向外設(shè)發(fā)送數(shù)據(jù)。讀寫數(shù)據(jù)通過兩個API函數(shù)完成。
????????? 1:讀數(shù)據(jù)函數(shù)???? BOOL ReadFile ( HANDLE hFile,
???????????????????????????????????????????????????????????????????LPVOID lpBuffer,
?????????????????????????????????????????????????????????????????? DWORD nNumberOfBytesToRead,
?????????????????????????????????????????????????????????????????? LPDWORD lpNumberOfBytesRead,
?????????????????????????????????????????????????????????????????? LPOVERLAPPED lpOverlapped);
?????????????? hFile是由CreateFile()返回的句柄; lpBuffer是讀取的數(shù)據(jù)緩沖區(qū)指針; nNumberOfBytesToRead是要讀取的字節(jié)數(shù); lpNumberOfBytesRead是實(shí)際讀取的字節(jié)數(shù)的首地址; lpOverlapped 是指向一個可重疊I/O(異步)的數(shù)據(jù)結(jié)構(gòu)指針。如果lpOverlapped設(shè)置為NULL,則ReadFile()工作在同步方式;如果lpOverlapped指向一個重疊結(jié)構(gòu),則工作在異步方式。不管是同步還是異步, ReadFile()函數(shù)執(zhí)行后將立刻返回。
??????????
??????????? 2:寫串口函數(shù)???? BOOL WriteFile( HANDLE hFile,
??????????????????????????????????????????????????????????????????? LPVOID lpBuffer,
??????????????????????????????????????????????????????????????????? DWORD nNumberOfBytesToRead,
??????????????????????????????????????????????????????????????????? LPDWORD lpNumberOfBytesRead,
??????????????????????????????????????????????????????????????????? LPOVERLAPPED lpOverlapped);
????????????????其參數(shù)的意義與讀串口相似。
???????? 四:工作模式
???????????? 在串口讀寫操作時,存在多種操作模式,從同步控制角度講,有同步和異步方式,從編程角度講,有查詢方式和事件驅(qū)動方式。
???????????? 在同步讀串口時,如果串口緩沖區(qū)中內(nèi)容沒有讀完,系統(tǒng)將處于等待狀態(tài),直至讀完才返回;如果是異步讀,即使緩沖區(qū)中沒有讀完,系統(tǒng)也將下行,執(zhí)行下一句代碼。如果串口的交互頻繁,則宜使用異步讀寫,但對于一般采集而言,主要是讀數(shù)據(jù),寫命令不多,一次讀取的數(shù)據(jù)量又不會太大,所以使用同步較好,更易于控制。
???????????? 查詢方式是指在一個無窮循環(huán)中直接讀寫串口數(shù)據(jù),對于從串口讀取數(shù)據(jù)來說,查詢是最為直接、最簡單的方法,但是這種方法效率較低,要花費(fèi)大量的CPU時間。
???????????? 事件驅(qū)動方式是指線程通過監(jiān)視通信資源中的一組事件來進(jìn)行讀寫操作,這種方式類似于DOS下的中斷工作方式,效率高。監(jiān)視事件的工作是通過SetCommMask()和WaitCommEvent()函數(shù)進(jìn)行的。在讀或?qū)懖僮髦锌梢酝ㄟ^SetCommMask()函數(shù)設(shè)置事件屏蔽來監(jiān)視指定通信資源上的事件,指定一組事件后,線程可以使用WaitCommEvent()函數(shù)等待其中一個事件發(fā)生,在等待過程中線程將掛起,這樣將花費(fèi)極少的CPU時間,一旦有相應(yīng)事件發(fā)生,WaitCommEvent()將返回, 告訴系統(tǒng)發(fā)生的事件,用戶可以根據(jù)事件的內(nèi)容確定相應(yīng)的處理方式。在等待事件時,WaitCommEvent()函數(shù)將獨(dú)占串口,此時串口既不能讀也不能寫,讀寫工作必須等WaitCommEvent()函數(shù)返回后進(jìn)行。
???????????? 設(shè)置同步控制模式在打開串口時進(jìn)行,由其第三個參數(shù)指定。 而在編程時采用事件驅(qū)動模式的函數(shù)有以下幾個。
?????????? 1:設(shè)置事件掩碼?? BOOL SetCommMask(HANDLE hFile,DWORD dwEvtMask);
??????????????? 其中hFile為打開串口的文件句柄。 DwEvtMask是設(shè)置的掩碼,其形式和意義如下表所示
????????????????掩碼?????????????????????????????? 事件
??????????????? EV_BREAK???????????????????在輸入中檢測到斷點(diǎn)
??????????????? EV_CTS??????????????????????? CTS (clear-to-send) 信號改變狀態(tài)
??????????????? EV_DSR??????????????????????? DSR (data-set-ready) 信號改變狀態(tài)
??????????????? EV_ERR??????????????????????? 出現(xiàn)線路狀態(tài)錯誤
??????????????? EV_RING?????????????????????? 檢測到振鈴指示
??????????????? EV_RLSD????????????????????? RLSD (receive-line-signal-detect) 信號改變狀態(tài)
??????????????? EV_RXCHAR??????????????? ?一個字符到達(dá)并存放于接收緩沖區(qū)
??????????????? EV_RXFLAG????????????????? 一個事件字符到達(dá)并存放于接收緩沖區(qū),事件字符包含在設(shè)備的DCB中,由SetCommState 函數(shù)應(yīng)用到串口
??????????????? EV_TXEMPTY??????????????? 發(fā)送緩沖區(qū)中的最后一個字符被送出
??????????? 2:等待事件到來??
???????????????? BOOL WaitCommEvent(HANDLE hFile,DWORD dwEvtMask,LPOVERLAPPED lpOverlapped);
???????????????? 其參數(shù)意義與設(shè)置掩碼相似。這個函數(shù)表示等待由SetCommMask()函數(shù)設(shè)置的事件的到來,在此函數(shù)工作時,串口處于阻塞模式獨(dú)占串口。 如果定義的事件到來,我們就可以采取相應(yīng)的措施來處理。在數(shù)據(jù)采集時,通常設(shè)置的事件為: EV_RXCHAR,在此事件到來時就可以讀出接收緩沖區(qū)中的數(shù)據(jù)并交給后臺線程處理。 如果使用的串口不止一個,則需要利用Win32的多任務(wù)特性。
總結(jié)
以上是生活随笔為你收集整理的COMMCONFIG进行配置的WIN32 API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 未来物联网全栈开发 --JavaScri
- 下一篇: 关于 UART