win32下的串口编程(二)_sernger的空间_百度空间
串口状态:

  (1)通信事件:用SetCommMask()函数设置想要得到的通信事件的掩码,再调用WaitCommEvent()函数检测通信事件的发生。可设置的通信事件标志(即SetCommMask()函数所设置的掩码)可以有EV_BREAKEV_CTSEV_DSR EV_ERREV_RINGEV_RLSDEV_RXCHAREV_RXFLAGEV_TXEMPTY

   注意:1对于EV_RING标志的设置,WIN95是不会返回EV_RING事件的,因为WIN95不检测该事件。2设置EV_RXCHAR,可以检测到字符到达,但是在绑定此事件和ReadFile()函数一起读取串口接收数据时,可能会出现错误,造成少读字节数,具体原因查看MSDN帮助。可以采用循环读的办法,另外一个比较好的解决办法是调用ClearCommError()函数,确定在一次读操作中在缓冲区中等待被读的字节数。

  (2)错误处理和通信状态:在串口通信中,可能会产生很多的错误,使用ClearCommError()函数可以检测错误并且xx错误条件。

   3Modem状态:用SetcommMask()可以包含很多事件标志,但是这些事件标志只指示在串口线路上的电压变化情况。而调用 GetCommModemStatus()函数可以获得线路上真正的电压状态。

   扩展函数:如果应用程序想用自己的流控,可以使用 EscapeCommFunction()函数设置DTRRTS线路的电平。

   通信超时:在通信中,超时是个很重要的考虑因素,因为如果在数据接收过程中由于某种原因突然中断或停止,如果不采取超时控制机制,将会使得I/O线程被挂起或无限阻塞。串口通信中的超时设置分为两步,首先设置 COMMTIMEOUTS结构的五个变量,然后调用SetcommTimeouts()设置超时值。对于使用异步方式读写的操作,如果操作挂起后,异步成功完成了读写,WaitForSingleObject() WaitForMultipleObjects()函数将返回WAIT_OBJECT_0GetOverlappedResult()返回TRUE。其实还可以用GetCommTimeouts()得到系统初始值。

   关闭串口:程序结束或需要释放串口资源时,应该正确关闭串口,关闭串口比较简单,使用API调用CloseHandle()关闭串口的句柄就可以了。

  调用方法为:CloseHandle(hComm);

   但是值得注意的是在关闭串口之前必须保证读写串口线程已经退出,否则会引起误操作,一般采用的办法是使用事件驱动机制,启动一事件,通知串口读写线程强制退出,在线程退出之前,通知主线程可以关闭串口。

二、实现
  1.程序设计思路
   对于不同的应用程序,虽然界面不同,但是如果采用串口与主机之间的通信,对串口的处理方式大致相似,无非就是通过串口收发数据,对于通过串口接收到的数据,交给上层软件处理显示,对于上层要发给串口的数据,进行转发。但在实际编程中,由于采用的通信方式和流控不同,串口设置也不同,这就涉及到 DCB的初始化问题和读写串口等细节问题。串口通信应用程序设计的总体思路(即操作过程)是:首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用 GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。

  一般来说,串口的读写由串口读写线程完成,这样可以避免读写阻塞时主程序死锁。对于全双工的串口读写,应该分别开启读线程和写线程;对于半双工和单工的,建议只需开启一个线程即可。在线程中,按照预定好的通信握手方式,正确检测串口状态,读取发送串口数据。

  2.实现细节

  在半双工的情况下,首先完成必要的串口配置,成功打开串口、DCB设置、超时设置;然后开启线程,如: CwinThread hSerialThread = (CWinThread) AfxBeginThread(SerialOperationhWndTHREAD_PRIORITY_NORMAL); 其中开启之线程为SerialOperation,优先级为普通。

   全双工情况下的串口编程,与单工差不多,区别仅仅在于启动双线程,分别为读线程和写线程,读线程根据不同的事件或消息,通过不断查询串口所收到的有效数据,完成读操作;写线程通过接收主线程的发送数据事件和要发送的数据,向串口发送。

///////////////////////////////////////////////////////////////////////////////////////
用于串口通信的函数和结构在Winbase.h头文件中定义。
函数 描述
CreateFile
打开串行口
GetCommState
用指定通信设备的当前控制设置填充设备控制块(DCB结构)
SetCommState
按照DCB结构的说明配置通信设备。这个函数重新初始化所有硬件
和控制设备,但不清空I/O队列
GetCommTimeouts
获得指定通信设备上所有读/写操作的超时参数
SetCommTimeouts
设置指定通信设备上所有读/写操作的超时参数
WriteFile
向串行口写数据,这样将把数据传送给串行连接另一端的设备
ReadFile
从串行口读数据,这样将从串行连接另一端的设备接收数据
SetCommMask
指定为通信设备监视的一组事件
GetCommMask
获得指定通信设备的事件掩码值
WaitCommEvent
等待指定通信设备的事件的发生。WaitCommEvent函数监视的事件
包含在与设备句柄相关联的事件掩码中
EscapeCommFunction
指导指定通信设备执行扩展功能。通常用于将串行口设置为IR模式
ClearCommBreak
恢复指定通信设备的字符传输,并设置传输线路为不可中断状态
ClearCommError
获得通信错误数据,并报告指定通信设备的当前状态

打开端口
CreateFile
函数用于打开串行口,因为硬件供应商和设备驱动程序开发者可以随意命名端口,所以应用程序应该列出所有可用端口,从而使用户能够指定要打开的端口。如果端口不存在,则CreateFile函数返回ERROR_FILE_NOT_FOUND,而且应该通知用户端口不可用。
打开串行口
1
在{dy}个参数lpzPortName指向的通信口后插入一个冒号。例如,指定“COM1为通信端口。
2
指定dwShareMode参数为0。通信端口不能像文件一样被共享。
3
dwCreationDisposition参数中指定OPEN_EXISTING。这个标志是必须的。
4
指定dwFlagsAndAttributes参数为0Windows CE只支持非重叠I/0.
下面的代码段说明了如何打开串行通信端口。
hPort=CreateFile(lpszPortName, //
指出通信端口
GENERIC_READ|GENERIC_WRITE, //
读写模式
0
//共享模式
NULL, //
安全属性
OPEN_EXISTING, //
如何打开服务端口
0, //
端口属性
NULL); //
端口属性句柄的拷贝



郑重声明:资讯 【win32下的串口编程(二)_sernger的空间_百度空间】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——