串口编程学习笔记,从入门到精通.pdf

上传人:qwe****56 文档编号:70023389 上传时间:2023-01-14 格式:PDF 页数:44 大小:393.78KB
返回 下载 相关 举报
串口编程学习笔记,从入门到精通.pdf_第1页
第1页 / 共44页
串口编程学习笔记,从入门到精通.pdf_第2页
第2页 / 共44页
点击查看更多>>
资源描述

《串口编程学习笔记,从入门到精通.pdf》由会员分享,可在线阅读,更多相关《串口编程学习笔记,从入门到精通.pdf(44页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、串口编程串口编程串口编程串口编程学习笔记学习笔记学习笔记学习笔记 作者:林国树 1.串口定义串口定义串口定义串口定义 串口即串行通信接口,它是 PC 与通信工业应用比较广泛的一种接口,主要是 RS-232。它被定义为一种在低速率串行通信中增加通信距离的单端标准。RS-232 采用不平衡传输方式。一个完整的 RS-232 接口有 22 根线,采用标准 25 芯插座头(DB-25)。除此,目前广泛使用一种 9 芯的 RS-232 接口(DB-9),如图 1 所示。其各个引脚及其信号如表 1,表 2。图 1 RS-232 接头形式 表 1 RS-232 DB-25 引脚定义 引 脚 号 缩 写 符

2、信 号 方 向 说 明 1 PE 公共端 连接器外壳 2 TXD 输出 发送数据 3 RXD 输入 接收数据 4 RTS 输出 请示发送 5 CTS 输入 清除发送 6 DSR 输入 数据设备准备好 7 SG 公共端 信号地 8 DCD 输入 载波检测 9 保留 10 保留 11 STF 输出 选择传送通道 12 DCD 输入 载波检测 13 CTS 输入 清除发送 14 TXD 输出 发送数据 15 TCK 输入 发送时钟 16 RXD 输入 接收数据 17 RCK 输入 接收器定时 18 LL 输出 本地回路控制 19 RTS 输出 请示发送 20 DTR 输出 数据终端准备好 21 RL

3、 输出 远程回路控制 22 RI 输入 振铃指示器 23 DSR 输入 数据装置准备好 24 XCK 输出 发送器定时 25 TI 输入 测试指示器 表 2 RS-232 DB-9 引脚定义 引 脚 号 缩 写 符 信 号 方 向 说 明 1 DCD 输入 载波检测 2 RXD 输入 接收数据 3 TXD 输出 发送数据 4 DTR 输出 数据终端准备好 5 GND 公共端 信号地 6 DSR 输入 数据装置准备好 7 RTS 输出 请示发送 8 CTS 输入 清除发送 9 RI 输入 振铃指示 在 RS-232 标准中规定的设备可以分为数据终端设备(DTE)和数据通信设备(DCE)两类,这种

4、分类定义了不同的线路用来发送和接收信号。一般来说,计算机和终端设备有 DTE连接器,调制解调器和打印机有 DCE 连接器。RS-232 标准中指定了 20 个不同的信号连接,由 25 个 D-sub(微型 D 类)引脚构成的 DB-25连接器。但很多设备只用其中的一小部分引脚,出于节省资金和空间的考虑不少机器采用较少的连接器,特别是 9 引脚的 D-sub 或者 DB-9 型连接器被广泛使用。因为 RS-232 到目前为止经历很多不同版本,最近版本为 E,它相对于广泛使用的 C 版本来说,电气性能改进了不少,也对连接器中的 25 个引脚进行了充分利用(只有 2 个予以保留)。在 RS-232C

5、 版本中,DB-25 的 25 个引脚(4 个数据引脚、11 个控制信号引脚、3 个定时引脚、7 个备用和未定义引脚)。实际上只用到表 1 中的 9 个,分别是:1、2、3、4、5、6、8、20、22 脚,它们的作用如下:(1)控制信号线(4、5、6、8、20、22 等 6 个引脚)?数据装置准备好(Data Set Ready,DSR):有效(ON)状态表明接口处于可以使用状态;?数据终端准备好(Data Terminal Ready,DTR):有效时(ON)状态,表明数据终端可以使用;这两个信号有时连到电源上,一上电就立即有效。但这两个设备状态信号有效,只表示设备本身可用,并不说明通信链路

6、可以开始进行通信了,能否开始进行通信要由下面的控制信号决定。?请求发送(Request To Send,RTS):用来表示 DTE 请求 DCE 发送数据,即当终端要发送数据时,使该信号有效(ON),向 DTE 设备请求发送;?允许发送(Clear To Send,CTS):用来表示 DCE 准备好接受 DTE 发来的数据,是对发送信号 RTS 的响应信号。当 MODEM 之类设备已准备好接收终端传来的数据并向前发送时,使该信号有效,通知终端开始沿发送数据线TxD发送数据。这对 RTS/CTS 请求应答联络信号是用于半双工 MODEM 系统中发送方式和接收方式之间的切换。在全双工系统中作发送方

7、式和接收方式之间的切换。在全双工系统中,因配置双向通道,故不需要 RTS/CTS 联络信号使其变高;?数据载波检出(Data Carrier Dectection,DCD):也叫“接收线信号检出”(Received Line Dectection,RLSD),用来表示 DCE 已接通通信链路,告知DTE 准备接收数据。当本地的 MODEM 收到由通信链路另一端(远地)的MODEM 送来的载波信号时,使 RLSD 信号有效,通知终端准备接收,并且由MODEM 将接收下来的载波信号解调成数字数据后,沿接收数据线 RxD 送到终端;?振铃指示(Ringing,RI):当 MODEM 收到交换台送来的

8、振铃呼叫信号时,使该信号有效(ON 状态),通知终端,已被呼叫;(2)数据发送和接收线(2、3 引脚)?发送数据(Transmitted Data,TxD):通过 TxD 终端将串行数据发送到MODEM,(DTEDCE);?接收数据(Received Data,RxD):通过 RxD 线终端接收从 MODEM 发来的串行数据,(DCEDTE)(3)地线?SG(7 脚)、PE(1 脚)分别用来接信号地和保护地信号线,无方向 上述控制信号线何时有效,何时无效的顺序表示了接口信号的传送过程。例如,只有当DSR 和 DTR 都处于有效(ON)状态时,才能在 DTE 和 DCE 间传送操作。若 DTE

9、要发送数据,则预先将 DTR 线置成有效(ON)状态,等 CTS 线上收到有效(ON)状态的回答后,才能在TxD 线上发送串行数据。这种顺序的规定对半双工的通信线路特别有用,因为只有半双工的通信能确定 DCE 已由接收方向改为发送方向,这时线路才能开始发送。使用 DB-9 连接器,作为提供多功能 I/O 卡或主板上 COM1 和 COM2 两个串行接口的连接器,它只提供异步通信的 9 个信号。DB-25 型连接器的引脚分配与 DB-25 型引脚信号完全不同。因此,若与配接 DB-25 型连接器的 DCE 设备连接,必须使用专门的电缆线。在连接距离上,如果通信速率低于 20kbit/s 时,RS

10、-232 所直接连接的最大物理距离为15m。2.Windows 下串口编程方式下串口编程方式下串口编程方式下串口编程方式 在 windows 操作系统下,串口通信的编程可以在 wince、win32 或者 dot net 下实现。2.1 win32 方式方式方式方式(Serial Communications in Win32)简介简介简介简介 串口通信的主要步骤为:打开串口,设置串口参数,读/写串口,关闭串口等四步。串口编程主要是 win32 API 的应用,在 windows 操作系统中,把串口看作是一种文件,对串口的操作也是对一种文件的操作,只不过这种文件需要作一些特殊的设置,以及有特定

11、的操作步骤,以下介绍其具体的过程和用到的 API。打开串口打开串口打开串口打开串口 用 CreateFileCreateFileCreateFileCreateFile 函数打开通信串口。打开串口有俩种方式:重叠和非重叠。下面的代码演示了以重叠方式打开串口:HANDLE hComm;hComm=CreateFile(gszPort,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);if(hComm=INVALID_HANDLE_VALUE)/串口没有打开,中止操作 取消标识 FILE_FLAG_OVE

12、RLAPPED,即用 NULL 方式调用 CreateFileCreateFileCreateFileCreateFile 就指定非重叠方式。重叠与非重叠方式在下一节介绍。SDK 文档中对串口通信的 CreateFileCreateFileCreateFileCreateFile 调用有以下特殊要求:fdwShareMode 必须为 0。通信串口不能共享,只能独占。fdwCreate 必须指定为 OPEN_EXISTING。hTemplateFile 必须为 NULL。注意:串口的名字为 COM1,COM2,COM3,或者 COM4。但 Win32 API 并不提供检测串口存在的机制。用户可以

13、自由指定要使用的串口名字,如果串口不存在,打开串口的操作时,系统会返回一个错误标识(ERROR_FILE_NOT_FOUND)。读读读读/写串口写串口写串口写串口 Win32 的读/写串口操作与文件操作的输入/输(I/O)出类似,实际上它们使用的是同样的函数。Win32 的串口 I/O 操作有两种方式:重叠或者非重叠。即文件操作里的同步和异步,在本笔记里,我们用重叠和非重叠。多数开发人员都熟悉非重叠方式 I/O,即一个操作完成以后函数才返回。而重叠方式 I/O调用函数会立即返回,不管操作有没有完成。但是操作完成后操作系统会有信号发送给调用者。用这种方式程序可以在 I/O 要求后和完成之前这段时

14、间干别的工作。读/写串口操作包括很多功能和选择,以下详细介绍:非重叠非重叠非重叠非重叠 I/O 非重叠 I/O 有些限制,但很直观。当一个操作发生时,线程会阻塞,直到这个操作函数返回,该线程才会继续工作。这种 I/O 方式适合于多线程,因为一个线程在 I/O 操作阻塞后,其他类型的线程还可以继续工作。应用程序的责任是安排好串口的访问顺序,避免一个线程阻塞了,其他的线程在等待这个线程函数返回结果也被阻塞。例如,一个线程读操作(ReadFileReadFileReadFileReadFile)没有完成,那么其他线程的写操作(WriteFileWriteFileWriteFileWriteFile)

15、就会被阻塞。选择非重叠方式的主要原因是可移植性,因为多数系统不支持重叠方式,但多数系统都支持多线程,所以多线程非重叠 I/O 是可移植性的最好选择。重叠重叠重叠重叠 I/O 重叠 I/O 不如非重叠 I/O 那样直观,但更灵活和有效。用重叠方式打开一个串口允许多线程多个线程同时操作,而且重叠操作还允许同一个线程对一个串口同时执行多种不同的操作。重叠 I/O 的优点在于线程可以在 I/O 操作的申请和结束之间这段时间最别的工作。重叠 I/O操作有俩个部分:请求开始和完成检测,请求开始设置 OVERLAPPEDOVERLAPPEDOVERLAPPEDOVERLAPPED 结构,设置同步重置事件,然

16、后调用读/写操作。I/O 操作可能不能立即完成。如果立即完成,应用程序可以准备正常继续处理,否则重叠 I/O 提供检测机制,检测方法包括等待事件句柄,然后获取数据。有许多错误标识标明错误结果,如创建失败,超时或者等待别的事件完成信号。读操作读操作读操作读操作 读操作使用 ReadFileReadFileReadFileReadFile 函数。以下代码给出读串口的一个例子,代码中定义 fWaitingOnRead标志用于在重叠操作中,如果一个操作正在进行,阻止其他新的操作。DWORD dwRead;BOOL fWaitingOnRead=FALSE;OVERLAPPED osReader=0;/

17、创建重叠事件,退出程序前必须关闭其句柄,防止内存泄露 osReader.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(osReader.hEvent=NULL)/错误创建重叠事件,程序终止。if(!fWaitingOnRead)/开始读操作 if(!ReadFile(hComm,lpBuf,READ_BUF_SIZE,&dwRead,&osReader)if(GetLastError()!=ERROR_IO_PENDING)/立即读?/通信错误,报告 else fWaitingOnRead=TRUE;else /读立即完成 HandleASuccess

18、fulRead(lpBuf,dwRead);重叠操作的第二部分是检测是否完成。事件句柄在信号标识时通过 WaitForSingleObjectWaitForSingleObjectWaitForSingleObjectWaitForSingleObject 函数返回给 OVERLAPPEDOVERLAPPEDOVERLAPPEDOVERLAPPED 结构。一旦事件被标识,操作就完成。但这并不表明操作成功,它只是表明操作完成。GetOverlappedResultGetOverlappedResultGetOverlappedResultGetOverlappedResult 函数报告操作结果,

19、如果有错误发生,GetOverlappedResultGetOverlappedResultGetOverlappedResultGetOverlappedResult 返回 FALSE,而 GetLastErrorGetLastErrorGetLastErrorGetLastError 返回错误代码。如果操作成功完成,GetOverlappedResultGetOverlappedResultGetOverlappedResultGetOverlappedResult 返回 TRUE。以下代码给出检测重叠方式读操作完成的一个实例。注意,代码在操作立即完成时也调用同样的函数处理数据。#defi

20、ne READ_TIMEOUT 500 /毫秒 DWORD dwRes;if(fWaitingOnRead)dwRes=WaitForSingleObject(osReader.hEvent,READ_TIMEOUT);switch(dwRes)/读完成 case WAIT_OBJECT_0:if(!GetOverlappedResult(hComm,&osReader,&dwRead,FALSE)/通信错误,报告 else /读完成 HandleASuccessfulRead(lpBuf,dwRead);/重设标识用于开始另一个操作 fWaitingOnRead=FALSE;break;ca

21、se WAIT_TIMEOUT:/操作还没完成,fWaitingOnRead 标识没有改变,在第一个操作完 /成前不打算改变,这时是做其他后台工作的时候 break;default:/WaitForSingleObject 错误,程序终止 /这表明 OVERLAPPED 结构有错误事件句柄 break;写操作写操作写操作写操作 从通信串口转换数据与读操作类似。以下代码给出开始和等待写操作完成的一个例子。BOOL WriteABuffer(char*lpBuf,DWORD dwToWrite)OVERLAPPED osWrite=0;DWORD dwWritten;DWORD dwRes;BOO

22、L fRes;/创建写操作 OVERLAPPED 结构的 hEvent.osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(osWrite.hEvent=NULL)/创建重叠事件句柄失败 return FALSE;/开始写 if(!WriteFile(hComm,lpBuf,dwToWrite,&dwWritten,&osWrite)if(GetLastError()!=ERROR_IO_PENDING)/WriteFile 失败,但没有延时,报告错误,程序终止 fRes=FALSE;else /正在写 dwRes=WaitForSingle

23、Object(osWrite.hEvent,INFINITE);switch(dwRes)/OVERLAPPED 结构事件被标识 case WAIT_OBJECT_0:if(!GetOverlappedResult(hComm,&osWrite,&dwWritten,FALSE)fRes=FALSE;else /写操作成功完成 fRes=TRUE;break;default:/WaitForSingleObject 有错误发生,这通常表明 /OVERLAPPED 结构事件句柄有问题 fRes=FALSE;break;else /WriteFile 立即完成 fRes=TRUE;CloseHan

24、dle(osWrite.hEvent);return fRes;注意 WaitForSingleObjectWaitForSingleObjectWaitForSingleObjectWaitForSingleObject 函数用超时值 INFINITE,这样 WaitForSingleObjectWaitForSingleObjectWaitForSingleObjectWaitForSingleObject 函数会一直等到操作完成,这样可能会阻塞线程。以下是上面的等价代码,但不会引起线程阻塞。BOOL WriteABuffer(char*lpBuf,DWORD dwToWrite)OVER

25、LAPPED osWrite=0;DWORD dwWritten;BOOL fRes;/创建写 OVERLAPPED 结构的 hEvent.osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(osWrite.hEvent=NULL)/创建句柄出错 return FALSE;/开始写 if(!WriteFile(hComm,lpBuf,dwToWrite,&dwWritten,&osWrite)if(GetLastError()!=ERROR_IO_PENDING)/写失败,但不延时,报告错误,终止程序 fRes=FALSE;else /写 i

26、f(!GetOverlappedResult(hComm,&osWrite,&dwWritten,TRUE)fRes=FALSE;else /写操作成功完成 fRes=TRUE;else /WriteFile 立即完成 fRes=TRUE;CloseHandle(osWrite.hEvent);return fRes;GetOverlappedResultGetOverlappedResultGetOverlappedResultGetOverlappedResult 并不是等待重叠操作完成的最好方式如果应用程序要等待其他句柄,那么第一种方式比第二种方式好,只要把 WaitForSingleO

27、bjectWaitForSingleObjectWaitForSingleObjectWaitForSingleObject 换成WaitForMultipleObjectsWaitForMultipleObjectsWaitForMultipleObjectsWaitForMultipleObjects 就好。在串口通信中 OVERLAPPEDOVERLAPPEDOVERLAPPEDOVERLAPPED 结构中需要设置的成员只有 hEventhEventhEventhEvent,其他的设为 0,或者不用管它。其他类型的资源则需要设置其他成员,如文件操作需要设置 OffsetOffsetOff

28、setOffset 和 OffsetHighOffsetHighOffsetHighOffsetHigh。串口状态串口状态串口状态串口状态 有俩种方法可以获得串口通信的状态。方法一是设置一个事件掩码,然后等待系统返回此事件。SetCommMaskSetCommMaskSetCommMaskSetCommMask 函数设置事件掩码,WaitCommEventWaitCommEventWaitCommEventWaitCommEvent 函数等待系统返回特定事件;方法二是定期查询串口状态。不推荐使用方法二,因为这种方法效率比较低。以下是 SetCommMaskSetCommMaskSetCommM

29、askSetCommMask 函数的应用例子:DWORD dwStoredFlags;dwStoredFlags=EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;if(!SetCommMask(hComm,dwStoredFlags)/设置通信掩码出错。表 1 是 msdn 对掩码标识的说明 Event Flag Description EV_BREAK A break was detected on input.EV_CTS The CTS(clear-to-send)signal ch

30、anged state.To get the actual state of the CTS line,GetCommModemStatus should be called.EV_DSR The DSR(data-set-ready)signal changed state.To get the actual state of the DSR line,GetCommModemStatus should be called.EV_ERR A line-status error occurred.Line-status errors are CE_FRAME,CE_OVERRUN,and CE

31、_RXPARITY.To find the cause of the error,ClearCommError should be called.EV_RING A ring indicator was detected.EV_RLSD The RLSD(receive-line-signal-detect)signal changed state.To get the actual state of the RLSD line,GetCommModemStatus should be called.Note that this is commonly referred to as the C

32、D(carrier detect)line.EV_RXCHAR A new character was received and placed in the input buffer.See the Caveat section below for a discussion of this flag.EV_RXFLAG The event character was received and placed in the input buffer.The event character is specified in the EvtChar member of the DCB structure

33、 discussed later.The Caveat section below also applies to this flag.EV_TXEMPTY The last character in the output buffer was sent to the serial port device.If a hardware buffer is used,this flag only indicates that all data has been sent to the hardware.There is no way to detect when the hardware buff

34、er is empty without talking directly to the hardware with a device driver.指定事件掩码后,用 WaitCommEventWaitCommEventWaitCommEventWaitCommEvent 函数检测事件的发生。如果串口以非重叠方式打开,WaitCommEventWaitCommEventWaitCommEventWaitCommEvent 不包含 OVERLAPPEDOVERLAPPEDOVERLAPPEDOVERLAPPED 结构。线程将会阻塞,直到等待的事件发生,如果此事件不发生,那么线程将会永远阻塞。以下

35、以非重叠方式等待 EV_RING 事件:DWORD dwCommEvent;if(!SetCommMask(hComm,EV_RING)/设置通信掩码出错 return FALSE;if(!WaitCommEvent(hComm,&dwCommEvent,NULL)/等待事件出错 return FALSE;else /事件发生 return TRUE;如果等待事件没有发生,以上代码会永远阻塞线程,更好的解决方案是以重叠方式打开串口,然后等待系统通知,如下:#define STATUS_CHECK_TIMEOUT 500 /Milliseconds DWORD dwRes;DWORD dwCom

36、mEvent;DWORD dwStoredFlags;BOOL fWaitingOnStat=FALSE;OVERLAPPED osStatus=0;dwStoredFlags=EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;if(!SetCommMask(comHandle,dwStoredFlags)/设置掩码出错 return 0;osStatus.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(osStatus.hEvent=NULL)/创建

37、事件出错 return 0;for(;)/开始事件检查 if(!fWaitingOnStat)if(!WaitCommEvent(hComm,&dwCommEvent,&osStatus)if(GetLastError()=ERROR_IO_PENDING)bWaitingOnStatusHandle=TRUE;else /WaitCommEvent 出错 break;else /WaitCommEvent 完成后立即返回 ReportStatusEvent(dwCommEvent);/Check on overlapped operation.if(fWaitingOnStat)/等待事件发

38、生 dwRes=WaitForSingleObject(osStatus.hEvent,STATUS_CHECK_TIMEOUT);switch(dwRes)/事件发生 case WAIT_OBJECT_0:if(!GetOverlappedResult(hComm,&osStatus,&dwOvRes,FALSE)/重叠操作错误发生时,调用 GetLastError 获得原因 else /事件状态存在事件标识中,用 WaitCommEvent 标明 ReportStatusEvent(dwCommEvent);/设置继续其他线程的标识 fWaitingOnStat=FALSE;break;c

39、ase WAIT_TIMEOUT:/操作没有完成,超时 /现在是做后台工作的时候 DoBackgroundWork();break;default:/WaitForSingleObject 出错 /表明 OVERLAPPED 结构有出错标识 CloseHandle(osStatus.hEvent);return 0;CloseHandle(osStatus.hEvent);SetCommMaskSetCommMaskSetCommMaskSetCommMask 和 WaitCommEventWaitCommEventWaitCommEventWaitCommEvent 有两方面的影响。第一,如

40、果串口以非重叠方式打开,WaitCommEventWaitCommEventWaitCommEventWaitCommEvent 在事件发生前线程会阻塞,如果另一个线程调用 SetCommMaskSetCommMaskSetCommMaskSetCommMask 设置新的掩码,那么线程会在 SetCommMaskSetCommMaskSetCommMaskSetCommMask 上面阻塞。第二,如果以重叠方式打开串口,SetCommMaskSetCommMaskSetCommMaskSetCommMask 设置事件掩码,WaitCommEventWaitCommEventWaitCommEve

41、ntWaitCommEvent 会立即成功返回,但是事件掩码操作是空的(NULL)错误处理和通信状态错误处理和通信状态错误处理和通信状态错误处理和通信状态 SetCommMaskSetCommMaskSetCommMaskSetCommMask 设置的掩码 EV_ERR 发生表明串口出错,但有时其他的错误不会引起 EV_ERR事件的发生。这两种情形下,串口 I/O 错误会挂起所有操作,直到发生错误的条件被清除。ClearCommErrorClearCommErrorClearCommErrorClearCommError 函数用于检查错误原因,并且清除错误条件。ClearCommErrorCl

42、earCommErrorClearCommErrorClearCommError 提供的通信状态表明传输停止的原因,它也可以显示串口中等待传输和读入内存中的字节数。传输停止的原因主要是流控制出错。以下代码显示如何使用 ClearCommErrorClearCommErrorClearCommErrorClearCommError:COMSTAT comStat;DWORD dwErrors;BOOL fOOP,fOVERRUN,fPTO,fRXOVER,fRXPARITY,fTXFULL;BOOL fBREAK,fDNS,fFRAME,fIOE,fMODE;/获取串口当前错误状态 if(!Cl

43、earCommError(hComm,&dwErrors,&comStat)return;/获取错误标识 fDNS=dwErrors&CE_DNS;fIOE=dwErrors&CE_IOE;fOOP=dwErrors&CE_OOP;fPTO=dwErrors&CE_PTO;fMODE=dwErrors&CE_MODE;fBREAK=dwErrors&CE_BREAK;fFRAME=dwErrors&CE_FRAME;fRXOVER=dwErrors&CE_RXOVER;fTXFULL=dwErrors&CE_TXFULL;fOVERRUN=dwErrors&CE_OVERRUN;fRXPARI

44、TY=dwErrors&CE_RXPARITY;/COMSTAT 结构包含通信状态 if(comStat.fCtsHold)/Tx 等待 CTS 信号 if(comStat.fDsrHold)/Tx 等待 DSR 信号 if(comStat.fRlsdHold)/Tx 等待 RLSD 信号 if(comStat.fXoffHold)/Tx 等待,XOFF 接收 if(comStat.fXoffSent)/Tx 等待,XOFF 发送 if(comStat.fEof)/EOF 接收 if(comStat.fTxim)/单字符等待 Tx;字符队列等待 TransmitCommChar if(comS

45、tat.cbInQue)/comStat.cbInQue 数据已经接收,但未读取 if(comStat.cbOutQue)/comStat.cbOutQue 数据等待传输 扩展函数扩展函数扩展函数扩展函数 在标准串口 RS-232 中,驱动程序会自动转化控制线的状态,但是其他非标准串口就需要有自己的驱动来控制状态,使用 EscapeCommFunctionEscapeCommFunctionEscapeCommFunctionEscapeCommFunction 实现非标准串口控制,具体使用方法请见 MSDN。串口设置串口设置串口设置串口设置(DCB)串口设置主要是对 DCB(Device-C

46、ontrol Block)结构的设置,串口通信经常出错的原因是没有正确设置 DCB,一旦串口通信不正常,检查 DCB 结构经常可以找到问题的所在。初始化 DCB结构有三种方法,第一种是调用 GetCommStateGetCommStateGetCommStateGetCommState 函数从串口中获得DCB结构数据,以下代码是 GetCommStateGetCommStateGetCommStateGetCommState 函数的使用例子:DCB dcb=0;if(!GetCommState(hComm,&dcb)/获取 DCB 结构出错 else /DCB 可用 第二种方法是调用 Buil

47、dCommDCBBuildCommDCBBuildCommDCBBuildCommDCB 函数初始化 DCB 结构。这个函数只填充 baud,parity,stopbits 等成员,其他的流控制成员使用缺省值。以下代码示例如何使用这种方法:DCB dcb;FillMemory(&dcb,sizeof(dcb),0);dcb.DCBlength=sizeof(dcb);if(!BuildCommDCB(9600,n,8,1,&dcb)/不能创建 DCB.通常是字符串出了问题 return FALSE;else /DCB 可用.第三种方法是手动设置 DCB 结构,这种方法是申请 DCB 结构内存,

48、然后设置每一个成员值,这种方法经常会出错,所以不推荐。应用程序经常只是设置部分成员,而其他的成员则使用默认值,或者根本就不需要改变其设置,最好的做法是先获取当前的 DCB,然后改变部分成员值,使用 SetCommStateSetCommStateSetCommStateSetCommState 函数通知串口状态改变。以下代码获取当前 DCB 结构,改变 baud,然后配置串口状态:DCB dcb;FillMemory(&dcb,sizeof(dcb),0);if(!GetCommState(hComm,&dcb)/取得当前 DCB /GetCommState 出错 return FALSE;/

49、更改 DCB 速率 dcb.BaudRate=CBR_9600;/Set new state.if(!SetCommState(hComm,&dcb)/SetCommState 出错.可能是通信句柄出错,或者 DCB 结构本身出错 以下是 MSDN 对 DCB 结构的说明 表表表表 2.DCB2.DCB2.DCB2.DCB 结构成员结构成员结构成员结构成员 Member Description DCBlength Size,in bytes,of the structure.Should be set before calling SetCommState to update the sett

50、ings.BaudRate Specifies the baud at which the communications device operates.This member can be an actual baud value,or a baud index.fBinary Specifies whether binary mode is enabled.The Win32 API does not support nonbinary mode transfers,so this member should be TRUE.Trying to use FALSE will not wor

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁