C++:串口通信之使用windows系统提供的串行口API函数
利用Visual C在windows环境下设计异步串行通信程序可以使用不同的方法。可以使用windows系统提供的串行口API函数另一种方法可以直接 使用Microsoft公司提供的ActiveX控件MSCOMM.OCX。利用MSCOMM.OCX控件进行串行口程序设计相对比较简单只要对该控件 的属性、事件和方法进行设置和操作就能完成简单的串行通信功能。而直接使用windows系统提供的串行口API函数则相对较为灵活。试验中可根据自 己的情况任意其中一种进行编程。一以下对如何使用windows系统提供的串行口API函数进行编程做简要介绍。在windows系统串行口和其它通信设备都是作为文件进行处理的。串行口的打开、关闭、发送和接收所用的函数都与操作文件的函数相同。总体来说利用 Visual C进行异步串行通信程序设计通常可以分为4个大阶段它们是串行口打开阶段、串行口状态值读取和属性设置阶段、串行数据的发送与接收阶段以及串行口 关闭阶段。1 打开串行口在 对串行口进行所有的操作之前首先要将其打开。串行口的打开可以使用CreateFile函数CreateFile函数将返回一个句柄在随后与该串行 口相关的各种操作中使用。与文件操作相同在利用CreateFile打开串行口时也可以将串行口指定为“读访问权限”、“写访问权限”或“读写访问权 限”。HANDLE CreateFileLPCTSTR lpFileNameDWORD dwDesiredAccessDWORD dwSharedModeLPSECURITY_ATTRIBUTES lpSecurityAttributesDWORD dwCreationDispositionDWORD dwFlagsAndAttributesHANDLE hTemplateFile)在调用成功时CreateFile返回打开文件的句柄该句柄将在以后与该串口相关的各个调用函数中使用。如果调用失败则CreateFile返回INVALID_HANDLE_VALUE。2 串行口的状态读取和属性设置一旦将串口打开就可以对该串口的属性进行设置。由于串口的属性非常复杂因此通常采用读取该串口当前状态值然后在此基础上进行修改的方法。获取串行口当前状态windows系统使用GetCommState函数获取串行口的当前配置GetCommState的声明如下BOOL GetCommStateHANDLE hFileLPDCB lpDCBGetCommState函数的第一个参数hFile是由CreateFile函数返回指向已打开串行口的句柄。第二个参数指向设备控制块DCB。DCB是一个非常重要的数据结构几乎所有的串行口属性和状态都存储在该结构的成员变量中。对串口进行设置windows系统利用SetCommState函数修改串行口的当前参数配置。SetCommState函数声明如下BOOL SetCommStateHANDLE hFileLPDCB lpDCBGetCommState 函数的第一个参数hFile是由CreateFile函数返回指向已打开串行口的句柄。第二个参数指向设备控制块DCB。如果函数调用成功则返回值为非 0若函数调用失败则返回值为0。当应用程序仅仅需要修改一部分串行口的配置值时可以通过GetCommState函数获得当前的DCB结构然后更 改参数再调用SetCommState函数设置修改过的DCB来配置串行口。为串口分配接收和发送缓冲区当 一个串行口打开时可以为该串口分配一个发送缓冲区和一个接收缓冲区。串行口发送缓冲区和接收缓冲区的配置可以由函数SetupComm实现。如果不调用 SetupComm系统会为该串口分配默认的发送缓冲区和接收缓冲区。但是为了保证缓冲区的大小与实际需要的一致最好调用该函数进行设置。 SetupComm函数原型如下BOOL SetupCommHANDLE hFileDWORD dwInQueueDWORD dwOutQueue其中hFile是由CreateFile函数返回指向已打开串行口的句柄。参数dwInQueue和dwOutQueue分别指定应用程序推荐使用的接收缓冲区和发送缓冲区的大小。清空接收和发送缓冲区在进行串口所有的发送和接收数据操作之前最好使用PurgeComm函数将串行口发送缓冲区和接收缓冲区中的数据清楚干净。PurgeComm函数原型如下BOOL PurgeCommHANDLE hFileDWORD dwFlages参 数hFile是由CreateFile函数返回指向已打开串行口的句柄参数dwFlags指明执行的动作。如果dwFlags为 PURGE_TXCLEAR则通知系统清空发送缓冲区如果dwFlags为PURGE_RXCLEAR则通知系统清空接收缓冲区如果需要将发送缓 冲区和接收缓冲区全部清空可以把dwFlags设置为PURGE_TXCLEAR|PURGE_RXCLEAR。如果PurgeComm函数调用成功 则返回值为非0若函数调用失败则返回值为0。3 串行数据的发送和接收与普通的文件操作相同在对串行口进行操作时通常利用ReadFile函数读取串行口收到的数据利用WriteFile将需要发送的数据写如串行口。串行数据的接收利用ReadFile函数可以读取将串行口接收到的数据。ReadFile函数原型如下BOOL ReadFileHANDLE hFileLPVIOD lpBufferDWORD nNumberOfBytesToReadLPDWORD lpNumberOfBytesReadLPOVERLAPPED lpOverlapped其中参数hFile指向已经打开的串行口句柄lpBuffer指向一个读取数据缓冲区nNumberOfBytesToRead指定要从串行设备中读取 的字节数lpNumberOfBytesRead指明实际从串行口中读出的字节数lpOverlapped指向一个OVERLAPPED结构变量该 结构变量中包含一个同步事件。通常如果调用成功ReadFile返回非0值 否则返回值为0。但是对于接收操作在后台进行的串口来说返回值为0不一定说明函数调用失败。此时可以调用GetLastError函数获取进一步的信 息。如果GetLastError返回值为ERROR_IO_PENDING则说明该读取串口的操作仍然处于后台等待状态而非一个真正意义上的错误。串行数据的发送利用WriteFile函数可以向串行口写入数据。WriteFile函数原型如下BOOL WriteFileHANDLE hFileLPVIOD lpBufferDWORD nNumberOfBytesToWriteLPDWORD lpNumberOfBytesWrittenLPOVERLAPPED lpOverlapped其 中参数hFile指向已经打开的串行口句柄lpBuffer指向一个发送数据缓冲区nNumberOfBytesToRead指定要从串行设备中发送 的字节数lpNumberOfBytesRead指明实际从串行口中发送的字节数lpOverlapped指向一个OVERLAPPED结构变量该 结构变量中包含一个同步事件。通常如果调用成功WriteFile返回非0 值否则返回值为0。但是对于发送操作在后台进行的串口来说返回值为0不一定说明函数调用失败。此时可以调用GetLastError函数获取进一步的 信息。如果GetLastError返回值为ERROR_IO_PENDING则说明该写入串口的操作仍然处于后台等待状态而非一个真正意义上的错 误。4 关闭串行口在用完串行口后通常要将其关闭。如果忘记关闭该串口会始终处于打开状态其它的应用程序就不能打开或使用它。关闭串口可以使用函数CloseHandle其函数原型如下BOOL CloseHandleHANDLE hObjectCloseHandle函数非常简单其中hObject为该打开串口的句柄。如果该函数调用成功则返回值为非0否则返回值为0。