的值将被改变,应用程序检查 CommEvent 属性值并作出相应的反应。在程序中用ClassWizard为CMSComm控件添加OnComm消息处理函数:
void CSampleDlg::OnComm(){ ...... switch(m_Serial.GetCommEvent()) { case 2: // 串行口数据接收,处理; }}---- 方法二:在单线程中实现自定义的串口通信类
---- 控件简单易用,但由于必须拿到对话框中使用,在一些需要在线程中实现通信的应用场合,控件的使用显得捉襟见肘。此时,若能够按不同需要定制灵活的串口通信类将弥补控件的不足,以下将介绍如何在单线程中建立自定义的
通信类。
---- 该通信类CSimpleComm需手动加入头文件与源文件,其基类为CObject,大致建立步骤如下:
---- (1) 打开串口,获取串口资源句柄
---- 通信
程序从CreateFile处指定串口设备及相关的操作属性。再返回一个句柄,该句柄将被用于后续的通信操作,并贯穿整个通信过程。CreateFile()函数中有几个值得注意的参数设置:串口共享方式应设为0,串口为不可共享设备;创建方式必须为OPEN_EXISTING,即打开已有的串口。对于dwFlagAndAttribute参数,对串口有意义的值是FILE_FLAG_OVERLAPPED,该标志表明串口采用异步通信模式,可进行重叠操作;若值为NULL,则为同步通信方式,在同步方式下,应用程序将始终控制程序流,直到程序结束,若遭遇通信故障等因素,将导致应用程序的永久等待,所以一般多采用异步通信。
---- (2)串口设置
---- 串口打开后,其属性被设置为默认值,根据具体需要,通过调用GetCommState(hComm,&;dcb)读
取当前串口设备控制块DCB(Device Control Block)设置,修改后通过SetCommState(hComm,&;dcb)将其写入。再需注意异步读写的超时控制设置, 通过COMMTIMEOUTS结构设置超时,调用SetCommTimeouts(hComm,&;timeouts)将结果写入。以下是温度监控程序中串口初始化成员函数:
BOOL CSimpleComm::Open( ) { DCB dcb;m_hIDComDev=CreateFile( "COM2", GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVE RLAPPED, NULL ); // 打开串口,异步操作if( m_hIDComDev == NULL ) return( FALSE );dcb.DCBlength = sizeof( DCB );GetCommState( m_hIDComDev, &;dcb ); // 获得端口默认设置dcb.BaudRate=CBR_4800;dcb.ByteSize=8;dcb.Parity= NOPARITY;dcb.StopBits=(BYTE) ONESTOPBIT; ...... }---- (3)串口读写操作
---- 主要运用ReadFile()与WriteFile()API函数,若为异步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject()来等待结束信号并设置最长等待时间,举例如下:
BOOL bReadStatus; bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &;dwBytesRead, &;m_OverlappedRead ); if(!bReadStatus) { if(GetLastError()==ERROR_IO_PENDING) { WaitForSingleObject(m_OverlappedRead.hEvent,1000); return ((int)dwBytesRead); } return(0); } return ((int)dwBytesRead);---- 定义全局变量m_Serial作为新建通信类CSimpleComm的对象,通过调用类的成员函数即可实现所需串行通信功能。与方法一相比,方法二赋予串行通信程序
设计较大的灵活性,端口的读写可选择较简单的
查询式,或通过设置与外设数据发送时间间隔TimeCycle相同的定时器:SetTimer(1,TimeCycle,NULL),进行定时读取或发送。
CSampleView:: OnTimer(UINT nIDEvent) { char InputData[30]; m_Serial.ReadData(InputData,30); // 数据处理 }---- 若对端口数据的响应