版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第3章串口網(wǎng)絡(luò)編程3.1串行通信概述3.2串口通信程序設(shè)計(jì)3.3串口通信程序設(shè)計(jì)小結(jié)
串口通信是一種通信條件要求最低卻十分重要的網(wǎng)絡(luò)通信模式,網(wǎng)絡(luò)設(shè)備調(diào)試、極端條件下的網(wǎng)絡(luò)通信都可以通過串口來實(shí)現(xiàn),特別是對一些便攜式、小型設(shè)備,串口通信可能是它們的唯一通信手段。串口通信處于OSI模型的數(shù)據(jù)鏈路層,通信協(xié)議簡單、編程接口函數(shù)數(shù)量較少,適合作為進(jìn)行網(wǎng)絡(luò)編程技術(shù)的入門學(xué)習(xí)內(nèi)容。
本章由串口通信的基本原理、接口入手,介紹串口通信的API函數(shù);并以主機(jī)與單片機(jī)、主機(jī)間的通信為實(shí)例,介紹串口網(wǎng)絡(luò)編程的方法。
串行總線是一種目前經(jīng)常使用的通信方式,單片機(jī)、PLC、測試儀器、PC、打印機(jī)、交換機(jī)、路由器、防火墻、工業(yè)控制設(shè)備都帶有串口總線。串行接口包括RS-232/422/485,其技術(shù)簡單成熟,性能可靠,所要求的軟硬件環(huán)境和條件都很低,是一種最簡單的建立網(wǎng)絡(luò)連接的方式。3.1串行通信概述3.1.1串行通信的模式
通過單線傳輸信息是串行數(shù)據(jù)通信的基礎(chǔ),數(shù)據(jù)通常是在兩個(gè)站(點(diǎn)對點(diǎn))之間進(jìn)行傳輸?shù)?。按照?shù)據(jù)流的方向,串行通信可分成三種傳輸模式:單工、半雙工、全雙工。
1.單工模式
單工模式的數(shù)據(jù)傳輸是單向的。通信雙方中,一方固定為發(fā)送端,另一方則固定為接收端。信息只能沿一個(gè)方向傳輸,使用一根傳輸線。單工模式一般用在只向一個(gè)方向傳輸數(shù)據(jù)的場合。例如計(jì)算機(jī)與打印機(jī)之間的通信是單工模式,因?yàn)橹挥杏?jì)算機(jī)向打印機(jī)傳輸數(shù)據(jù),而沒有相反方向的數(shù)據(jù)傳輸。在某些通信信道中,存在單工無線發(fā)送等單工模式。
2.半雙工模式
半雙工通信中使用同一根傳輸線,既可發(fā)送數(shù)據(jù)又可接收數(shù)據(jù),但不能同時(shí)進(jìn)行發(fā)送和接收。在任何時(shí)刻,只能由其中的一方發(fā)送數(shù)據(jù),另一方接收數(shù)據(jù)。因此半雙工模式既可以使用一條數(shù)據(jù)線,也可以使用兩條數(shù)據(jù)線。在半雙工通信中,每一端需裝有一個(gè)收發(fā)切換電子開關(guān),通過切換來決定數(shù)據(jù)向哪個(gè)方向傳輸。因?yàn)橛星袚Q,所以會(huì)產(chǎn)生時(shí)間延遲,信息傳輸效率也較低。
3.全雙工模式
全雙工數(shù)據(jù)通信分別由兩根可以在兩個(gè)不同的站點(diǎn)同時(shí)發(fā)送和接收的傳輸線進(jìn)行傳輸,通信雙方都能在同一時(shí)刻進(jìn)行發(fā)送和接收操作。在全雙工模式中,每一端都有發(fā)送器和接收器,有兩條傳輸線,可在交互式應(yīng)用和遠(yuǎn)程監(jiān)控系統(tǒng)中使用,信息傳輸效率較高。3.1.2串口的基本參數(shù)與標(biāo)準(zhǔn)
目前,常用的串口標(biāo)準(zhǔn)有RS-232C、RS-422、RS-485標(biāo)準(zhǔn)。
1.RS-232C
RS-232C是美國電子工業(yè)協(xié)會(huì)(ElectronicIndustryAssociation,EIA)于1962年公布并于1969年修訂的串行接口標(biāo)準(zhǔn),它已經(jīng)成為了國際上通用的標(biāo)準(zhǔn)。1987年1月,RS-232C經(jīng)修改后,正式改名為EIA-232D。由于標(biāo)準(zhǔn)修改內(nèi)容并不多,因此現(xiàn)在很多廠商仍使用舊的。RS-232C標(biāo)準(zhǔn)(協(xié)議)的全稱是EIA-RS-232C標(biāo)準(zhǔn),其中RS(RecommendedStandard)代表推薦標(biāo)準(zhǔn),232是標(biāo)識號,C代表RS-232的最新一次修改,它適合于數(shù)據(jù)傳輸速度在0~20
kb/s范圍內(nèi)的通信。這個(gè)標(biāo)準(zhǔn)對串行通信接口的有關(guān)問題,如信號電平、信號線功能、電氣特性、機(jī)械特性等都作了明確的規(guī)定。目前RS-232C已成為數(shù)據(jù)終端設(shè)備(DTE,如計(jì)算機(jī))和數(shù)據(jù)通信設(shè)備(DCE,如Modem)的接口標(biāo)準(zhǔn)。RS-232C是PC與通信工業(yè)中應(yīng)用最廣泛的一種串行接口,PC上的COM1和COM2大多是RS-232C接口。
利用RS-232C串行通信接口可實(shí)現(xiàn)兩臺個(gè)人計(jì)算機(jī)之間點(diǎn)對點(diǎn)的通信;通過RS-232C接口可與其他外設(shè)(如打印機(jī)、邏輯分析儀、智能調(diào)節(jié)儀、PLC等)近距離串行連接通過RS-232C接口連接調(diào)制解調(diào)器(Modem)可遠(yuǎn)距離地與其他計(jì)算機(jī)通信;將RS-232C接口轉(zhuǎn)換為RS-422或RS-485接口,可實(shí)現(xiàn)一臺個(gè)人計(jì)算機(jī)與多臺現(xiàn)場設(shè)備之間的通信。
RS-232的每一引腳都有它的作用,也有其信號流動(dòng)的方向,各引腳的信號功能描述見表3-1。原來的RS-232是用來連接調(diào)制解調(diào)器作為傳輸用的,因此它的引腳位意義通常也和調(diào)制解調(diào)器傳輸有關(guān)。從功能來看,全部信號線分為三類,即數(shù)據(jù)線(TXD、RXD)、地線(GND)和聯(lián)絡(luò)控制線(DSR、DTR、RI、DCD、RTS、CTS)。表3-1RS-232各引腳的信號功能只有當(dāng)DSR和DTR都處于有效(ON)狀態(tài)時(shí),才能在DTE和DCE之間進(jìn)行傳輸操作。若DTE要發(fā)送數(shù)據(jù),則預(yù)先將DTR線置成有效(ON)狀態(tài),等CTS線上收到有效(ON)狀態(tài)的回答后,才能在TXD線上發(fā)送串行數(shù)據(jù)。這種順序的規(guī)定對半雙工的通信線路特別有用,因?yàn)榘腚p工的通信確定DCE已由接收端向改為發(fā)送端向,這時(shí)線路才能開始發(fā)送。從計(jì)算機(jī)的角度來看這些引腳的通信狀況,流進(jìn)計(jì)算機(jī)端的,可以看做數(shù)字輸入;而流出計(jì)算機(jī)端的,則可以看做數(shù)字輸出。從工業(yè)應(yīng)用的角度來看,所謂的輸入就是用來“監(jiān)測”的,而輸出就是用來“控制”的。
2.RS-422
RS-422由RS-232發(fā)展而來,是為了彌補(bǔ)RS-232的不足而提出的。為了改進(jìn)RS-232抗干擾能力差、通信距離短、傳輸速度低等缺點(diǎn),RS-422定義了一種平衡通信接口,將傳輸速度提高到10
Mb/s,速率低于100
kb/s時(shí)的傳輸距離延長到4000英尺(1英尺=0.3048
m),并允許在一條平衡總線上連接最多10個(gè)接收器。RS-422是一種單機(jī)發(fā)送、多機(jī)接收的單向、平衡傳輸規(guī)范。
3.RS-485
為擴(kuò)展應(yīng)用范圍,EIA又于1983年在RS-422基礎(chǔ)上制定了RS-485標(biāo)準(zhǔn),增加了多點(diǎn)、雙向通信能力,即允許多個(gè)發(fā)送器連接到同一條總線上,同時(shí)增加了發(fā)送器的驅(qū)動(dòng)能力和沖突保護(hù)特性,擴(kuò)展了總線共模范圍。RS-485協(xié)議可以看做是RS-232協(xié)議的替代標(biāo)準(zhǔn),與傳統(tǒng)的RS-232協(xié)議相比,其在通信速率、傳輸距離、多機(jī)連接等方面均有了非常大的提高。由于RS-485總線是RS-232總線的改良標(biāo)準(zhǔn),因此在軟件設(shè)計(jì)上它與RS-232總線基本上一致。當(dāng)兩臺RS-232串口設(shè)備通信距離較近時(shí)(小于15
m),可以用電纜線直接將兩臺設(shè)備的RS-232端口連接;若通信距離較遠(yuǎn)時(shí)(大于15
m),則需要附加Modem。當(dāng)PC與串口設(shè)備的通信距離較遠(yuǎn)或PC與多臺具有RS-232接口的設(shè)備通信時(shí),也可以采用RS-485總線。3.1.3串行通信握手協(xié)議
串行通信需要使用握手協(xié)議保持?jǐn)?shù)據(jù)收發(fā)雙方的同步,握手協(xié)議靠握手信號實(shí)現(xiàn)。握手信號實(shí)際上就是控制信號,用來控制數(shù)據(jù)的傳輸。通過握手信號,發(fā)送端可以得知接收端是否有數(shù)據(jù)要發(fā)送。接收端通過握手信號通知發(fā)送端它是否已經(jīng)準(zhǔn)備好了接收信號。握手信號遵循某種協(xié)議。當(dāng)發(fā)送端和接收端處理數(shù)據(jù)的速度不一樣時(shí),可能會(huì)造成數(shù)據(jù)丟失。在數(shù)據(jù)傳輸中,如果發(fā)送端的發(fā)送速度大于接收端的接收速度,同時(shí)接收端處理數(shù)據(jù)的速度不夠快,那么接收端的緩沖區(qū)必定在一定時(shí)間后溢出,從而造成以后發(fā)送過來的數(shù)據(jù)不能進(jìn)入緩沖區(qū)而丟失。發(fā)送端何時(shí)可以繼續(xù)發(fā)送數(shù)據(jù),何時(shí)必須暫停發(fā)送,從而讓接收端有時(shí)間處理數(shù)據(jù),則必須靠握手信號來解決這個(gè)問題。例如,打印機(jī)和計(jì)算機(jī)進(jìn)行通信時(shí),一些打印機(jī)的打印速度可能跟不上計(jì)算機(jī)發(fā)送數(shù)據(jù)的速度,就必須通過握手信號通知計(jì)算機(jī)暫停發(fā)送數(shù)據(jù)。通常,串行通信握手的協(xié)議可以是硬件握手、軟件握手或二者的結(jié)合,具體如下所述。
1.硬件握手
在硬件握手中,發(fā)送端通過將某一條導(dǎo)線拉到高電平或者低電平,以表示發(fā)送端可以發(fā)送數(shù)據(jù)。接收端已經(jīng)準(zhǔn)備好接收數(shù)據(jù)之后,也把某一個(gè)導(dǎo)線拉到高電平或者是低電平,以通知發(fā)送端,發(fā)送端一直在檢測這個(gè)信號。接收端可以在任何時(shí)候把這個(gè)信號變?yōu)闊o效,甚至是在接收一個(gè)數(shù)據(jù)塊的過程中。當(dāng)發(fā)送端檢測到這個(gè)信號變?yōu)闊o效之后,就必須停止本次發(fā)送,直到這個(gè)信號變?yōu)橛行橹埂?/p>
2.軟件握手
在軟件握手中,以數(shù)據(jù)線上特定的數(shù)據(jù)信號來代替實(shí)際的硬件電路電平變化。這種方法用在直接連接或者通過調(diào)制解調(diào)器連接的兩臺計(jì)算機(jī)之間進(jìn)行雙向通信的場合。
對于軟件握手,現(xiàn)在已經(jīng)建立了一些標(biāo)準(zhǔn)協(xié)議,其中最常用的是通信協(xié)議。通信協(xié)議是指通信雙方的一種約定,包括對數(shù)據(jù)格式、同步方式、傳輸速度、傳輸步驟、檢/糾錯(cuò)方式以及控制字符定義等問題進(jìn)行統(tǒng)一規(guī)定,通信雙方必須共同遵守,也叫做通信控制規(guī)程或傳輸控制規(guī)程,它屬于OSI七層參考模型中的數(shù)據(jù)鏈路層。
3.軟硬結(jié)合握手
在使用個(gè)人計(jì)算機(jī)或終端設(shè)備通過調(diào)制解調(diào)器和主計(jì)算機(jī)進(jìn)行通信時(shí)(例如:對路由器進(jìn)行基于串口的遠(yuǎn)程配置的情況),一般會(huì)采用軟硬結(jié)合的握手。這種握手同時(shí)采用了硬件握手和軟件握手:一方面,個(gè)人計(jì)算機(jī)與調(diào)制解調(diào)器、主計(jì)算機(jī)與調(diào)制解調(diào)器之間,使用硬件握手方法進(jìn)行聯(lián)系;另一方面,主計(jì)算機(jī)和個(gè)人計(jì)算機(jī)之間將使用軟件握手方法進(jìn)行聯(lián)系。因此,個(gè)人計(jì)算機(jī)向主計(jì)算機(jī)傳輸數(shù)據(jù)時(shí),同時(shí)要考慮硬件和軟件握手。例如:在個(gè)人計(jì)算機(jī)通過調(diào)制解調(diào)器向主計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí),只有在調(diào)制解調(diào)器DSR(有時(shí)可能使用CD)線電位變高,且沒有收到來自主計(jì)算機(jī)的“停止傳輸”軟件信號時(shí),才送出數(shù)據(jù)。
一些計(jì)算機(jī)會(huì)自動(dòng)監(jiān)測硬件握手信號,所以應(yīng)用程序只需要處理軟件握手信號即可。但這種情況并不等于硬件握手不存在,依然是軟硬結(jié)合的握手。
現(xiàn)在的產(chǎn)品若要自動(dòng)化,一定要提供一個(gè)能與計(jì)算機(jī)進(jìn)行通信的通道。最簡單的方式就是在產(chǎn)品內(nèi)部燒上一顆單芯片,利用單芯片上的串行通信功能進(jìn)行自動(dòng)化的工作,由于計(jì)算機(jī)中的串口是必備的通道,且從價(jià)格及技術(shù)上來說是最能被廠商所接受的,因此,市面上很多自動(dòng)化產(chǎn)品也就加上了串行通信的功能,從而擴(kuò)大了產(chǎn)品的使用領(lǐng)域,使產(chǎn)品自動(dòng)化的實(shí)現(xiàn)技術(shù)變得簡單化。3.2串口通信程序設(shè)計(jì)3.2.1串行通信軟件工具
除了用戶自己動(dòng)手編寫串口通信軟件之外,目前也有一些現(xiàn)成的串口通信軟件工具。
1.超級終端程序
超級終端程序是Windows操作系統(tǒng)自帶的串口通信軟件,用戶可以選擇“開始/程序/附件/通信/超級終端”命令來調(diào)用它。使用超級終端程序需要對其進(jìn)行設(shè)置,設(shè)置步驟如下:
(1)首先按照“開始/程序/附件/通信”順序,執(zhí)行“超級終端”操作(對應(yīng)系統(tǒng)目錄“C:\ProgramFiles\WindowsNT”下的hypertrm.exe應(yīng)用程序),會(huì)出現(xiàn)一個(gè)本次聯(lián)機(jī)的名稱設(shè)置窗口(第一次使用該應(yīng)用程序時(shí),可能還會(huì)被要求設(shè)置國家、區(qū)號等屬性參數(shù)),在其中輸入名稱并選擇一個(gè)代表圖標(biāo)。此名稱通常應(yīng)使用易記的名稱來命名,以后再進(jìn)行聯(lián)機(jī)操作時(shí),只要加載該名稱,一切其它的設(shè)置就會(huì)恢復(fù)。
(2)然后在出現(xiàn)的界面中選擇所要連接的設(shè)備??梢愿鶕?jù)需要連接相應(yīng)的設(shè)備,可選得選項(xiàng)包括:COM、TCP/IP等,在這里選擇COM。
(3)在彈出的窗口中設(shè)置相關(guān)的參數(shù),如圖3-1所示。圖3-1超級終端參數(shù)設(shè)置
(4)單擊“確定”按鈕后,就會(huì)出現(xiàn)一個(gè)工作窗口,這說明已經(jīng)連接到需要連接的設(shè)備上。
設(shè)置完成后,會(huì)出現(xiàn)連接提示,包括連接時(shí)間、終端類型、連接參數(shù)等。如果串口不存在,或已被其他設(shè)備使用,超級終端就無法打開該端口,會(huì)顯示錯(cuò)誤提示。
用超級終端和其他的設(shè)備進(jìn)行連接時(shí),雙方互傳的數(shù)據(jù)以文字?jǐn)?shù)據(jù)為主,在正式用程序?qū)⒂?jì)算機(jī)和設(shè)備聯(lián)機(jī)之前,最好使用類似超級終端之類的程序先行做一些基本的測試,以確定使用字符串的通信沒有問題,然后再進(jìn)行控制。
2.窗口精靈軟件
窗口精靈軟件是一個(gè)極好的串口監(jiān)視與調(diào)試程序,適用于Win9X/NT平臺,能提高開發(fā)效率。它可以在線設(shè)置各種通信速度、奇偶校驗(yàn)、通信口而無需重新啟動(dòng)程序;可以設(shè)置定時(shí)發(fā)送的數(shù)據(jù)以及時(shí)間間隔;可以自動(dòng)顯示接收到的數(shù)據(jù),并能在字符串、十進(jìn)制和十六進(jìn)制之間自由切換;還能自動(dòng)保存設(shè)置參數(shù)。窗口精靈軟件是工程技術(shù)人員監(jiān)視、調(diào)試串口程序的必備工具。
3.串口調(diào)試助手
串口調(diào)試助手是在實(shí)際工程應(yīng)用中,根據(jù)實(shí)際的、普遍的需求而開發(fā)的串口調(diào)試工具,其界面精致美觀、實(shí)用性強(qiáng),支持各種串口設(shè)置,如波特率、校驗(yàn)位、數(shù)據(jù)位和停止位等。支持ASCII/Hex發(fā)送,發(fā)送和接收的數(shù)據(jù)可以在十六進(jìn)制和ASCII碼之間任意轉(zhuǎn)換??梢宰詣?dòng)在發(fā)送的數(shù)據(jù)末尾增加校驗(yàn)位,支持多種校驗(yàn)格式。支持間隔發(fā)送、循環(huán)發(fā)送和批處理發(fā)送,輸入的數(shù)據(jù)可以從外部文件導(dǎo)入,并且能夠自動(dòng)將接收到的數(shù)據(jù)保存到磁盤文件。
4.串口監(jiān)控器
串口監(jiān)控器是一個(gè)免費(fèi)的多功能串口通信監(jiān)控軟件,它能夠以多種方式顯示、接收、分析通信數(shù)據(jù);能夠以多種靈活方式發(fā)送數(shù)據(jù);具有方便的數(shù)據(jù)編輯功能。串口監(jiān)控器的特點(diǎn)是功能強(qiáng)大,操作簡單,在串口通信監(jiān)控、設(shè)備通信測試中,能夠很好地提高工作效率。它的主要功能如下:
(1)接收數(shù)據(jù);
(2)以十六進(jìn)制方式顯示接收到的數(shù)據(jù);
(3)以字符方式顯示接收到的數(shù)據(jù);
(4)數(shù)據(jù)幀自動(dòng)識別,分行顯示。
5.串口文件自動(dòng)發(fā)送/接收系統(tǒng)
當(dāng)要求隔離的兩個(gè)網(wǎng)絡(luò)之間需要經(jīng)常性地傳輸一些文件時(shí),若使用優(yōu)盤拷貝則費(fèi)時(shí)、費(fèi)力,使用網(wǎng)閘則動(dòng)輒花費(fèi)數(shù)萬至數(shù)十萬元,而此時(shí)使用“串口文件自動(dòng)發(fā)送/接收系統(tǒng)”不失為一種很好的解決方案。串口文件自動(dòng)發(fā)送/接收系統(tǒng)使用的是Zmodem文件傳輸協(xié)議,雖然速度不快,但不使用任何網(wǎng)絡(luò)協(xié)議。串口文件自動(dòng)發(fā)送/接收系統(tǒng)由發(fā)送端和接收端兩部分組成:發(fā)送端可設(shè)置需要傳輸?shù)奈募A和文件類型,支持定時(shí)檢測,當(dāng)發(fā)現(xiàn)新增文件或當(dāng)文件長度、創(chuàng)建時(shí)間發(fā)生變化時(shí),都會(huì)自動(dòng)地通過串口發(fā)送到接收端;接收端處在自動(dòng)接收狀態(tài),當(dāng)收到文件后會(huì)自動(dòng)將其保存到指定的文件夾中。
上述軟件在基于串口通信的工程實(shí)踐中發(fā)揮了巨大效益,使用范圍非常廣泛。下面我們將從串口操作函數(shù)入手,講解如何設(shè)計(jì)實(shí)現(xiàn)自己的串口通信程序。3.2.2串口操作API函數(shù)
在32位的Windows系統(tǒng)中,串口和其他通信設(shè)備都是作為文件進(jìn)行處理的。串口的打開、關(guān)閉、讀取和寫入所用的函數(shù)與操作文件的函數(shù)完全一樣。
1.打開串口
在通信過程中,程序是通過CreateFile()函數(shù)打開串口來進(jìn)行讀、寫或讀/寫訪問的。CreateFile()調(diào)用成功后返回一個(gè)句柄,這個(gè)句柄將會(huì)在后續(xù)操作中使用,可以打開已經(jīng)存在的文件、創(chuàng)建新文件和打開系統(tǒng)設(shè)備(例如:串口設(shè)備、并口設(shè)備和調(diào)制解調(diào)器等。注意:這些設(shè)備需正確安裝驅(qū)動(dòng),獲得系統(tǒng)合法I/O資源),它的原型如下:
HANDLECreateFile(
LPCTSTRlpFileName, //指向文件名的指針
DWORDdwDesiredAccess, //訪問模式(寫/讀)
DWORDdwShareMode, //共享模式
LPSECURITY_ATTRIBUTESlpSecurityAttributes,//指向安全屬性的指針
DWORDdwCreationDisposition,//如何創(chuàng)建
DWORDdwFlagsAndAttributes,//文件屬性
HANDLEhTemplateFile); //用于復(fù)制文件句柄函數(shù)調(diào)用成功后,返回一個(gè)HANDLE句柄,可以在串口后續(xù)操作中對其進(jìn)行調(diào)用,該句柄指向所開辟串口。
2.關(guān)閉串口
調(diào)用CloseHandle()函數(shù)即可關(guān)閉由CreateFile()函數(shù)返回的句柄。使用串口后一般要關(guān)閉串口,如果忘記關(guān)閉串口,串口就會(huì)始終處于打開狀態(tài),其他應(yīng)用程序就不能打開并使用串口了,其原型如下:
BOOLCloseHandle(HANDLEhObject); //指向需關(guān)閉的文件句柄
3.讀串口操作
程序可以使用Win32API的ReadFile()函數(shù)或者ReadFileEx()函數(shù)從串口中讀取數(shù)據(jù)。Readfile()函數(shù)對同步或異步操作都支持,而ReadFileEx()函數(shù)只支持異步操作。這兩個(gè)函數(shù)不受函數(shù)是否異步操作、超時(shí)操作等有關(guān)參數(shù)的影響和限制。利用Win32API讀/寫串口時(shí),既可同步執(zhí)行,也可以異步執(zhí)行。同步執(zhí)行時(shí),函數(shù)直到操作完成后才返回,這意味著在同步執(zhí)行時(shí)線程會(huì)被阻塞,從而導(dǎo)致效率變低。異步執(zhí)行時(shí),即使操作還未完成,調(diào)用的函數(shù)也會(huì)立即返回并交出控制權(quán),把費(fèi)時(shí)的I/O操作安排在后臺進(jìn)行,這樣就可以提高工作效率。ReadFile()的原型如下(ReadFilEx()與之非常類似):
BOOLReadFile( HANDLEhFile,//文件的句柄
LPVOIDlpBuffer, //用于保存讀入數(shù)據(jù)的一個(gè)緩沖區(qū)
DWORDnNumberOfBytesToRead, //要讀入的字符數(shù)
LPDWORDlpNumberOfBytesRead, //指向?qū)嶋H讀取字節(jié)數(shù)的指針
LPOVERLAPPEDlpOverlapped); //異步讀取操作數(shù)據(jù)結(jié)構(gòu)體指針
Windows9X/NT/2000中讀/寫串口時(shí)引入了超時(shí)結(jié)構(gòu)。超時(shí)結(jié)構(gòu)直接影響讀/寫操作行為。當(dāng)事先設(shè)定的超時(shí)間隔消失時(shí),ReadFile()、ReadFileEx()、WriteFile()和WriteFileEx()函數(shù)操作仍未結(jié)束,那么超時(shí)設(shè)置將無條件結(jié)束讀/寫操作,而不管是否已讀出或已寫入指定數(shù)量的字符。在讀/寫操作期間發(fā)生的超時(shí)將不按錯(cuò)誤處理,即讀/寫操作返回指定成功的值。對于同步讀/寫操作,實(shí)際傳輸?shù)淖止?jié)數(shù)由ReadFile()和WriteFile()函數(shù)報(bào)告。對于異步操作,則由OVERLAPPED結(jié)構(gòu)來獲取。該結(jié)構(gòu)定義如下:
typedefstruct_OVERLAPPED{ DWORDInternal; //操作系統(tǒng)保留,指出系統(tǒng)相關(guān)狀態(tài)
DWORDInternalHigh; //指出發(fā)送或接收的數(shù)據(jù)長度
DWORDOffset; //文件傳送的開始位置
DWORDOffsetHigh; //文件傳送的字節(jié)偏移量的高位字
HANDLEhEvent //指定一個(gè)I/O操作完成后觸發(fā)的事件
}OVERLAPPED
可以使用下面函數(shù)獲得超時(shí)設(shè)定時(shí)間:
BOOLGetCommTimeouts(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPCOMMTIMEOUTSlpCommTimeouts); //超時(shí)結(jié)構(gòu)體指針
可以使用下面函數(shù)設(shè)置超時(shí):
BOOLSetCommTimeouts(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPCOMMTIMEOUTSlpCommTimeouts); //超時(shí)結(jié)構(gòu)體指針
4.寫串口操作
可以使用Win32API的函數(shù)WriteFile()或者WriteFileEx()向串口中寫數(shù)據(jù)。WriteFile()函數(shù)對同步或異步操作都支持,而WriteFileEx()函數(shù)只支持異步操作。這兩個(gè)函數(shù)都受函數(shù)是否異步操作、超時(shí)操作等有關(guān)參數(shù)的影響和限制。WriteFile()函數(shù)原型如下:
BOOLWriteFile(HANDLEhFile, //文件句柄
LPCVOIDlpBuffer, //數(shù)據(jù)緩存區(qū)指針
DWORDnNumberOfBytesToWrite, //需寫入的字節(jié)數(shù)
LPDWORDlpNumberOfBytesWritten, //實(shí)際寫入字節(jié)數(shù)的存儲區(qū)域指針
LPOVERLAPPEDlpOverlapped); //OVERLAPPED結(jié)構(gòu)體指針
5.通信狀態(tài)操作
獲取串口狀態(tài)使用GetCommState()函數(shù),該函數(shù)原型如下:
BOOLGetCommState(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPDCBlpDCB);//驅(qū)動(dòng)控制塊結(jié)構(gòu)指針
串口的狀態(tài)在成功調(diào)用上述函數(shù)后,將被放入一個(gè)類型名為DCB的結(jié)構(gòu)體,結(jié)構(gòu)體成員定義如下:
typedefstruct_DCB{DWORDDCBlength; //DCB長度
DWORDBaudRate; //指定當(dāng)前的波特率
DWORDfBinary:1; //指定是否允許二進(jìn)制模式
DWORDfParity:1; //指定奇偶校驗(yàn)是否允許
DWORDfOutxCtsFlow:1; //指定Cts是否用于檢測發(fā)送控制
DWORDfOutxDsrFlow:1; //指定Dsr是否用于檢測發(fā)送控制
DWORDfDtrControl:2; //Dtr流控制類型
DWORDfDsrSensitivity:1; //Dsrsensitivity
DWORDfTXContinueOnXoff:1; //XOFF信號時(shí)發(fā)送是否停止
DWORDfOutX:1; //Xon/Xoff流出
DWORDfInX:1; //Xon/Xoff流入控制
DWORDfErrorChar:1; //是否用ErrorChar成員代替錯(cuò)誤字符
DWORDfNull:1; //接收時(shí)是否去掉空(0值)字節(jié)
DWORDfRtsControl:2; //Rts流控制
DWORDfAbortOnError:1; //有錯(cuò)誤發(fā)生時(shí)是否終止讀和寫操作
DWORDfDummy2:17; //保留未用
WORDwReserved; //未使用,必須為0
WORDXonLim; //傳輸Xon字符發(fā)送之前的接收緩沖區(qū)
//中可允許的最小字節(jié)數(shù)
WORDXoffLim; //傳輸Xoff字符發(fā)送之前的接收緩沖區(qū) //中可允許的最小字節(jié)數(shù)
BYTEByteSize; //指定端口當(dāng)前使用的數(shù)據(jù)位
BYTEParity;//指定端口當(dāng)前使用的奇偶校驗(yàn)方法
BYTEStopBits;//指定端口當(dāng)前使用的停止
位數(shù)
charXonChar;//指定用于發(fā)送和接收字符的Xon值
charXoffChar;//指定用于發(fā)送和接收字符的Xoff值
charErrorChar;//代替奇偶校驗(yàn)發(fā)生錯(cuò)誤時(shí)的字符值
charEofChar; //輸入字符結(jié)束
charEvtChar; //當(dāng)接收到此字符時(shí)產(chǎn)生一個(gè)事件
WORDwReserved1;//保留未用
}DCB;
也可人工填寫好DCB結(jié)構(gòu),通過調(diào)用下面函數(shù)設(shè)置串口狀態(tài):
BOOLSetCommState(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPDCBlpDCB);//驅(qū)動(dòng)控制塊結(jié)構(gòu)指針
函數(shù)調(diào)用成功,返回TRUE;否則返回FALSE。
6.串口數(shù)據(jù)清除
串口數(shù)據(jù)清除函數(shù)用于清除串口的錯(cuò)誤信息。如果在串口通信中發(fā)生錯(cuò)誤,如終端、奇偶錯(cuò)誤等,I/O操作將會(huì)終止。如果程序要進(jìn)一步執(zhí)行I/O操作,則必須調(diào)用ClearCommError()函數(shù),它有兩個(gè)作用:清除錯(cuò)誤條件和確定串口通信狀態(tài)。ClearCommError()函數(shù)原型如下:
BOOLClearCommError(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPDWORDlpErrors, //接收錯(cuò)誤碼變量指針
LPCOMSTATlpStat); //通信狀態(tài)存儲區(qū)指針清除串口緩沖區(qū)可通過下面函數(shù)來實(shí)現(xiàn):
BOOLPurgeComm(HANDLEhFile, //通信資源句柄
DWORDdwFlags); //執(zhí)行動(dòng)作
函數(shù)調(diào)用成功后,返回TRUE,代表接收緩存區(qū)被成功清空;否則返回FALSE。
7.串口事件操作
串口事件操作函數(shù)為某一個(gè)驅(qū)動(dòng)器設(shè)置事件,當(dāng)事件發(fā)生時(shí),觸發(fā)并通知主程序??蛇x的事件有EV_BREAK、EV_CTS等(見表3-2)。監(jiān)控的事件可以是“|”聯(lián)結(jié)或多個(gè)事件的組合,如EV_RXCHAR|EV_TXEMPTY。函數(shù)結(jié)構(gòu)如下:
BOOLSetCommMask(HANDLEhFile, //通信驅(qū)動(dòng)句柄
DWORDdwEvtMask); //串口事件掩碼
可使用下面函數(shù)對某事件進(jìn)行查找:
BOOLGetCommMask(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPDWORDlpEvtMask); //接收事件變量指針
事件設(shè)置完畢后,可以調(diào)用下面函數(shù)等待驅(qū)動(dòng)器上設(shè)置的事件的發(fā)生:
BOOLWaitCommEvent(HANDLEhFile, //通信驅(qū)動(dòng)句柄
LPDWORDlpEvtMask, //接收事件變量指針
LPOVERLAPPEDlpOverlapped,); //重疊結(jié)構(gòu)體指針
SetCommMask的調(diào)用會(huì)導(dǎo)致正在監(jiān)聽的WaitCommEvent()立即返回。表3-2串口可選的事件
通常,串口通信可以分為以下幾個(gè)步驟,按這些步驟操作就可以創(chuàng)建自己的串口通信傳輸軟件了。
(1)設(shè)置串口號碼,使用CreateFile()函數(shù)打開串口;
(2)設(shè)置傳輸速度等參數(shù);
(3)設(shè)置超時(shí)參數(shù);
3.3串口通信程序設(shè)計(jì)
(4)設(shè)置事件掩碼來監(jiān)視指定通信端口上的事件;
(5)監(jiān)控事件并寫出或讀入字符串,可以使用WriteFile()及ReadFile()函數(shù);
(6)使用完畢后用CloseHandle()函數(shù)將串口關(guān)閉。
由于使用WindowsAPI中的函數(shù)作為串行通信的基礎(chǔ),使用CreateFile()函數(shù)打開串口后的返回值是一個(gè)數(shù)值(稱為Handle),在往后的函數(shù)中,只要是和該串口有關(guān)的操作與設(shè)置,一定要使用到這個(gè)Handle。這個(gè)Handle就是在串口成功打開后,由操作系統(tǒng)配置的一個(gè)代碼,程序所要求的操作也必須通過出示這個(gè)代碼才得以進(jìn)行。換句話說,就是把這個(gè)分配到的Handle視為該串口的代表,當(dāng)對該Handle進(jìn)行操作時(shí),操作系統(tǒng)會(huì)代為轉(zhuǎn)向到實(shí)際的硬件對象(也就是COM1或COM2)上去。3.3.1枚舉本地機(jī)串口
串口的使用具有隨機(jī)性,也就是用戶在進(jìn)行串口編程的時(shí)候并不知道哪一個(gè)串口處于連接狀態(tài),因此有必要對本地所有串口進(jìn)行枚舉。枚舉的方法主要是查詢注冊表中HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM\\下的鍵值。
下面程序?qū)崿F(xiàn)了對該鍵值的查詢和屏幕打印,使用了RegOpenKeyEx()、RegEnumValue()、RegCloseKey()等三個(gè)注冊表操作函數(shù)。除了實(shí)現(xiàn)枚舉COM口的功能外,對于網(wǎng)絡(luò)程序設(shè)計(jì)中其他相關(guān)的注冊表操作也有借鑒作用。
#include"stdafx.h"
#include"windows.h"http://不要使用winreg.h,因其版本太舊容易引起錯(cuò)誤
intmain(intargc,char*argv[])
{
charstrSerialList[256][25];
//臨時(shí)定義256個(gè)字符串組,因?yàn)橄到y(tǒng)最多也就256個(gè)
ERROR_SUCCESSHKEYhKey;
LPCTSTRdata_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\";
longret0=RegOpenKeyEx(HKEY_LOCAL_MACHINE,data_Set,0,KEY_READ,&hKey);
if(ret0!=ERROR_SUCCESS)return-1;
DWORDcValues;
//獲取"HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM\\"鍵值下項(xiàng)數(shù)目
RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,NULL,NULL,&cValues,NULL,
NULL,NULL,NULL);
CHARName[256];
UCHARszPortName[256];
LONGStatus;
DWORDdwIndex=0;
DWORDdwName;
DWORDdwSizeofPortName;
DWORDType;
dwName=sizeof(Name);
dwSizeofPortName=sizeof(szPortName);
for(DWORDi=0;i<cValues;i++)
{
dwName=sizeof(Name); //一定要在每一次調(diào)用RegEnumValue時(shí)都要初始化!!!
dwSizeofPortName=sizeof(szPortName);
ZeroMemory(Name,256);
ZeroMemory(szPortName,256);
Status=RegEnumValue(hKey,i,Name,&dwName,NULL,&Type,szPortName,
&dwSizeofPortName);
if(ERROR_SUCCESS!=Status)break;
strcpy(&strSerialList[i][0],(char*)szPortName);//串口字符串保存
printf("%s\n",&strSerialList[i][0]);
}
RegCloseKey(hKey);
//…COM調(diào)用
return0;
}
程序執(zhí)行后,COM將會(huì)填入strSerialList數(shù)組,以便后續(xù)調(diào)用。有時(shí)管理員會(huì)因安全原因關(guān)閉所有COM口,那么上述程序則無法查詢到任何端口。3.3.2主機(jī)與單片機(jī)間的通信
下面程序?qū)崿F(xiàn)了主機(jī)與單片機(jī)之間的單工通信,有很多應(yīng)用都是采用這種方式工作的,如主機(jī)從傳感器中接收采集信息。假設(shè)連接于PC的COM4端口,該程序監(jiān)聽一個(gè)基
于單片機(jī)無線接收器接收到的信號,接收數(shù)據(jù)由read_com()函數(shù)實(shí)現(xiàn)(假設(shè)最多接收256個(gè)字節(jié))。
#include"stdafx.h"
#include<shlobj.h>
DWORDread_com(HANDLEhCom,char*Buffer)
{
COMSTATComStat;
DWORDdwErrorFlags;
BOOLbResult;
DWORDnBytesToRead=256;
DWORDnBytesRead;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
bResult=ReadFile(hCom,Buffer,nBytesToRead,&nBytesRead,NULL);
returnnBytesRead;
}
intmain(intargc,char*argv[])
{
HANDLEhCom;
charcom[10]="\\\\.\\COM4";
//1.以同步讀/寫方式打開串口COM4,這里的\\\\.\\COM4是COM的全名,最好寫成這樣
hCom=CreateFile(com, //打開串口COM4
GENERIC_READ|GENERIC_WRITE, //允許進(jìn)行讀/寫操作
0, //獨(dú)占方式
NULL,
OPEN_EXISTING, //打開一個(gè)存在的串口
0,
NULL);
//2.將串口設(shè)置為:波特率為9600,數(shù)據(jù)位數(shù)為7位,停止位為2位,偶校驗(yàn),接收
//緩沖區(qū)和發(fā)送緩沖區(qū)的大小均為1024個(gè)字節(jié),最后用PurgeComm函數(shù)終止所有的后臺
//讀/寫操作并清空接收緩沖區(qū)和發(fā)送緩沖區(qū)
DCBdcb;
GetCommState(hCom,&dcb); //必須調(diào)用一下GetCommState才能使SetCommState的
//返回值不為0?。?!
dcb.BaudRate=9600; //波特率為9600
dcb.ByteSize=7; //數(shù)據(jù)位數(shù)為7位
dcb.Parity=EVENPARITY; //偶校驗(yàn)
dcb.StopBits=2; //兩個(gè)停止位
dcb.fBinary=TRUE;
dcb.fParity=TRUE;
if(SetCommState(hCom,&dcb)==0)
{
MessageBox(NULL,"串口連接不正確!",NULL,MB_OK);
return0;
}
SetupComm(hCom,1024,1024);//設(shè)置串口緩沖區(qū)的大小為1024位
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|
PURGE_TXCLEAR|PURGE_RXCLEAR); //清空串口緩沖區(qū)
//3.程序?qū)⒋谧x操作的超時(shí)設(shè)定為10毫秒
COMMTIMEOUTSto;
memset(&to,0,sizeof(to));
to.ReadIntervalTimeout=10;
SetCommTimeouts(hCom,&to);
//4.設(shè)置事件掩碼來監(jiān)視指定通信端口上的事件
SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY|EV_BREAK);
OVERLAPPEDov;
DWORDlpEvtMask;
charrcvbuff[256];
ZeroMemory(&ov,sizeof(ov));
intread_num=0;
ov.hEvent=CreateEvent(0,true,0,0);
do
{
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|
PURGE_TXCLEAR|PURGE_RXCLEAR);
//5.等待串口上出現(xiàn)了利用SetCommMask()函數(shù)設(shè)置的事件
WaitCommEvent(hCom,&lpEvtMask,&ov);//程序在此阻塞,直到COM中接收到數(shù)據(jù)
if((lpEvtMask&EV_BREAK)==EV_BREAK)
{
printf("串口斷開!\n");
break;
}
read_num=read_com(hCom,rcvbuff);
if(read_num==0)continue;
//...接收數(shù)據(jù)處理
ZeroMemory(rcvbuff,256);
}while(1);
//6.關(guān)閉串口
CloseHandle(hCom);
return0;
}
注意:在接收數(shù)據(jù)前,必須根據(jù)監(jiān)控設(shè)備的有關(guān)通信參數(shù)約定雙方的通信方式,包括各種參數(shù)的設(shè)置,如程序中的步驟2。3.3.3主機(jī)間的通信
以下程序可以實(shí)現(xiàn)兩臺主機(jī)之間的串口數(shù)據(jù)傳輸,可用于計(jì)算機(jī)與路由器或交換機(jī)進(jìn)行交互。在無網(wǎng)絡(luò)可用的時(shí)候應(yīng)急用。與3.3.1節(jié)中的程序功能不完全相同,最大的區(qū)別就是該程序是雙工的。連接線采用TXD與RXD交叉相連、GND共線的方法。程序代碼如下(下面主要列出了與3.3.1節(jié)中不同的代碼):
…
DWORDwrite_com(HANDLEhCom,char*Buffer)
{
OVERLAPPEDm_ov;
BOOLbResult;
DWORDnBytesToSend=strlen(Buffer);
DWORDnBytesSend;
charbuff[10];
m_ov.Offset=0;
m_ov.OffsetHigh=0;
PurgeComm(
hCom,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|
PURGE_TXABORT);
bResult=WriteFile(hCom,buff,nBytesToSend,&nBytesSend,&m_ov);//Overlappedstructure
returnnBytesSend;
}
intmain(intargc,char*argv[])
{
HANDLEhCom;
charcom[10]="\\\\.\\COM4";
//1.以同步讀/寫方式打開串口COM4,這里的\\\\.\\COM4是COM的全名,最好寫成這樣
hCom=CreateFile(com, //打開串口COM4
GENERIC_READ|GENERIC_WRITE, //允許進(jìn)行讀/寫操作
0, //獨(dú)占方式
NULL,
OPEN_EXISTING, //打開一個(gè)存在的串口
FILE_FLAG_OVERLAPPED, //設(shè)置為異步串口
NULL);
…//與3.3.2節(jié)的程序相同
//4.設(shè)置事件掩碼來監(jiān)視指定通信端口上的事件
SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY|EV_BREAK);
OVERLAPPEDov;
DWORDlpEvtMask;
charbuff[256];
ZeroMemory(&ov,sizeof(ov));
DWORDEvent;
DWORDCommEvent=0;
intread_num=0;
HANDLE m_hEventArray[2];
HANDLE WriteEvent={0};
HANDLE ExitEvent={0};
ov.hEvent=CreateEvent(0,true,0,0);
PurgeComm(hCom,URGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|
PURGE_RXCLEAR);
m_hEventArray[0]=ov.hEvent;
m_hEventArray[1]=WriteEvent;
m_hEventArray[2]=ExitEvent;
//5.等待串口上出現(xiàn)讀、寫和關(guān)閉串口等三類事件
do
{
if(WaitCommEvent(hCom,&lpEvtMask,&ov)==0) //因?yàn)閔Com為異步模式,所以在
//這里不會(huì)阻塞
{
printf("WaitCommEventiserror!\n");
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國紙帽數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2030年中國寵物掛飾數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2030年中國全自動(dòng)飯柜數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2030年中國PDA點(diǎn)菜系統(tǒng)數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2031年中國谷物清理機(jī)行業(yè)投資前景及策略咨詢研究報(bào)告
- 2025年度電商直播內(nèi)容制作合同4篇
- 2025年度出租車司機(jī)休息休假聘用合同4篇
- 二零二五年度存量房交易合同與物業(yè)管理交接服務(wù)協(xié)議4篇
- 二零二五年度美容院美容產(chǎn)品綠色生產(chǎn)合同3篇
- 2025年繆含離婚協(xié)議書及離婚后財(cái)產(chǎn)監(jiān)管協(xié)議4篇
- 2024-2025學(xué)年北京石景山區(qū)九年級初三(上)期末語文試卷(含答案)
- 第一章 整式的乘除 單元測試(含答案) 2024-2025學(xué)年北師大版數(shù)學(xué)七年級下冊
- 春節(jié)聯(lián)歡晚會(huì)節(jié)目單課件模板
- 中國高血壓防治指南(2024年修訂版)
- 糖尿病眼病患者血糖管理
- 抖音音樂推廣代運(yùn)營合同樣本
- 教育促進(jìn)會(huì)會(huì)長總結(jié)發(fā)言稿
- 北師大版(2024新版)七年級上冊數(shù)學(xué)第四章《基本平面圖形》測試卷(含答案解析)
- 心理調(diào)適教案調(diào)整心態(tài)積極應(yīng)對挑戰(zhàn)
- 噴漆外包服務(wù)合同范本
- JT-T-390-1999突起路標(biāo)行業(yè)標(biāo)準(zhǔn)
評論
0/150
提交評論