日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > Win32串行通信中文版(Serial Communications In Win32)

Win32串行通信中文版(Serial Communications In Win32)

來源:程序員人生   發布時間:2016-07-11 08:53:31 閱讀次數:3235次

轉:http://blog.csdn.net/zcube/article/details/8591972

到http://download.csdn.net/detail/zcube/5079651下載排版好的PDF版本。   

原文鏈接:http://msdn.microsoft.com/en-us/library/ms810467.aspx 

         艾倫戴夫

         微軟Windows開發者支持中心

          1995/12/11

         利用于:

  • Microsoft? Win32?
  • Microsoft Windows?

         摘要:學習Win32中的串口通訊和16Windows操作系統中的串口通訊有很大的不同。這篇文章假定讀者已熟習Win32下多線程和同步的基本原理。另外,如果對Win32中的heap功能如果有基礎的了解,將使讀者在完全理解這篇文章中提到的多線程TTYMTTTY)例子的內存管理方法上是很有用的。 

綜述

        Win32中的串口通訊和16Windows中的串口通訊有顯著的不同。那些熟習16位串口通訊函數的開發人員將不能不重新學習許多系統部份的知識,以便能編寫正確的串口通訊程序。這篇文章將幫助實現這個目標。那些不熟習串口通訊的人員將發現這篇文章會為他們以后研究發展奠定堅實的基礎。 

        這篇文章假定讀者已熟習Win32下多線程和同步的基本原理。另外,如果對Win32中的heap功能如果有基礎的了解,將使讀者在完全理解這篇文章中提到的MTTTY例子的內存管理方法上是很有用的。 

        關于這些函數的更多信息,請查閱平臺SDK文檔:微軟Win32知識庫或微軟開發者聯機文庫。雖然那些控制用戶界面特性的利用程序接口(APIs)和對話框在這里其實不討論,但是對完全理解這篇文章所提供的例程還是很有用的。不熟習1般的Windows編程的讀者在開始處理串行通訊前首先應當學習1些Windows編程基礎。換句話說,冒失地潛水前先沾濕你的腳。 

引言

        這篇文章主要介紹利用程序接口(APIs)和微軟Windows NTWindows 95所兼容的方法。因此,只討論在NT95這兩個平臺上都被支持的APIs。Windows 95支持Win32電話APITAPI),但是Windows NT3.x卻不支持。因此,這里不對TAPI進行討論。但是,TAPI值得1提的時,它在調制解調器的連接和調用控制上是非常好的工具。如果1個利用程序產品觸及調制解調器工作和電話撥號,那末利用TAPI接口可以實現這些功能。它允許和用戶可能有的TAPI程序實現無縫結合。另外,這篇文章也不討論Win32中的1些配置函數,像GetCommProperties。 

        這篇文章包括的例子,MTTTY:多線程TTY4918.exe),實現了許多這里所要討論的功能。在它的實現中使用了3個線程:1個用戶界面線程實現內存管理、1個寫線程實現控制所有的寫操作、還有1個讀/狀態線程實現讀數據和處理端口上產生改變的狀態。該例子采取1些不同的數據堆實現內存管理。它也廣泛使用同步方法增進線程之間的通訊。 

打開串口

         使用CreateFile函數可以打開1個通訊端口。調用CreateFile打開通訊端口有兩種方式:堆疊的和非堆疊的。下面是使用堆疊方式打開1個通訊資源的例子:

[cpp] view plain copy
  1. HANDLE hComm;  
  2. hComm = CreateFile(gszPort,  
  3.         GENERIC_READ | GENERIC_WRITE,  
  4.         0,  
  5.         OPEN_EXISTING,  
  6.         FILE_FLAG_OVERLAPPED,  
  7.         0);  
  8. if (hComm == INVALID_HANDLE_VALUE)  
  9. // 打開毛病;使中斷。  
        移除CreateFile中的FILE_FLAG_OVERLAPPED標志可指定為非堆疊方式。下1章節將對堆疊和非堆疊方式進行討論。

         在Win32軟件開發工具包(SDK)程序員參考手冊(概述,窗口管理,系統服務)中規定,當打開1個通訊端口時候,調用CreateFile有以下要求: 

  • fdwShareMode必須為0。通訊端口不能像文件1樣被同享。利用程序使用TAPI可使用TAPI函數很容易實現兩個利用程序之間的資源同享。對Win32利用程序,不是使用TAPI。處理繼承或副本需要同享通訊端口。處理副本超越了本文的范圍,請查閱Win32SDK文檔獲得更多信息。
  • fdwCreate必須指定為OPEN_EXISTING標志。
  • hTemplateFile必須是NULL 

        需要注意1件事,慣例上它們有4個端口分別為:COM1、COM2、COM3COM4Win32 API沒有提供任何途徑去肯定系統中存在的端口。Windows NTWindows 95在配置串口方面相互其實不相同,所以任何1種方法都不能確保對所有的Win 32平臺都是可移植的。1些系統乃至有比慣例上的最大數量4個端口還要多的端口。硬件廠商和串行裝備驅動的作者可以用他們所喜歡的方式去自由命名端口。為此,如果用戶可以去指定他們想用的端口名是最好的選擇。如果1個端口不存在,在企圖打開這個端口的時候1個毛?。?span style="font-family:'Times New Roman'">ERROR_FILE_NOT_FOUND)將會出現,應當正告用戶這個端口是不可用的。

 

讀和寫

        從通訊端口讀和寫在Win32中極為類似于Win32中文件的輸入/輸出(I/O)。實際上,實現文件I/O的函數和用于串行I/O的函數是相同的。Win32中的I/O可以通過兩種方式被使用:堆疊和非堆疊。在Win32 SDK文檔中用異步和同步這樣的術語去暗示這些I/O操作的類型。但是,這篇文章中將用堆疊和非堆疊這樣的術語。 

        非堆疊I/O對大多數開發者來講是熟習的,由于這屬于傳統的I/O操作情勢,當函數返回的時候1個被要求的操作將被假定為已完成。就堆疊I/O來講,即便操作沒有完成系統也能夠立刻返回給調用者,當操作完成的時候將會用信號通知調用者。程序可以利用I/O要求和結束這段時間去履行1些“后臺”工作。 

        在Win32中和16位Windows中對串行通訊端口的讀和寫有顯著的不同。16位Windows只有ReadCommWriteComm函數。Win32中的讀寫操作可能牽涉更多的函數和選擇。這些問題在下文將會被討論。

 

非堆疊I/O

           非堆疊I/O非常簡單,雖然它還有1些限制。1個操作的履行將致使調用它的線程被阻塞。1旦該操作完成,函數返回,線程繼續工作。這類類型的I/O對多線程利用程序來講是非常有用的,由于當I/O操作的時候即便1個線程被阻塞,其它線程依然可以履行工作。利用程序有責任正確無誤的處理連續的端口操作。如果1個線程被阻塞去等待I/O操作的完成,隨后的其它線程如果調用1個通訊API也將可能被阻塞,直到最初的操作完成。例如,如果1個線程正在等待ReadFile函數返回,其它線程如果調用WriteFile函數將會被阻塞。 

        在非堆疊和堆疊操作之間做出選擇的諸多因素中,其中之1是要斟酌到可移植性。堆疊操作不是1個好的選擇,由于大多數操作系統其實不支持它。但是大多數操作系統支持多線程,所以多線程的非堆疊I/O操作從可移植性上面斟酌的話是最好的選擇。

堆疊I/O

         堆疊I/O不像非堆疊I/O那樣簡單的,但是提供了更多的靈活性和效力。當1個端口打開的時候,對堆疊操作來講,允許線程與此同時履行I/O操作和其它的工作,即便這個操作正處于不肯定狀態。另外,堆疊操作允許單線程發出許多不同的要求和履行后臺工作,即便這個操作處于不肯定狀態。 

         對單線程和多線程利用程序,在發出要求和得到結果之間必須產生1些同步性。1個線程將會被阻塞,直到1個操作的結果變成有效的。堆疊I/O的優勢所在是允許1個線程在要求和完成之間去做1些工作。如果沒有工作可以被做,然后對堆疊I/O只有1種可能,就是它將允許為更好的用戶提供響應。 

         堆疊I/OMTTTY例子中所使用的1種操作類型。它創建1個線程來負責讀取端口的數據和狀態。它也履行定期的后臺工作。程序創建另外1個線程專門用來從端口寫出數據。 

    注意:有時利用程序創建太多的線程,濫用多線程操作系統。雖然利用多線程可以解決很多困難的問題,但是創建過量的線程在利用程序中其實不是最有效的方式。在系統中線程沒有進程緊張,但是依然會占用系統資源,像CPU時間和內存。如果1個利用程序創建過量的線程,可能對全部系統的性能產生不利的影響。線程的1個更好的使用方式是對每一個工作類型創建1個不同的要求隊列,有1個工作者線程通過發出1個I/O要求使其進入要求隊列。上述方法將會被這篇文章中所提到的MTTTY這個例子用到。 

         1個堆疊I/O操作包括兩部份:創建操作和檢測是不是完成。創建操作必須建立1個OVERLAPPED結構體,為同步創建1個手工重置事件,然后在調用特定的函數(ReadFileWriteFile)。I/O操作可能也可能不會立即的完成。對1個程序來講,如果假定1個堆疊操作要求總是產生1個堆疊操作是毛病的。如果1個操作完成后,利用程序需要準備繼續正常地運行。堆疊操作的第2部份是檢測它是不是完成。檢測操作是不是完成包括等待事件處理,檢查堆疊結果和處理數據。有很多工作牽涉到堆疊操作的緣由是存在很多故障點。如果1個非堆疊操作失敗了,函數只是會返回1個毛病返回的結果。如果1個堆疊操作失敗了,它可能在創建操作時候失敗或是使操作處于等待狀態。你也可能有1個超時操作或只是1個超時去等待操作完成的信號。

         ReadFile函數將產生1個讀的操作。ReadFileEx也產生1個讀操作,但是由于它在Windows 95上是不可用的,所以在這篇文章中不對它做討論。這里的代碼段詳細說明了怎樣產生1個讀操作。注意,如果ReadFile函數返回TRUE,它的功能是將調用1個函數去處理數據。如果操作變成了堆疊方式,這個處理數據的函數也是1樣的。注意在代碼段中定義的fWaitingOnRead標記變量,用它來指明1個讀操作是不是為堆疊的。它通經常使用來避免在1個讀操作還沒有完成的時候又重新創建1個新的讀操作。

[cpp] view plain copy
  1. DWORD dwRead;  
  2. BOOL fWaitingOnRead = FALSE;  
  3. OVERLAPPED osReader = {0};  
  4.   
  5. // 創建堆疊事件。必須關閉之前存在的事件以免句柄泄漏。  
  6. osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  7.   
  8. if (osReader.hEvent == NULL)  
  9.     // 創建堆疊事件毛??;使中斷。  
  10.   
  11. if (!fWaitingOnRead) {  
  12.     // 履行讀操作  
  13.     if (!ReadFile(hComm, lpBuf, READ_BUF_SIZE, &dwRead, &osReader)) {  
  14.             // 讀操作是不是處于等待狀態?  
  15.             if (GetLastError() != ERROR_IO_PENDING)  
  16.                 // 通訊毛?。粓蟾嬖撁?。  
  17.             else  
  18.                 fWaitingOnRead = TRUE;  
  19.     }  
  20.     else {  
  21.         // 完成讀操作  
  22.         HandleASuccessfulRead(lpBuf, dwRead);  
  23.     }  
  24. }  

         堆疊操作的第2部份是檢測它是不是完成。OVERLAPPED結構體中的事件句柄會被傳遞到WaitForSingleObject函數中進行等待,直到對象被傳遞信號。1旦事件被傳遞信號,則代表操作完成了。這其實不意味著操作是被成功地完成,僅僅是完成而已。GetOverlappedResult函數將報告操作的結果。如果產生了毛病,GetOverlappedResult函數將返回FALSE,GetLastError函數將返回毛病代碼。如果操作被成功的完成,GetOverlappedResult將返回TRUE。 

         注意:GetOverlappedResult函數可以探測操作是不是完成,也能夠返回操作的失敗狀態。如果操作沒有完成,GetOverlappedResult將返回FALSE且GetLastError函數將返回ERROR_IO_INCOMPLETE。另外,GetOverlappedResult可能會被阻塞直到操作完成。實際上,堆疊操作轉變成非堆疊操作可以通過給GetOverlappedResult函數中的bWait參數傳遞TRUE來實現。 

         這里的代碼段展現了1種檢查1個堆疊讀操作是不是完成的方法。注意下面的代碼也調用的處理數據函數和上面是相同的,該函數在操作完成后立即調用。也要注意使用的fWaitingOnRead標記,在這里它用來控制是不是履行檢測代碼,由于它只有在1個讀操作還沒有完成時候才應當被調用。

[cpp] view plain copy
  1. #define READ_TIMEOUT 500    // 毫秒  
  2.   
  3. DWORD dwRes;  
  4.   
  5. if (fWaitingOnRead) {  
  6.   
  7.     dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);  
  8.   
  9.     switch(dwRes) {  
  10.         // 讀操作完成。  
  11.     case WAIT_OBJECT_0:  
  12.         if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))  
  13.             // 通訊毛??;報告該毛病。  
  14.         else  
  15.             // 讀操作成功地完成。  
  16.             HandleASuccessfulRead(lpBuf, dwRead);  
  17.           
  18.         // 重置標記變量,以便其它操作可以被履行。  
  19.         fWaitingOnRead = FALSE;  
  20.         break;  
  21.   
  22.     case WAIT_TIMEOUT:  
  23.         // 操作還沒有完成。fWaitingOnRead標記變量沒有改變,由于我將  
  24.         // 繼續返回循環,我不想在第1個讀操作沒完成績去履行另外1個。  
  25.         //  
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 91在线看看 | 欧产日产国产精品视频 | 久久久蜜臀 | 久久九九| 免费91麻豆精品国产自产在线观看 | 91亚洲国产视频 | 岛国毛片| 中文字幕av在线播放 | 国产成人精品久久 | 在线精品亚洲欧美日韩国产 | 欧美日韩国产综合网 | 亚洲激情欧美激情 | 久久久久在线观看 | 黄色短视频在线观看 | 国产福利电影在线观看 | 久久久久久成人 | 日韩欧美高清 | 亚洲第一视频网站 | 久久精品久久精品 | 国产日产亚洲精品 | 中文字幕av片 | 黄色国产在线 | 97在线免费视频 | 免费一二三区 | 欧美久久一区二区三区 | 51ⅴ精品国产91久久久久久 | 三级网站免费看 | 精品国产91乱码一区二区三区 | 麻豆乱码国产一区二区三区 | 波多野结衣av中文字幕 | 国产免费专区 | 国产一级片在线 | 国产成人在线播放 | 日韩av一区在线 | 国产剧情一区二区三区 | av影视网| 亚洲成人天堂 | 国产一区在线免费观看 | 又湿又紧又大又爽a视频国产 | 成网站人电影亚洲国产 | 国产欧美精品一区 |