深入淺出Visual C++串口編程_第1頁
深入淺出Visual C++串口編程_第2頁
深入淺出Visual C++串口編程_第3頁
深入淺出Visual C++串口編程_第4頁
深入淺出Visual C++串口編程_第5頁
已閱讀5頁,還剩111頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、深入淺出Visual C+串口編程RS-232C接口,1970年由美國電子工業(yè)協(xié)會聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定,全名是數(shù)據(jù)終端設備(DTE)和數(shù)據(jù)通訊設備(DCE)之間串行二進制數(shù)據(jù)交換接口技術標準。本期教程將對DOS平臺的串口編程,及Windows平臺下基于API、控件和第三方類的串口編程進行介紹?;靖拍钜栽赑C機的主板上,有一種類型的接口可能為我們所忽視,那就是RS-232C串行接口,在微軟的Windows系統(tǒng)中稱其為COM。我們可以通過設備管理器來查看COM的硬件參數(shù)設置,如圖1。圖1 在Windows上查看PC串口設置迄今為止,幾乎每一臺PC都包含COM

2、。本質(zhì)而言,COM是PC為和外界通信所提供的一種串行數(shù)據(jù)傳輸?shù)慕涌凇W鳛橐环N物理通信的途徑和設備,它和目前風靡的另一種串行接口USB所提供的功能是一致的。不過RS-232C顯然已經(jīng)開始被后起之秀USB趕超,因為USB的傳輸速率已經(jīng)遠遠超過了RS-232C。盡管如此,RS-232C仍然具有非常廣泛的應用,在相對長的一段時間里,難以被USB等接口取代。RS-232C接口(又稱EIA RS-232C),1970年由美國電子工業(yè)協(xié)會(EIA)聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定,全名是數(shù)據(jù)終端設備(DTE)和數(shù)據(jù)通訊設備(DCE)之間串行二進制數(shù)據(jù)交換接口技術標準。本文將對這一接口

3、進行硬件原理的介紹,隨后我們將逐章學習DOS平臺的串口編程,及Windows平臺下基于API、控件和第三方類的串口編程,最后本文將給出一個綜合實例。在本文的連載過程中,您可以通過如下方式聯(lián)系作者(熱忱歡迎讀者朋友對本文的內(nèi)容提出質(zhì)疑或給出修改意見):作者email:21cnbao(可以來信提問,筆者將力求予以回信解答,并摘取其中的典型問題,在本系列文章最后一次連載的讀者反饋中予以闡述);硬件原理眾所周知,CPU與存儲芯片和I/O芯片的通信是并行的(并行傳輸?shù)淖畲笪粩?shù)依賴于CPU的字長、數(shù)據(jù)總線的寬度),一種叫做UART(通用異步收發(fā)器,Universal Asynchronous Receiv

4、er/Transmitter)的芯片提供了并行數(shù)據(jù)傳輸和RS-232C串行數(shù)據(jù)傳輸方式的轉換。這樣的設備通常有如圖2所示的管腳分布,當其向外傳輸數(shù)據(jù)時,CPU并行的將數(shù)據(jù)寫入這類芯片的寄存器,UART再將寄存器中的數(shù)據(jù)一位一位地移動并向外傳輸;當外界向其傳輸數(shù)據(jù)時,UART一位一位地接收數(shù)據(jù),并將其移位組合為并行數(shù)據(jù),CPU再并行地讀取這些數(shù)據(jù)。實際上,由于UART芯片一般以TTL/CMOS電平工作,在UART連接接口之前,還要經(jīng)過一個TTL/CMOS和RS-232C電平的轉換。RS-232C規(guī)定了其標準的電氣特性,邏輯1對應的電壓必須在-5-15V之間;邏輯0對應的的電壓必須在+5+15V之

5、間。圖2 UART并/串轉換一個常見的TTL/CMOS和RS-232C電平轉換芯片如圖3。圖3 常見的TTL/CMOS和RS-232C電平轉換芯片RS-232C通常以兩類接插件與外界相連,分別稱為DB9和DB25,如圖4所示。圖4 DB9和DB25而接插件中各個針的定義則如表1:表1 DB9和DB25引腳定義DB9 DB25針號 功能說明 縮寫 針號 功能說明 縮寫1 數(shù)據(jù)載波檢測DCD 8 數(shù)據(jù)載波檢測 DCD2 接收數(shù)據(jù) RXD 3 接收數(shù)據(jù)RXD3 發(fā)送數(shù)據(jù)TXD2 發(fā)送數(shù)據(jù) TXD4 數(shù)據(jù)終端準備 DTR 20 數(shù)據(jù)終端準備 DTR5 信號地 GND 7 信號地 GND6 數(shù)據(jù)設備準備

6、好DSR6 數(shù)據(jù)準備好DSR7 請求發(fā)送RTS 4 請求發(fā)送 RTS8 清除發(fā)送 CTS 5 清除發(fā)送CTS9 振鈴指示DELL22 振鈴指示DELLRS-232C定義為數(shù)據(jù)通信設備(DCE)和數(shù)據(jù)終端設備(DTE)之間的互連,實現(xiàn)上,到現(xiàn)在為止,究竟一個設備屬于DCE還是屬于DTE已經(jīng)沒有明顯的界限,PC即可作為DCE,又可作為DTE。兩串口互連,連接方法主要有二:一種方法是,數(shù)據(jù)的發(fā)送和接收由軟件控制,不進行硬件握手,其連接方法如圖5(最常用DB9連接示意)和表2(DB9、DB25三線連接表),真正需要互相連接的是RXD、TXD和GND;圖5 無硬件握手時兩串口連接表2 DB9、DB25三

7、線連接9針9針5針25針2 9針25針2 3 3 2 2 23 2 2 3 3 3 5 5 7 7 5 7 軟件握手又稱為XON/XOFF,通常以CTRL-S(0x13)和CTRL-Q(0x11)兩個字符來實現(xiàn)流控制。前者用于請求對方暫停發(fā)送,后者用于清除暫停傳送的請求,繼續(xù)發(fā)送數(shù)據(jù)。另一種方法是,數(shù)據(jù)的發(fā)送和接收由硬件控制,進行硬件握手,其連接方法如圖6(最常用DB9連接示意),需要連接的信號除RXD、TXD和GND外,還包括DTR、DSR、RTS和CTS。硬件握手依賴于RTS和CTS信號,當發(fā)送設備欲發(fā)送數(shù)據(jù)時,將RTS信號置為有效表示請求發(fā)送,接收設備準備好后,置CTS信號有效,接著發(fā)送

8、設備通過信號線TXD開始發(fā)送串行數(shù)據(jù)。這里我們聯(lián)想開來,RTS/CTS模式在許多領域里都出現(xiàn)過?;貞浺幌翴EEE 802.11無線局域網(wǎng)協(xié)議標準,在其MAC協(xié)議中就使用了RTS/CTS,RTS/CTS抽象開來就是一種請求/應答。筆者曾經(jīng)在拙作中多次以實例論證計算機領域里許多知識的相通性,這又是一個明證。圖6 有硬件握手時兩串口連接實際上,目前我們經(jīng)常使用的是方法一,即只連接RXD、TXD和GND,簡單靈活。另外,串口之間互連還有諸多途徑,如圖7所示。圖7 其它互連方式調(diào)試工具在MS-DOS下使用的編程環(huán)境是TC 2.0;在Windows 2000下的編程環(huán)境是VC+ 6.0;借助工具:串口調(diào)試

9、助手2.1(圖8)。圖8 串口調(diào)試助手串口調(diào)試助手是由Visual C+/Turbo C串口通信編程實踐一書作者龔建偉編寫的共享軟件,可以方便地進行串口上的數(shù)據(jù)收發(fā)、顯示(16進制和ASCII碼方式)和串口參數(shù)的設置,在串口調(diào)試領域應用廣泛。串口調(diào)試助手的開發(fā)原理很簡單(相信讀者看完本文后在相當短的時間之內(nèi)就能開發(fā)出這樣的軟件),但是作者龔建偉敏銳地抓住了串口調(diào)試在業(yè)界的需求,使得自身隨這一軟件而成名。這一事件或多或少會給程序員們一定的啟發(fā)。優(yōu)秀的共享軟件不一定要技術含量高,只要有需求,哪怕是開發(fā)原理再簡單,都能擁有廣泛的使用者。為了在一臺PC上同時搭建DOS和Windows平臺,我們應該在W

10、indows平臺上安裝虛擬PC的軟件VmWare(圖9,VMware Inc.版權所有,)。VMware的確是天才的作品!在同一PC上,利用VmWare幾乎可以安裝所有的操作系統(tǒng),而且操作系統(tǒng)之間的切換不需要重新啟動電腦,與傳統(tǒng)的LILO等多系統(tǒng)引導方式有本質(zhì)的不同。VM的意義是Virtual Machine,即虛擬出一個邏輯的電腦。圖9 VmWare虛擬PC在虛擬PC的MS-DOS操作系統(tǒng)上,我們安裝TC 2.0開發(fā)環(huán)境。如果您的PC上沒有軟驅(qū),為了制作MS-DOS啟動軟盤,請安裝RamDiskNT模擬一個軟盤,并在其上安裝MS-DOS啟動程序。RamDiskNT是一個磁盤模擬軟件,其界面如

11、圖10所示。圖10 磁盤模擬深入淺出VC+串口編程之DOS的串口編程在DOS平臺下,操作串口主要有下列方式:通過BIOS調(diào)用、通過串口的硬件中斷或通過對串口硬件進行輪詢,本章將對以上三種方式進行具體的介紹并給出例子。1.BIOS中斷在DOS操作系統(tǒng)下,IBM PC及其兼容機提供了一種靈活的串口I/O訪問方法,即通過INT 14H調(diào)用ROM BIOS串行通訊例行程序。當設置AH為不同的值時,產(chǎn)生不同的功能:AH 0 初始化端口AH 1 向串口寫字符AH 2 從串口讀字符AH 3 取通訊口狀態(tài)初始化端口時(即當AH0時),需要在AL寄存器中賦一字節(jié)初始化參數(shù),其各項意義如圖1;圖1 調(diào)用INT 1

12、4H時AL寄存器設置當向串口寫字符時(即當AH1時),AL寄存器中的字符是需要寫入的字符;當向串口寫字符時(即當AH2時),AL寄存器中的字符是需要讀取的字符。看看下面的例程:#include #include #include #define STR author:sbhunion REGS inregs,outregs;main() /設置串口參數(shù)init_rs232();/寫串口的例子write_rs232(STR,strlen(STR);/讀串口的例子read_rs232();return(0);init_rs232()doinregs.h.ah=0; /AH=0表示初始化端口inre

13、gs.h.al=0xe7;inregs.x.dx=0; /COM1int86(0x14, &inregs, &outregs);while(outregs.h.ah=0x80);return(0);write_rs232(char *string, int len)int i;doinregs.h.ah=1;/發(fā)送AL寄存器的字符inregs.h.al= *string;inregs.x.dx=0;int86(0x14, &inregs, &outregs);while(outregs.h.al=0x80);for(i=1;i=0x80);return(0);其中使用的int86函數(shù)的原型為:

14、int _Cdecl int86(int intno, union REGS *inregs, union REGS *outregs);int86()函數(shù)可以調(diào)用BIOS功能,現(xiàn)在的程序員們已經(jīng)很少接觸這個函數(shù),80%的程序員甚至都未曾見過這個函數(shù)。其實,在茹毛飲血的DOS時代,int86()函數(shù)幾乎是最常用和最核心的函數(shù)之一。幾乎可以說,在那個時代,不會int86()就等于不會編程。而與int86配合使用的,就是REGS這樣一個聯(lián)合體,定義為:union REGS struct WORDREGS x;struct BYTEREGS h;其中的WORDREGS定義為:struct WORDR

15、EGS unsigned int ax, bx, cx, dx, si, di,cflag /*進位標志*/,flags /*標志寄存器*/;而BYTEREGS則定義為:struct BYTEREGS unsigned char al, ah, bl, bh, cl, ch, dl, dh;原來WORDREGS和BYTEREGS是16位的8086處理器內(nèi)部的寄存器??!因此,當CPU發(fā)展到286、386以后,再安裝DOS也是建立在利用CPU實模式的基礎上的!另外一個函數(shù)與int86()的功能是類似的:Int _Cdecl int86x(int intno, union REGS inregs,

16、union REGS outregs, struct SREGS segregs); 其中的SREGS為段寄存器結構體,定義為:struct SREGS unsigned int es;unsigned int cs;unsigned int ss;unsigned int ds;int86和int86x這兩個函數(shù)的功能都是執(zhí)行一個由參數(shù)intno指定的8086軟中斷。在執(zhí)行軟中斷之前,兩個函數(shù)都把inregs中的內(nèi)容放置到各寄存器中(int86x還把segregs.x.es和segregs.x.ds的值存到相應的段寄存器中),軟中斷返回后,這兩個函數(shù)都把當前寄存器的值存到outregs,并把

17、系統(tǒng)進位標志拷貝到outregs.s.cflag中,把8086標志寄存器值存到outregs.x.flag中(int86x還恢復DS,并設置Segregs.es和Segregs.ds的值為對應段寄存器的值)。查閱BIOS中斷調(diào)用手冊,發(fā)現(xiàn)絕大多數(shù)調(diào)用都未用到ES和DS段寄存器,故在程序設計中經(jīng)常只利用了int86函數(shù)。2.硬件中斷為了給讀者一個直觀的印象,我們通過在Windows操作系統(tǒng)中查看COM的資源屬性獲得某COM對應的中斷號,如圖2(該對話框中設備管理器中開啟)。圖2 COM中斷號實際上COM的確直接對應于一個中斷,而系統(tǒng)也按照一定的規(guī)律為各類硬件分配了一個較固定的中斷號,如表1。表1

18、 中斷向量表INT (Hex) IRQ Common Uses08 0 System Timer09 1 Keyboard0A 2 Redirected0B 3 Serial Comms. COM2/COM40C 4 Serial Comms. COM1/COM3 0D 5Reserved/Sound Card 0E 6 Floppy Disk Controller 0F7 Parallel Comms. 70 8 Real Time Clock71 9 Reserved72 10 Reserved73 11 Reserved74 12 PS/2 Mouse75 13Maths Co-Proc

19、essor76 14 Hard Disk Drive77 15 Reserved 通過編寫COM對應的中斷服務程序,我們也可以操作串口,涉及到的相關函數(shù)有:(1)設置中斷向量表/*dos.h*/void _Cdecl setvect (int interruptno, void interrupt (*isr) ();例如,COM3對應的中斷號是4,那么對應中斷向量表中的地址是0x0C,設置0x0C對應中斷程序的函數(shù)為:setvect(0x0C, PORT1INT);其中的中斷服務程序PORT1INT為:void interrupt PORT1INT()int c;doc = inportb(

20、PORT1 + 5);if (c &1)bufferbufferin = inportb(PORT1);bufferin+;if (bufferin = 1024)bufferin = 0;while (c &1);outportb(0x20, 0x20);上述中斷服務程序檢查是否有字符可接收,其后將其通過inportb(PORT1)語句將其從UART中讀出并放入輸入buffer。持續(xù)的檢查UART,以便能在一次中斷里讀取所有可獲得的數(shù)據(jù)。最后的outportb(0x20,0x20);語句告訴可編程中斷控制器(Programmable Interrupt Controller,PIC)中斷已經(jīng)

21、完成。(2)讀取中斷向量表/*dos.h*/void interrupt (* _Cdecl getvect(int interruptno) ();例如:oldport1isr = getvect(INTVECT); 其中的oldport1isr定義為:void interrupt (*oldport1isr)();我們?nèi)诤蟬etvect()函數(shù)、中斷服務程序和getvect()函數(shù),給出一個由Craig Peacock編寫的完備例程:/* Name : Sample Comms Program - 1024 Byte Buffer - buff1024.c */* Written By :

22、 Craig Peacock */#include #include #include #define PORT1 0x3F8 /* Port Address Goes Here */#define INTVECT 0x0C /* Com Ports IRQ here (Must also change PIC setting) */* Defines Serial Ports Base Address */* COM1 0x3F8 */* COM2 0x2F8 */* COM3 0x3E8 */* COM4 0x2E8 */int bufferin = 0;int bufferout = 0

23、;char ch;char buffer1025;void interrupt(*oldport1isr)();void interrupt PORT1INT() /* Interrupt Service Routine (ISR) for PORT1 */int c;doc = inportb(PORT1 + 5);if (c &1)bufferbufferin = inportb(PORT1);bufferin+;if (bufferin = 1024)bufferin = 0;while (c &1);outportb(0x20, 0x20);void main(void)int c;o

24、utportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */oldport1isr = getvect(INTVECT); /* Save old Interrupt Vector of laterrecovery */setvect(INTVECT, PORT1INT); /* Set Interrupt Vector Entry */* COM1 - 0x0C */* COM2 - 0x0B */* COM3 - 0x0C */* COM4 - 0x0B */* PORT 1 - Communication Settings */outp

25、ortb(PORT1 + 3, 0x80); /* SET DLAB ON */outportb(PORT1 + 0, 0x0C); /* Set Baud rate - Divisor Latch Low Byte */* Default 0x03 = 38,400 BPS */* 0x01 = 115,200 BPS */* 0x02 = 57,600 BPS */* 0x06 = 19,200 BPS */* 0x0C = 9,600 BPS */* 0x18 = 4,800 BPS */* 0x30 = 2,400 BPS */outportb(PORT1 + 1, 0x00); /*

26、 Set Baud rate - Divisor Latch High Byte */outportb(PORT1 + 3, 0x03); /* 8 Bits, No Parity, 1 Stop Bit */outportb(PORT1 + 2, 0xC7); /* FIFO Control Register */outportb(PORT1 + 4, 0x0B); /* Turn on DTR, RTS, and OUT2 */outportb(0x21, (inportb(0x21) &0xEF); /* Set Programmable Interrupt Controller */*

27、 COM1 (IRQ4) - 0xEF */* COM2 (IRQ3) - 0xF7 */* COM3 (IRQ4) - 0xEF */* COM4 (IRQ3) - 0xF7 */outportb(PORT1 + 1, 0x01); /* Interrupt when data received */printf(nSample Comms Program. Press ESC to quit n);doif (bufferin != bufferout)ch = bufferbufferout;bufferout+;if (bufferout = 1024)bufferout = 0;pr

28、intf(%c, ch);if (kbhit()c = getch();outportb(PORT1, c);while (c != 27);outportb(PORT1 + 1, 0);/* Turn off interrupts - Port1 */outportb(0x21, (inportb(0x21) | 0x10); /* MASK IRQ using PIC */* COM1 (IRQ4) - 0x10 */* COM2 (IRQ3) - 0x08 */* COM3 (IRQ4) - 0x10 */* COM4 (IRQ3) - 0x08 */setvect(INTVECT, o

29、ldport1isr); /* Restore old interrupt vector */3.硬件查詢通過讀取和寫入串口UART對應的硬件端口,我們可以控制串口的收發(fā)。請看下面的例子:/* Name : Sample Comms Program - Polled Version - termpoll.c */* Written By : Craig Peacock */#include #include #include #define PORT1 0x3F8/* Defines Serial Ports Base Address */* COM1 0x3F8 */* COM2 0x2F8

30、 */* COM3 0x3E8 */* COM4 0x2E8 */void main(void)int c;int ch;outportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */* PORT 1 - Communication Settings */outportb(PORT1 + 3, 0x80); /* SET DLAB ON */outportb(PORT1 + 0, 0x03); /* Set Baud rate - Divisor Latch Low Byte */* Default 0x03 = 38,400 BPS */*

31、 0x01 = 115,200 BPS */* 0x02 = 57,600 BPS */* 0x06 = 19,200 BPS */* 0x0C = 9,600 BPS */* 0x18 = 4,800 BPS */* 0x30 = 2,400 BPS */outportb(PORT1 + 1, 0x00); /* Set Baud rate - Divisor Latch High Byte */outportb(PORT1 + 3, 0x03); /* 8 Bits, No Parity, 1 Stop Bit */outportb(PORT1 + 2, 0xC7); /* FIFO Co

32、ntrol Register */outportb(PORT1 + 4, 0x0B); /* Turn on DTR, RTS, and OUT2 */printf(nSample Comms Program. Press ESC to quit n);doc = inportb(PORT1 + 5); /* Check to see if char has been */* received. */if (c &1)ch = inportb(PORT1); /* If so, then get Char */printf(%c, ch); /* Print Char to Screen */

33、if (kbhit()ch = getch(); /* If key pressed, get Char */outportb(PORT1, ch); /* Send Char to Serial Port */while (ch != 27); /* Quit when ESC (ASC 27) is pressed */程序中的c = inportb(PORT1 + 5); /* Check to see if char has been */* received. */if (c &1)檢查PORT1 + 5端口地址,通過c&1可以判斷是否有數(shù)據(jù)被UART接收到。關于UART對應的端口范

34、圍,從圖2中也可以直觀地看出。深入淺出VC+串口編程之基于Win32 API1、API描述在WIN32 API中,串口使用文件方式進行訪問,其操作的API基本上與文件操作的API一致。打開串口Win32 中用于打開串口的API 函數(shù)為CreateFile,其原型為:HANDLE CreateFile (LPCTSTR lpFileName, /將要打開的串口邏輯名,如COM1 或COM2DWORD dwAccess, /指定串口訪問的類型,可以是讀取、寫入或兩者并列DWORD dwShareMode, /指定共享屬性,由于串口不能共享,該參數(shù)必須置為0LPSECURITY_ATTRIBUTES

35、 lpsa, /引用安全性屬性結構,缺省值為NULLDWORD dwCreate, /創(chuàng)建標志,對串口操作該參數(shù)必須置為OPEN EXISTINGDWORD dwAttrsAndFlags, /屬性描述,用于指定該串口是否可進行異步操作,/FILE_FLAG_OVERLAPPED:可使用異步的I/OHANDLE hTemplateFile /指向模板文件的句柄,對串口而言該參數(shù)必須置為NULL);例如,以下程序用于以同步讀寫方式打開串口COM1:HANDLE hCom;DWORD dwError;hCon = CreateFile(COM1, GENERIC_READ | GENERIC_WR

36、ITE, 0, NULL, OPEN_EXISTING, 0, NULL);if (hCom = (HANDLE)0xFFFFFFFF)dwError = GetLastError();MessageBox(dwError);對于dwAttrsAndFlags參數(shù)及FILE_FLAG_OVERLAPPED標志的由來,可解釋如下:Windows文件操作分為同步I/O和重疊I/O(Overlapped I/ O)兩種方式,在同步I/O方式中,API會阻塞直到操作完成以后才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監(jiān)聽線程);而在重疊I/O方式中,API會立即返回,操作在后臺進行,避

37、免線程的阻塞。重疊I/O非常靈活,它也可以實現(xiàn)阻塞(例如我們可以設置一定要讀取到一個數(shù)據(jù)才能進行到下一步操作)。如果進行I/O操作的API 在沒有完成操作的情況下返回,我們可以通過調(diào)用GetOverLappedResult()函數(shù)阻塞到I/O操作完成后返回。配置串口配置串口是通過改變設備控制塊DCB(Device Control Block) 的成員變量值來實現(xiàn)的,接收緩沖區(qū)和發(fā)送緩沖區(qū)的大小可通過SetupComm函數(shù)來設置。DCB結構體定義為:typedef struct _DCB / dcb DWORD DCBlength; / sizeof(DCB) DWORD BaudRate; /

38、 current baud rate DWORD fBinary: 1; / binary mode, no EOF check DWORD fParity: 1; / enable parity checking DWORD fOutxCtsFlow:1; / CTS output flow control DWORD fOutxDsrFlow:1; / DSR output flow control DWORD fDtrControl:2; / DTR flow control type DWORD fDsrSensitivity:1; / DSR sensitivity DWORD fT

39、XContinueOnXoff:1; / XOFF continues Tx DWORD fOutX: 1; / XON/XOFF out flow control DWORD fInX: 1; / XON/XOFF in flow control DWORD fErrorChar: 1; / enable error replacement DWORD fNull: 1; / enable null stripping DWORD fRtsControl:2; / RTS flow control DWORD fAbortOnError:1; / abort reads/writes on

40、error DWORD fDummy2:17; / reserved WORD wReserved; / not currently used WORD XonLim; / transmit XON threshold WORD XoffLim; / transmit XOFF threshold BYTE ByteSize; / number of bits/byte, 4-8 BYTE Parity; / 0-4=no,odd,even,mark,space BYTE StopBits; / 0,1,2 = 1, 1.5, 2 char XonChar; / Tx and Rx XON c

41、haracter char XoffChar; / Tx and Rx XOFF character char ErrorChar; / error replacement character char EofChar; / end of input character char EvtChar; / received event character WORD wReserved1; / reserved; do not use DCB; 而SetupComm函數(shù)的原型則為:BOOL SetupComm(HANDLE hFile, / handle to communications devi

42、ceDWORD dwInQueue, / size of input bufferDWORD dwOutQueue / size of output buffer);以下程序?qū)⒋谠O置為:波特率為9600,數(shù)據(jù)位數(shù)為7位,停止位為2 位,偶校驗,接收緩沖區(qū)和發(fā)送緩沖區(qū)大小均為1024個字節(jié),最后用PurgeComm函數(shù)終止所有的后臺讀寫操作并清空接收緩沖區(qū)和發(fā)送緩沖區(qū):DCB dcb;dcb.BaudRate = 9600; /波特率為9600dcb.ByteSize = 7; /數(shù)據(jù)位數(shù)為7位dcb.Parity = EVENPARITY; /偶校驗dcb.StopBits = 2; /兩個

43、停止位dcb.fBinary = TRUE;dcb.fParity = TRUE;if (!SetCommState(hCom, &dcb)MessageBox(串口設置出錯!); SetupComm(hCom, 1024, 1024);PurgeComm(hCom, PURCE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);超時設置超時設置是通過改變COMMTIMEOUTS結構體的成員變量值來實現(xiàn)的,COMMTIMEOUTS的原型為:typedef struct _COMMTIMEOUTSDWORD ReadInterval

44、Timeout; /定義兩個字符到達的最大時間間隔,單位:毫秒/當讀取完一個字符后,超過了ReadIntervalTimeout,仍未讀取到下一個字符,就會/發(fā)生超時DWORD ReadTotalTimeoutMultiplier; DWORD ReadTotalTimeoutConstant;/其中各時間所滿足的關系如下:/ReadTotalTimeout = ReadTotalTimeOutMultiplier* BytesToRead + ReadTotalTimeoutConstantDWORD WriteTotalTimeoutMultiplier;DWORD WriteTotalT

45、imeoutConstant; COMMTIMEOUTS, *LPCOMMTIMEOUTS;設置超時的函數(shù)為SetCommTimeouts,其原型中接收COMMTIMEOUTS的指針為參數(shù):BOOL SetCommTimeouts(HANDLE hFile, / handle to communications deviceLPCOMMTIMEOUTS lpCommTimeouts / pointer to comm time-out structure);以下程序?qū)⒋谧x操作的超時設定為10 毫秒:COMMTIMEOUTS to;memset(&to, 0, sizeof(to);to.Re

46、adIntervalTimeout = 10;SetCommTimeouts(hCom, &to);與SetCommTimeouts對應的GetCommTimeouts()函數(shù)的原型為:BOOL GetCommTimeouts(HANDLE hFile, / handle of communications deviceLPCOMMTIMEOUTS lpCommTimeouts / pointer to comm time-out structure);事件設置在讀寫串口之前,需要用SetCommMask ()函數(shù)設置事件掩模來監(jiān)視指定通信端口上的事件,其原型為:BOOL SetCommMas

47、k(HANDLE hFile, /標識通信端口的句柄DWORD dwEvtMask /能夠使能的通信事件);有了Set當然還會有Get,與SetCommMask對應的GetCommMask()函數(shù)的原型為:BOOL GetCommMask(HANDLE hFile, /標識通信端口的句柄LPDWORD lpEvtMask / address of variable to get event mask);串口上可以發(fā)生的事件可以是如下事件列表中的一個或任意組合:EV_BREAK、EV_CTS、EV_DSR、EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV

48、_TXEMPTY。我們可以用WaitCommEvent()函數(shù)來等待串口上我們利用SetCommMask ()函數(shù)設置的事件:BOOL WaitCommEvent(HANDLE hFile, /標識通信端口的句柄LPDWORD lpEvtMask, / address of variable for event that occurredLPOVERLAPPED lpOverlapped, / address of overlapped structure);WaitCommEvent()函數(shù)一直阻塞,直到串口上發(fā)生我們用所SetCommMask ()函數(shù)設置的通信事件為止。一般而言,當Wai

49、tCommEvent()返回時,程序員可以由分析*lpEvtMask而獲得發(fā)生事件的類別,再進行相應的處理。讀串口對串口進行讀取所用的函數(shù)和對文件進行讀取所用的函數(shù)相同,讀函數(shù)原型如下:BOOL ReadFile(HANDLE hFile, / handle of file to readLPVOID lpBuffer, / pointer to buffer that receives dataDWORD nNumberOfBytesToRead, / number of bytes to readLPDWORD lpNumberOfBytesRead, / pointer to numbe

50、r of bytes readLPOVERLAPPED lpOverlapped / pointer to structure for overlapped I/O);寫串口對串口進行寫入所用的函數(shù)和對文件進行寫入所用的函數(shù)相同,寫函數(shù)原型如下:BOOL WriteFile(HANDLE hFile, / handle to file to write toLPCVOID lpBuffer, / pointer to data to write to fileDWORD nNumberOfBytesToWrite, / number of bytes to writeLPDWORD lpNum

51、berOfBytesWritten, / pointer to number of bytes writtenLPOVERLAPPED lpOverlapped / pointer to structure for overlapped I/O);關閉串口利用API 函數(shù)實現(xiàn)串口通信時關閉串口非常簡單,只需使用CreateFile 函數(shù)返回的句柄作為參數(shù)調(diào)用CloseHandle 即可:BOOL CloseHandle(HANDLE hObject / handle to object to close);2.例程在筆者的深入淺出Win32多線程程序設計之綜合實例中我們已經(jīng)給出一個利用WIN API進行串口通信的例子,這里再給出一個類似的例子,以進一步加深理解。對話框上控件對應的資源文件(.RC)中的內(nèi)容如下:BEGINEDITTEXT IDC_RECV_EDIT,28,1

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論