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