版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、深入浅出Visual C+串口编程RS-232C接口,1970年由美国电子工业协会联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定,全名是数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准。本期教程将对DOS平台的串口编程,及Windows平台下基于API、控件和第三方类的串口编程进行介绍。基本概念引言在PC机的主板上,有一种类型的接口可能为我们所忽视,那就是RS-232C串行接口,在微软的Windows系统中称其为COM。我们可以通过设备管理器来查看COM的硬件参数设置,如图1。图1 在Windows上查看PC串口设置迄今为止,几乎每一台PC都包含COM
2、。本质而言,COM是PC为和外界通信所提供的一种串行数据传输的接口。作为一种物理通信的途径和设备,它和目前风靡的另一种串行接口USB所提供的功能是一致的。不过RS-232C显然已经开始被后起之秀USB赶超,因为USB的传输速率已经远远超过了RS-232C。尽管如此,RS-232C仍然具有非常广泛的应用,在相对长的一段时间里,难以被USB等接口取代。RS-232C接口(又称EIA RS-232C),1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定,全名是数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准。本文将对这一接口
3、进行硬件原理的介绍,随后我们将逐章学习DOS平台的串口编程,及Windows平台下基于API、控件和第三方类的串口编程,最后本文将给出一个综合实例。在本文的连载过程中,您可以通过如下方式联系作者(热忱欢迎读者朋友对本文的内容提出质疑或给出修改意见):作者email:21cnbao(可以来信提问,笔者将力求予以回信解答,并摘取其中的典型问题,在本系列文章最后一次连载的读者反馈中予以阐述);硬件原理众所周知,CPU与存储芯片和I/O芯片的通信是并行的(并行传输的最大位数依赖于CPU的字长、数据总线的宽度),一种叫做UART(通用异步收发器,Universal Asynchronous Receiv
4、er/Transmitter)的芯片提供了并行数据传输和RS-232C串行数据传输方式的转换。这样的设备通常有如图2所示的管脚分布,当其向外传输数据时,CPU并行的将数据写入这类芯片的寄存器,UART再将寄存器中的数据一位一位地移动并向外传输;当外界向其传输数据时,UART一位一位地接收数据,并将其移位组合为并行数据,CPU再并行地读取这些数据。实际上,由于UART芯片一般以TTL/CMOS电平工作,在UART连接接口之前,还要经过一个TTL/CMOS和RS-232C电平的转换。RS-232C规定了其标准的电气特性,逻辑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 数据载波检测DCD 8 数据载波检测 DCD2 接收数据 RXD 3 接收数据RXD3 发送数据TXD2 发送数据 TXD4 数据终端准备 DTR 20 数据终端准备 DTR5 信号地 GND 7 信号地 GND6 数据设备准备
6、好DSR6 数据准备好DSR7 请求发送RTS 4 请求发送 RTS8 清除发送 CTS 5 清除发送CTS9 振铃指示DELL22 振铃指示DELLRS-232C定义为数据通信设备(DCE)和数据终端设备(DTE)之间的互连,实现上,到现在为止,究竟一个设备属于DCE还是属于DTE已经没有明显的界限,PC即可作为DCE,又可作为DTE。两串口互连,连接方法主要有二:一种方法是,数据的发送和接收由软件控制,不进行硬件握手,其连接方法如图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)两个字符来实现流控制。前者用于请求对方暂停发送,后者用于清除暂停传送的请求,继续发送数据。另一种方法是,数据的发送和接收由硬件控制,进行硬件握手,其连接方法如图6(最常用DB9连接示意),需要连接的信号除RXD、TXD和GND外,还包括DTR、DSR、RTS和CTS。硬件握手依赖于RTS和CTS信号,当发送设备欲发送数据时,将RTS信号置为有效表示请求发送,接收设备准备好后,置CTS信号有效,接着发送
8、设备通过信号线TXD开始发送串行数据。这里我们联想开来,RTS/CTS模式在许多领域里都出现过。回忆一下IEEE 802.11无线局域网协议标准,在其MAC协议中就使用了RTS/CTS,RTS/CTS抽象开来就是一种请求/应答。笔者曾经在拙作中多次以实例论证计算机领域里许多知识的相通性,这又是一个明证。图6 有硬件握手时两串口连接实际上,目前我们经常使用的是方法一,即只连接RXD、TXD和GND,简单灵活。另外,串口之间互连还有诸多途径,如图7所示。图7 其它互连方式调试工具在MS-DOS下使用的编程环境是TC 2.0;在Windows 2000下的编程环境是VC+ 6.0;借助工具:串口调试
9、助手2.1(图8)。图8 串口调试助手串口调试助手是由Visual C+/Turbo C串口通信编程实践一书作者龚建伟编写的共享软件,可以方便地进行串口上的数据收发、显示(16进制和ASCII码方式)和串口参数的设置,在串口调试领域应用广泛。串口调试助手的开发原理很简单(相信读者看完本文后在相当短的时间之内就能开发出这样的软件),但是作者龚建伟敏锐地抓住了串口调试在业界的需求,使得自身随这一软件而成名。这一事件或多或少会给程序员们一定的启发。优秀的共享软件不一定要技术含量高,只要有需求,哪怕是开发原理再简单,都能拥有广泛的使用者。为了在一台PC上同时搭建DOS和Windows平台,我们应该在W
10、indows平台上安装虚拟PC的软件VmWare(图9,VMware Inc.版权所有,)。VMware的确是天才的作品!在同一PC上,利用VmWare几乎可以安装所有的操作系统,而且操作系统之间的切换不需要重新启动电脑,与传统的LILO等多系统引导方式有本质的不同。VM的意义是Virtual Machine,即虚拟出一个逻辑的电脑。图9 VmWare虚拟PC在虚拟PC的MS-DOS操作系统上,我们安装TC 2.0开发环境。如果您的PC上没有软驱,为了制作MS-DOS启动软盘,请安装RamDiskNT模拟一个软盘,并在其上安装MS-DOS启动程序。RamDiskNT是一个磁盘模拟软件,其界面如
11、图10所示。图10 磁盘模拟深入浅出VC+串口编程之DOS的串口编程在DOS平台下,操作串口主要有下列方式:通过BIOS调用、通过串口的硬件中断或通过对串口硬件进行轮询,本章将对以上三种方式进行具体的介绍并给出例子。1.BIOS中断在DOS操作系统下,IBM PC及其兼容机提供了一种灵活的串口I/O访问方法,即通过INT 14H调用ROM BIOS串行通讯例行程序。当设置AH为不同的值时,产生不同的功能:AH 0 初始化端口AH 1 向串口写字符AH 2 从串口读字符AH 3 取通讯口状态初始化端口时(即当AH0时),需要在AL寄存器中赋一字节初始化参数,其各项意义如图1;图1 调用INT 1
12、4H时AL寄存器设置当向串口写字符时(即当AH1时),AL寄存器中的字符是需要写入的字符;当向串口写字符时(即当AH2时),AL寄存器中的字符是需要读取的字符。看看下面的例程:#include #include #include #define STR author:sbhunion REGS inregs,outregs;main() /设置串口参数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;/发送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函数的原型为:
14、int _Cdecl int86(int intno, union REGS *inregs, union REGS *outregs);int86()函数可以调用BIOS功能,现在的程序员们已经很少接触这个函数,80%的程序员甚至都未曾见过这个函数。其实,在茹毛饮血的DOS时代,int86()函数几乎是最常用和最核心的函数之一。几乎可以说,在那个时代,不会int86()就等于不会编程。而与int86配合使用的,就是REGS这样一个联合体,定义为: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处理器内部的寄存器啊!因此,当CPU发展到286、386以后,再安装DOS也是建立在利用CPU实模式的基础上的!另外一个函数与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这两个函数的功能都是执行一个由参数intno指定的8086软中断。在执行软中断之前,两个函数都把inregs中的内容放置到各寄存器中(int86x还把segregs.x.es和segregs.x.ds的值存到相应的段寄存器中),软中断返回后,这两个函数都把当前寄存器的值存到outregs,并把
17、系统进位标志拷贝到outregs.s.cflag中,把8086标志寄存器值存到outregs.x.flag中(int86x还恢复DS,并设置Segregs.es和Segregs.ds的值为对应段寄存器的值)。查阅BIOS中断调用手册,发现绝大多数调用都未用到ES和DS段寄存器,故在程序设计中经常只利用了int86函数。2.硬件中断为了给读者一个直观的印象,我们通过在Windows操作系统中查看COM的资源属性获得某COM对应的中断号,如图2(该对话框中设备管理器中开启)。图2 COM中断号实际上COM的确直接对应于一个中断,而系统也按照一定的规律为各类硬件分配了一个较固定的中断号,如表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对应的中断服务程序,我们也可以操作串口,涉及到的相关函数有:(1)设置中断向量表/*dos.h*/void _Cdecl setvect (int interruptno, void interrupt (*isr) ();例如,COM3对应的中断号是4,那么对应中断向量表中的地址是0x0C,设置0x0C对应中断程序的函数为: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。持续的检查UART,以便能在一次中断里读取所有可获得的数据。最后的outportb(0x20,0x20);语句告诉可编程中断控制器(Programmable Interrupt Controller,PIC)中断已经
21、完成。(2)读取中断向量表/*dos.h*/void interrupt (* _Cdecl getvect(int interruptno) ();例如:oldport1isr = getvect(INTVECT); 其中的oldport1isr定义为:void interrupt (*oldport1isr)();我们融合setvect()函数、中断服务程序和getvect()函数,给出一个由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对应的硬件端口,我们可以控制串口的收发。请看下面的例子:/* 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可以判断是否有数据被UART接收到。关于UART对应的端口范
34、围,从图2中也可以直观地看出。深入浅出VC+串口编程之基于Win32 API1、API描述在WIN32 API中,串口使用文件方式进行访问,其操作的API基本上与文件操作的API一致。打开串口Win32 中用于打开串口的API 函数为CreateFile,其原型为:HANDLE CreateFile (LPCTSTR lpFileName, /将要打开的串口逻辑名,如COM1 或COM2DWORD dwAccess, /指定串口访问的类型,可以是读取、写入或两者并列DWORD dwShareMode, /指定共享属性,由于串口不能共享,该参数必须置为0LPSECURITY_ATTRIBUTES
35、 lpsa, /引用安全性属性结构,缺省值为NULLDWORD dwCreate, /创建标志,对串口操作该参数必须置为OPEN EXISTINGDWORD dwAttrsAndFlags, /属性描述,用于指定该串口是否可进行异步操作,/FILE_FLAG_OVERLAPPED:可使用异步的I/OHANDLE hTemplateFile /指向模板文件的句柄,对串口而言该参数必须置为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参数及FILE_FLAG_OVERLAPPED标志的由来,可解释如下:Windows文件操作分为同步I/O和重叠I/O(Overlapped I/ O)两种方式,在同步I/O方式中,API会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而在重叠I/O方式中,API会立即返回,操作在后台进行,避
37、免线程的阻塞。重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。如果进行I/O操作的API 在没有完成操作的情况下返回,我们可以通过调用GetOverLappedResult()函数阻塞到I/O操作完成后返回。配置串口配置串口是通过改变设备控制块DCB(Device Control Block) 的成员变量值来实现的,接收缓冲区和发送缓冲区的大小可通过SetupComm函数来设置。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函数的原型则为:BOOL SetupComm(HANDLE hFile, / handle to communications devi
42、ceDWORD dwInQueue, / size of input bufferDWORD dwOutQueue / size of output buffer);以下程序将串口设置为:波特率为9600,数据位数为7位,停止位为2 位,偶校验,接收缓冲区和发送缓冲区大小均为1024个字节,最后用PurgeComm函数终止所有的后台读写操作并清空接收缓冲区和发送缓冲区:DCB dcb;dcb.BaudRate = 9600; /波特率为9600dcb.ByteSize = 7; /数据位数为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结构体的成员变量值来实现的,COMMTIMEOUTS的原型为:typedef struct _COMMTIMEOUTSDWORD ReadInterval
44、Timeout; /定义两个字符到达的最大时间间隔,单位:毫秒/当读取完一个字符后,超过了ReadIntervalTimeout,仍未读取到下一个字符,就会/发生超时DWORD ReadTotalTimeoutMultiplier; DWORD ReadTotalTimeoutConstant;/其中各时间所满足的关系如下:/ReadTotalTimeout = ReadTotalTimeOutMultiplier* BytesToRead + ReadTotalTimeoutConstantDWORD WriteTotalTimeoutMultiplier;DWORD WriteTotalT
45、imeoutConstant; COMMTIMEOUTS, *LPCOMMTIMEOUTS;设置超时的函数为SetCommTimeouts,其原型中接收COMMTIMEOUTS的指针为参数:BOOL SetCommTimeouts(HANDLE hFile, / handle to communications deviceLPCOMMTIMEOUTS lpCommTimeouts / pointer to comm time-out structure);以下程序将串口读操作的超时设定为10 毫秒:COMMTIMEOUTS to;memset(&to, 0, sizeof(to);to.Re
46、adIntervalTimeout = 10;SetCommTimeouts(hCom, &to);与SetCommTimeouts对应的GetCommTimeouts()函数的原型为:BOOL GetCommTimeouts(HANDLE hFile, / handle of communications deviceLPCOMMTIMEOUTS lpCommTimeouts / pointer to comm time-out structure);事件设置在读写串口之前,需要用SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为:BOOL SetCommMas
47、k(HANDLE hFile, /标识通信端口的句柄DWORD dwEvtMask /能够使能的通信事件);有了Set当然还会有Get,与SetCommMask对应的GetCommMask()函数的原型为:BOOL GetCommMask(HANDLE hFile, /标识通信端口的句柄LPDWORD lpEvtMask / address of variable to get event mask);串口上可以发生的事件可以是如下事件列表中的一个或任意组合:EV_BREAK、EV_CTS、EV_DSR、EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV
48、_TXEMPTY。我们可以用WaitCommEvent()函数来等待串口上我们利用SetCommMask ()函数设置的事件:BOOL WaitCommEvent(HANDLE hFile, /标识通信端口的句柄LPDWORD lpEvtMask, / address of variable for event that occurredLPOVERLAPPED lpOverlapped, / address of overlapped structure);WaitCommEvent()函数一直阻塞,直到串口上发生我们用所SetCommMask ()函数设置的通信事件为止。一般而言,当Wai
49、tCommEvent()返回时,程序员可以由分析*lpEvtMask而获得发生事件的类别,再进行相应的处理。读串口对串口进行读取所用的函数和对文件进行读取所用的函数相同,读函数原型如下: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);写串口对串口进行写入所用的函数和对文件进行写入所用的函数相同,写函数原型如下: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 函数实现串口通信时关闭串口非常简单,只需使用CreateFile 函数返回的句柄作为参数调用CloseHandle 即可:BOOL CloseHandle(HANDLE hObject / handle to object to close);2.例程在笔者的深入浅出Win32多线程程序设计之综合实例中我们已经给出一个利用WIN API进行串口通信的例子,这里再给出一个类似的例子,以进一步加深理解。对话框上控件对应的资源文件(.RC)中的内容如下:BEGINEDITTEXT IDC_RECV_EDIT,28,1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024门面施工现场管理及应急预案合同3篇
- 2024年货物出口合同标的及出口规格
- 2024年社区羽毛球馆租赁协议3篇
- 2024汽车租赁公司新能源车辆推广合同
- 2024年限定版房产市场调研与营销策划服务协议版B版
- 2024年跨界合作居间协议书
- 2024年铁路轨道焊接分包商协议
- 2025年度餐厅与旅行社联合运营美食旅游项目合同3篇
- 2024版铁路安全协议书
- 职业学院工会评优评先实施办法
- 新能源发电技术 课件 第6章 地热发电
- 期末测试卷(试题)-2024-2025学年人教PEP版(2024)英语三年级上册
- 2024至2030年中国购物商场行业市场深度调查与投资发展研究报告
- 期末测试(试题)2023-2024学年五年级上册数学人教版
- 二年级上册数学两位数加减竖式计算题100道及答案
- 《天然药物学基础》复习考试题库(带答案)
- 湖北省2024年中考数学试卷【附真题答案】
- 德国高等工程教育认证制度研究
- 2024年四川省成都市中考数学试卷(含解析)
- 【人民日报】72则金句期末评语模板-每页4张
- 零缺陷质量意识
评论
0/150
提交评论