亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        線程安全的.NET平臺串口通信程序設(shè)計研究

        2012-10-13 02:38:42
        關(guān)鍵詞:處理程序輔助線微控制器

        彭 偉

        (武漢城市職業(yè)學(xué)院電子信息工程學(xué)院,湖北武漢430064)

        RS-232串行端口通信技術(shù)大量應(yīng)用于工業(yè)控制系統(tǒng),Microsoft在其.NET Framework加入了串行端口類Serial Port,以支持 Windo ws軟件界面與外部設(shè)備之間的串口通信,實現(xiàn)數(shù)據(jù)采集及管理控制.然而,當.NET程序開發(fā)人員在串口組件數(shù)據(jù)接收事件處理程序中將讀取的數(shù)據(jù)直接顯示到可視化UI組件時,系統(tǒng)卻拋出線程異常,提示當前線程與可視化組件不在同一線程上運行.通過查閱MSDN技術(shù)手冊可知,.NET串口通信組件與可視化顯示組件雖然處于同一窗體,但串口數(shù)據(jù)接收事件卻是在輔助線程上引發(fā),它并非與窗體中其他可視化組件同處于主線程[1].

        本文將分析研究.NET Framewor k所提供的Serial Port、delegate、Thread及 Background Worker類相關(guān)技術(shù),研究解決.NET開發(fā)環(huán)境下串口通信程序中的線程安全問題,并與以PIC微控制器為核心的8通道A/D轉(zhuǎn)換模塊之間進行串口數(shù)據(jù)通信與圖文顯示測試.

        1 .NET串行端口類相關(guān)技術(shù)

        1.1 串行端口類簡介

        .NET的System.IO.Ports命名空間包含用于控制串行端口的類,最重要的類Serial Port為同步和事件驅(qū)動I/O提供框架,提供對串口針腳和中斷狀態(tài)的訪問以及對串行驅(qū)動程序?qū)傩缘脑L問.

        1.2 串行端口類數(shù)據(jù)接收事件處理

        ,由于其處理程序在輔助線程上引發(fā),故而在事件處理程序中無法直接訪問UI組件.為刷新窗體中相關(guān)組件的數(shù)據(jù)顯示,根據(jù) MSDN技術(shù)手冊可知,在Data Recived事件的輔助線程內(nèi)必須用Invoke激發(fā)委托來訪問UI組件,它將會在恰當?shù)木€程上執(zhí)行這些操作,實現(xiàn)線程安全調(diào)用.

        2 .NET的委托類型

        2.1 委托類型簡介

        .NET Fra mewor k定義了稱為委托(delegate)的特殊的類型,該類型提供函數(shù)指針的功能,是具有相同函數(shù)屬性(簽名)的抽象,是一種類型安全的方法引用,它可以看成是一個類型安全的C函數(shù)指針,但與C函數(shù)指針不同的是,.NET的委托是面向?qū)ο蠛皖愋桶踩?,通用語言運行時(CLR)會確保一個委托指向一個有效的方法[2-3].

        委托可用于封裝對“命名”或“匿名”方法的引用,使用委托有三個步驟,即:聲明、實例化和激發(fā).委托類型聲明的格式為:

        修飾符 關(guān)鍵字delegate返回類型 委托類型名稱(參數(shù)列表);

        委托類型構(gòu)造函數(shù)的參數(shù)必須是對方法(“命名”或“匿名”方法)或lambda表達式的引用.

        2.2 用數(shù)據(jù)接收事件與委托實現(xiàn)線程安全訪問

        基于Serial Port類數(shù)據(jù)接收事件處理程序,借助委托實現(xiàn)UI組件訪問,可有如下委托類型聲明:public delegate void ShowCall Back(string s);

        假設(shè)主線程中刷新顯示的命名方法為:private void Set Text(string s){

        /*訪問UI刷新組件顯示的代碼寫在這里*/}

        通過委托訪問Set Text,需要先實例化委托[4]:Show Call Back d= new Show Call Back(Set Text);

        當Data Received事件在輔助線程上引發(fā)以后,其事件處理程序通過委托實例d即可在輔助線程中訪問主線程中的Set Text方法.

        .NET并不保證對接收到的每個字節(jié)引發(fā)Data Received事件,在該事件發(fā)生時,可根據(jù)Bytes To-Read屬性確定緩沖區(qū)中尚未讀取的數(shù)據(jù)字節(jié)數(shù),通過循環(huán)讀取數(shù)據(jù)直到Bytes To Read返回0,如此即可讀取緩沖內(nèi)的所有數(shù)據(jù).

        對于所選擇的以PIC微控制器為核心的A/D轉(zhuǎn)換模塊所發(fā)送的8通道A/D值,本文約定通過串口讀取的數(shù)據(jù)為形如“xxx xxx xxx xxx xxx xxx xxx xxx\r\n”的字符串,它以“\r\n”為結(jié)束標識.Data Received事件處理程序通過串口讀取8通道A/D轉(zhuǎn)換數(shù)據(jù)時有:String s=serial Port1.Read-Line();調(diào)用Read Line時要注意設(shè)置串口組件的New Line屬性.讀取數(shù)據(jù)字符串s以后,即可同步或異步激發(fā)委托實例d訪問Set Text.以同步方法Invoke為例,有:

        this.Invoke(d,s);

        省略變量s的定義,可以寫成:

        this.Invoke(d,new object[]{serial Port1.Read Line()});

        更為簡潔的寫法是:

        this.Invoke(new Show Call Back(Set Text),new object[]{serial Port1.Read Line()});

        圖1所示的在輔助線程中通過委托訪問UI的示意圖描繪了上述委托定義及在輔助線程內(nèi)實例化委托,并通過Invoke/BeginInvoke激發(fā)對命名方法Set Text調(diào)用的整個過程.

        如果省略委托聲明,還可以使用預(yù)定義委托Event Handler調(diào)用主線程中的方法,參照圖1,有this.Invoke(new Event Handler(UIShow));其中UIShow可定義為

        private void UIShow(object sender,Event Args e){

        /*讀取串口數(shù)據(jù),訪問UI刷新數(shù)據(jù)顯示*/}

        圖1 在輔助線程中通過委托訪問UI組件

        如果要求輔助線程提供事件數(shù)據(jù)而不是在UIShow方法內(nèi)部讀取待顯示串口數(shù)據(jù),可選擇使用Event Handler<TEvent Ar gs>泛型委托.

        .NET還為UI組件提供了一個特殊的屬性:Contr ol.Invoke Required,它既可以在主線程也可以在輔助線程內(nèi)訪問,根據(jù)該屬性值可知調(diào)用方在對控件進行方法調(diào)用時是否必須使用Invoke方法,因為調(diào)用方可能位于創(chuàng)建控件所在的線程以外的線程中.借助這一屬性,可以按圖2所示流程設(shè)計主線程與輔助線程共用的訪問UI刷新顯示的方法.當輔助線程調(diào)用該方法時,代碼執(zhí)行形如“遞歸調(diào)用”,當然它與遞歸是毫無關(guān)系的.

        圖2 主/輔線程共用的UI訪問方法設(shè)計

        2.3 Invoke/BeginInvoke的工作原理

        Invoke與BeginInvoke方法都需要以委托對象作為參數(shù),委托類似于回調(diào)函數(shù)的地址,因此調(diào)用者通過Invoke或BeginInvoke方法可以把需要調(diào)用的函數(shù)地址封送給UI線程.使用同步方法Invoke完成一個委托方法的封送類似于使用Windows API的Send Message函數(shù)給界面線程發(fā)送消息,消息將進入消息隊列(Message Queue)并等待處理.作為一個異步方法,BeginInvoke則類似于使用Post-Message函數(shù)進行通信,封送完畢后將不等待委托方法執(zhí)行結(jié)束即返回,調(diào)用者線程不會被阻塞.不過調(diào)用者也可以使用EndInvoke方法或者其它類似Wait Handle的機制等待異步操作完成.

        通過Reflector.exe反編譯軟件可知,在內(nèi)部實現(xiàn)時,Invoke和BeginInvoke都使用了 Windows API的Post Message函數(shù),其中前者的同步阻塞通過Wait For Wait Handle方法完成.此外,它們還引用通過循環(huán)向上回溯查找頂級父控件的Find Marshaling Control方法;使消息進入消息隊列的Enqueue方法、定義一個新的視窗消息的API Register Window Message,以便通過 Send Message或Post Message發(fā)送(這里僅使用了后者);獲取與指定窗口關(guān)聯(lián)的進程和線程標識符的API Get Window Thread ProcessId及獲取當前線程唯一線程標識符的Get Current ThreadId.圖3描繪二者通過Windows的消息系統(tǒng)實現(xiàn)線程安全的UI訪問過程.

        圖3 通過消息系統(tǒng)實現(xiàn)線程安全的UI訪問

        3 .NET的Thread類

        3.1 Thread類簡介

        .NET的System.Threading命名空間提供進行多線程編程的類和接口,命名空間中的Thread類可創(chuàng)建并控制線程[6],線程執(zhí)行的代碼通過Thread Start委托或Parameterized Thread Start(帶參數(shù)的Thread Start)委托指定,使用后者可以向線程過程傳遞數(shù)據(jù).顯然,借助Thread類可以不使用串口組件的內(nèi)置Data Received事件,直接通過線程類與委托實現(xiàn)同樣的功能.

        3.2 用Thread類及委托實現(xiàn)線程安全訪問

        仍使用此前設(shè)計的顯示委托,下面給出Para meterized Thread Start委托及線程類Thread實現(xiàn)線程安全訪問的代碼.以串口數(shù)據(jù)接收與UI訪問刷新顯示為例,其中Recv Data方法將在form加載時調(diào)用,有:

        異步接收及顯示數(shù)據(jù)的命名方法如下:

        由于“匿名”方法也可以實例化委托,使用匿名方法時無須創(chuàng)建獨立的方法,可減少實例化委托所需的系統(tǒng)開銷.例如:

        對于函數(shù)Recv Data,可進一步作如下改寫:

        4 .NET的Background worker類

        4.1 Backgr ound worker類簡介

        System.Component Model命名空間提供用于實現(xiàn)組件和控件運行時及設(shè)計時行為的類,其中的Background Worker類用于在單獨的線程上執(zhí)行操作.圖4給出了該類的Do_Wor k事件處理流程.

        圖4 Background Worker類事件處理流程

        主線程通過Run worker Async引發(fā)Backgr ound worker對象在輔助線程上處理Do_Wor k事件以后,在輔助線程中,通過Report Progress方法可以將數(shù)據(jù)消息封送給主線程中的Progress-Changed事件處理程序;當完成所有事務(wù)處理時,也會將消息發(fā)給主線程,激發(fā)Run Worker completed事件處理程序.輔助線程上引發(fā)的Do_Wor k事件處理程序內(nèi)有兩條路徑可以實現(xiàn)對主線程中UI組件的安全訪問.

        4.2 使用Background worker實現(xiàn)線程安全訪問

        仍以串口數(shù)據(jù)接收及主窗體UI訪問為例,主窗體加載時,首先啟動后臺工作者:

        Run worker Async使后臺工作者開啟輔助線程執(zhí)行Do_Work,系統(tǒng)退出時注意在formClosing事件中停止backgr ound worker1對象的后臺工作:

        當后臺工作者對象發(fā)生“進度變化”事件時,由事件處理流程圖可知事件處理程序?qū)⒃谥骶€程上執(zhí)行,故而可以直接訪問UI組件:

        要持續(xù)讀取串口數(shù)據(jù)并直接訪問UI,輔助線程需不斷通過報告進度方法(Report Progress)觸發(fā)“進度變化”事件.下面的代碼中,輔助線程上執(zhí)行的

        Do_Wor k事件處理程序?qū)⒚扛?0 ms執(zhí)行一次“進度報告”:

        5 PIC微控制器A/D轉(zhuǎn)換及串口通信設(shè)計

        5.1 8通道A/D轉(zhuǎn)換及串口數(shù)據(jù)傳輸電路

        為測試C#程序?qū)Υ跀?shù)據(jù)的接收及顯示效果,圖5給出了所選擇的以PIC18F452微控制器為核心的通信測試模塊,其中8個10位精度的A/D轉(zhuǎn)換通道(AN0~AN7)分別連接了不同類型的模擬信號,圖中同時給出了虛擬仿真串口組件(COMPI M)及物理串口(MAX232)[5-6].

        基于HI-TECH PICC18編譯器設(shè)計的C程序?qū)⒀h(huán)執(zhí)行8通道A/D轉(zhuǎn)換,并將結(jié)果轉(zhuǎn)換為約定的字符串格式,通過串口發(fā)送給上位主機程序接收并刷新圖文顯示.

        圖5 8通道A/D轉(zhuǎn)換及串口數(shù)據(jù)傳輸電路

        5.2 PIC微控制器串口配置及數(shù)據(jù)傳輸設(shè)計

        HI-TECH PICC18提供了 USART專用庫函數(shù),例如:Open USART用于按指定配置(例如波特率設(shè)置等)打開指定串口;puts USART與gets USART分別用于發(fā)送與接收字符串.假設(shè)上位機控制PIC微控制器A/D啟停的語句為:

        PIC微控制器可使用相應(yīng)函數(shù)讀取主機C#程序發(fā)送的控制命令,選擇其當前工作狀態(tài);對于已轉(zhuǎn)換后的當前8通道A/D數(shù)據(jù),則可通過相應(yīng)函數(shù)向上位主機發(fā)送[7-8].

        5.3 A/D通道數(shù)據(jù)采集函數(shù)設(shè)計

        函數(shù)ADC_Convert()將對PIC18F452的AN0~AN7通道分別進行 A/D轉(zhuǎn)換.由于 HI-TECH PICC18提供了A/D轉(zhuǎn)換專用庫函數(shù),ADC_Convert()的具體實現(xiàn)將大為簡化:

        執(zhí)行PIC微控制器8通道A/D轉(zhuǎn)換的函數(shù):

        由于PIC18F452的A/D模塊為10位精度,最大值為0B0000001111111111(即0x03FF),故保存一個通道的轉(zhuǎn)換結(jié)果最多只需要3位十六進制數(shù)(即xxx).PIC微控制器主程序?qū)⒀h(huán)執(zhí)行A/D轉(zhuǎn)換,并將ADC_Buff中的8組數(shù)據(jù)轉(zhuǎn)換為形如:“xxx xxx xxx xxx xxx xxx xxxx xxx\r\n”的字符串,再通過puts USART庫函數(shù)輸出.

        6 主機接收及圖文刷新顯示程序設(shè)計

        實現(xiàn)線程安全的串口數(shù)據(jù)接收及UI訪問可以有多種方法,以下選擇通過Data Received事件及委托實現(xiàn).下面的C#程序?qū)⒃赨I組件中實現(xiàn)8通道轉(zhuǎn)換結(jié)果對應(yīng)的電壓值的圖文顯示:

        輔助線程上執(zhí)行的串口組件數(shù)據(jù)接收事件Data Received的處理程序內(nèi)簡化編寫的唯一語句為:this.Invoke(new Show Call Back (Show_ADC),new object[]{serial Port1.Read Line()});8通道模擬電壓數(shù)據(jù)在基于C#.NET設(shè)計的上位機UI中的圖文刷新顯示效果見圖6.

        圖6 C#程序接收并刷新8通道數(shù)據(jù)顯示

        7 結(jié)束語

        通過對 Serial Port及 delegate、Thread、Background worker類相關(guān)技術(shù)的研究,給出了.NET開發(fā)環(huán)境下線程安全的串口通信程序,并通過了與PIC18F452微控制器8通道A/D轉(zhuǎn)換及串口通信模塊的數(shù)據(jù)傳輸與圖文刷新顯示測試,驗證了本文提出的程序設(shè)計方法的正確性與可靠性,為.NET平臺的串口通信管理控制與數(shù)據(jù)傳輸程序設(shè)計提供了參考.

        [1]Microsoft Cor poration.Serial Port類[EB/OL].[2012-01-03]http://msdn.microsoft.co m/zh-cn/library.

        [2]蔡昭權(quán).C#和C++數(shù)據(jù)傳遞的研究與實現(xiàn)[J].計算機應(yīng)用與軟件,2009(3):145-147.

        [3]曹 文.C#程序設(shè)計語言中的委托和事件 [J].現(xiàn)代計算機,2008(2):72-75,81.

        [4]韓志強.對C#委托內(nèi)部機制的探析 [J].赤峰學(xué)院學(xué)報(自然科學(xué)版),2010(10):37-38.

        [5]謝振華.PLC與上位機串口通訊的實現(xiàn)及應(yīng)用 [J].儀器儀表用戶,2011(6):59-61.

        [6]楊旭東,蔡敬坤,李 娟.一種通用串口線程在C++Builder中的實現(xiàn) [J].計算機測量與控制,2011(7):1 687-1 689.

        [7]徐蕾璐,俞子榮.C#.NET環(huán)境下基于Serial Port實現(xiàn)SR23與PC機的通信 [J].計算機與現(xiàn)代化,2011(5):107-108.

        [8]熊才高.基于PIC單片機低功耗數(shù)據(jù)采集系統(tǒng)的設(shè)計[J].湖北工業(yè)大學(xué)學(xué)報,2008(2):20-22.

        猜你喜歡
        處理程序輔助線微控制器
        怎樣添輔助線證全等
        高速公路工程變更與計量支付處理程序的優(yōu)化方法
        兩種重要的輔助線
        淺談輔助線在數(shù)控切割中的應(yīng)用
        物聯(lián)網(wǎng)技術(shù)在微控制器實驗教學(xué)中的應(yīng)用
        電子制作(2017年14期)2017-12-18 07:07:58
        基于C++的數(shù)控加工通用后處理程序的開發(fā)應(yīng)用研究
        企業(yè)危機公關(guān)管理問題分析
        Atmel針對新一代物聯(lián)網(wǎng)應(yīng)用發(fā)布全新32位微控制器
        最新STM32設(shè)計工具增加對混合信號微控制器的支持
        Have Fun with Math
        久久中文字幕av一区二区不卡 | 亚洲国产精品一区二区成人片国内| 私人毛片免费高清影视院| 亚洲福利视频一区| 激情亚洲综合熟女婷婷| 亚洲美女毛多水多免费视频| 国产熟妇另类久久久久| 日韩毛片在线| 女同国产日韩精品在线| 少妇激情一区二区三区99| 亚洲日韩国产精品乱-久 | 国产精品一区二区午夜久久| 人妻夜夜爽天天爽三区麻豆av| 无码人妻少妇久久中文字幕蜜桃| 大地资源网最新在线播放| 亚洲中文字幕有码av| 精品少妇一区二区三区免费| 美女把尿囗扒开让男人添| www插插插无码视频网站| 少妇一级内射精品免费| 亚洲图片自拍偷图区| 波多野结衣中文字幕久久| 亚洲综合国产成人丁香五月小说| av成人一区二区三区| 国产中文字幕乱人伦在线观看| 人妻少妇不满足中文字幕| 国内精品女同一区二区三区| 人人妻人人澡人人爽人人dvd| 国产乱妇乱子视频在播放| 色偷偷亚洲第一综合网| 亚洲av熟女一区二区三区站| 亚洲毛片αv无线播放一区| 思思99热| 91精品人妻一区二区三区水蜜桃 | 国产欧美日韩久久久久| 国产成人精品免费视频大全| 精品中文字幕在线不卡| 亚洲人成电影在线播放| 手机看片国产日韩| 白白色视频这里只有精品| 狠狠精品久久久无码中文字幕|