|
@@ -0,0 +1,588 @@
|
|
|
+/*-----------------------------------------
|
|
|
+* Copyright (c) 2008 Eric Wong
|
|
|
+* 本版紧供读者参考,不得用于任何商业行为
|
|
|
+*
|
|
|
+* 文件名称: CESeries.cpp
|
|
|
+* 文件标识:
|
|
|
+* 摘要:用于封装WINCE 串口通讯
|
|
|
+*
|
|
|
+* 当前版本: 1.0
|
|
|
+* 作者: 汪兵 Eric Wong
|
|
|
+* 完成日期: 2008年1月17日
|
|
|
+*
|
|
|
+* 取代版本:
|
|
|
+* 原作者:
|
|
|
+* 完成日期:
|
|
|
+----------------------------------------*/
|
|
|
+#include "StdAfx.h"
|
|
|
+#include "MySeries.h"
|
|
|
+
|
|
|
+//构造函数
|
|
|
+CMyCESeries::CMyCESeries(UINT portNo, UINT baud, UINT parity, UINT databits, UINT stopbits)
|
|
|
+:m_portNo(portNo)
|
|
|
+,m_baud(baud)
|
|
|
+,m_parity(parity)
|
|
|
+,m_databits(databits)
|
|
|
+,m_stopbits(stopbits)
|
|
|
+,m_hReadThread(NULL)
|
|
|
+,m_hReadCloseEvent(NULL)
|
|
|
+{
|
|
|
+ //m_portNo = portNo; //串口号使用串口1 CAN模块和GPS共用
|
|
|
+ //m_baud = baud; //波特率
|
|
|
+ //m_parity = parity; //奇偶校验,0-None,1-Odd,2-Even
|
|
|
+ //m_databits = databits; //数据位
|
|
|
+ //m_stopbits = stopbits; //停止位 0-停止位1,1-停止位1.5,2-停止位2
|
|
|
+
|
|
|
+ //初始化内部变量
|
|
|
+ m_hComm = INVALID_HANDLE_VALUE;
|
|
|
+ m_OnSeriesRead = NULL;
|
|
|
+ m_hReadCloseEvent = NULL;
|
|
|
+ m_bOpened = false;
|
|
|
+
|
|
|
+ bCanComRead = true;
|
|
|
+ m_bSyncOrAsync = true;//使用同步方式或者异步方式(重叠方式),默认值为true:异步方式
|
|
|
+
|
|
|
+ memset(&m_olWrite,0,sizeof(OVERLAPPED));
|
|
|
+}
|
|
|
+
|
|
|
+//析构函数
|
|
|
+CMyCESeries::~CMyCESeries()
|
|
|
+{
|
|
|
+ if (m_bOpened)
|
|
|
+ ClosePort();
|
|
|
+}
|
|
|
+
|
|
|
+//串口读线程函数
|
|
|
+DWORD CMyCESeries::ReadThreadFunc(LPVOID lparam)
|
|
|
+{
|
|
|
+ CMyCESeries *ceSeries = (CMyCESeries*)lparam;
|
|
|
+
|
|
|
+
|
|
|
+ BYTE * readBuf = NULL;//读取的字节
|
|
|
+ DWORD actualReadLen=0;//实际读取的字节数
|
|
|
+ DWORD willReadLen;
|
|
|
+
|
|
|
+ DWORD dwReadErrors;
|
|
|
+ COMSTAT cmState;
|
|
|
+ //异步方式下将使用这些变量
|
|
|
+ //LPOVERLAPPED
|
|
|
+ OVERLAPPED olWait;
|
|
|
+ //memset(&olWaite,0,sizeof(olWaite));
|
|
|
+ memset(&olWait,0,sizeof(OVERLAPPED));
|
|
|
+ olWait.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
|
+
|
|
|
+ //同步方式,将使用该变量
|
|
|
+ DWORD evtMask;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 清空缓冲,并检查串口是否打开。
|
|
|
+ ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE);
|
|
|
+
|
|
|
+
|
|
|
+ //清空串口
|
|
|
+ PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );
|
|
|
+
|
|
|
+ SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );//设置3个串口事件
|
|
|
+
|
|
|
+ //可以查看串口设置了哪些事件
|
|
|
+ //DWORD dwMask1;
|
|
|
+ //GetCommMask(ceSeries->m_hComm,&dwMask1);
|
|
|
+
|
|
|
+ OVERLAPPED olRead;
|
|
|
+ memset(&olRead,0,sizeof(OVERLAPPED));
|
|
|
+ olRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
|
+
|
|
|
+
|
|
|
+ while(TRUE)
|
|
|
+ {
|
|
|
+ if(ceSeries->m_bSyncOrAsync)//异步方式下
|
|
|
+ {
|
|
|
+ DWORD dwCommStatus = 0;
|
|
|
+ BOOL bWait1=0;
|
|
|
+ bWait1= WaitCommEvent(ceSeries->m_hComm,&dwCommStatus,&olWait);//如果以上设置的3个事件中任何一个发生了,这里主要是监测接收缓冲区中有数据时
|
|
|
+ //while(!bWait1);//等待WaitCommEvent返回为TRUE,再往下执行,这种方式行不通,重叠方式(异步方式)时,该函数一直返回为false,
|
|
|
+ DWORD dwByte; //norains:It is only suitable for the GetOverlappedResult(),not undefined here.
|
|
|
+ if(GetOverlappedResult(ceSeries->m_hComm,&olWait,&dwByte,TRUE) == FALSE)//正常清空下,会一直在该函数阻塞,直到olWaite中的hEvent事件发生了
|
|
|
+ //则该函数不阻塞了,并且返回值为True
|
|
|
+ {
|
|
|
+ if(GetLastError() != ERROR_IO_PENDING)
|
|
|
+ {
|
|
|
+ return 0x30;
|
|
|
+ }
|
|
|
+ //Clear the error flag
|
|
|
+ DWORD dwErrors;
|
|
|
+ COMSTAT comStat;
|
|
|
+ memset(&comStat,0,sizeof(comStat));
|
|
|
+ ClearCommError(ceSeries->m_hComm,&dwErrors,&comStat);
|
|
|
+ return 0x35;
|
|
|
+ }
|
|
|
+
|
|
|
+ //表示串口收到字符
|
|
|
+ if (dwCommStatus & EV_RXCHAR)
|
|
|
+ {
|
|
|
+ ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
|
|
|
+ willReadLen = cmState.cbInQue ;
|
|
|
+ if (willReadLen <= 0)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ //异步方式
|
|
|
+ //分配内存
|
|
|
+ readBuf = new BYTE[willReadLen+1];
|
|
|
+ ZeroMemory(readBuf,willReadLen+1);
|
|
|
+ //读取串口数据
|
|
|
+
|
|
|
+ //异步方式
|
|
|
+ if(ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,&olRead)==FALSE)//异步操作,在读取完成以后返回TRUE
|
|
|
+ {
|
|
|
+ //释放内存
|
|
|
+ delete[] readBuf;
|
|
|
+ readBuf = NULL;
|
|
|
+
|
|
|
+ if(GetLastError() != ERROR_IO_PENDING)
|
|
|
+ return 0x40;
|
|
|
+
|
|
|
+ if(GetOverlappedResult(ceSeries->m_hComm,&olRead,&actualReadLen,TRUE) == FALSE)
|
|
|
+ return 0x45;
|
|
|
+
|
|
|
+ if(actualReadLen == 0)
|
|
|
+ return 0x50;
|
|
|
+ }
|
|
|
+ else//缓冲区中的数据读取完时
|
|
|
+ {
|
|
|
+ //如果读取的数据大于0,
|
|
|
+ if (actualReadLen>0)
|
|
|
+ {
|
|
|
+ //触发读取回调函数
|
|
|
+ if (ceSeries->m_OnSeriesRead)
|
|
|
+ {
|
|
|
+ ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //释放内存
|
|
|
+ delete[] readBuf;
|
|
|
+ readBuf = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else//同步方式下
|
|
|
+ {
|
|
|
+ if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
|
|
|
+ {
|
|
|
+ SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
|
|
|
+ //表示串口收到字符
|
|
|
+ if (evtMask & EV_RXCHAR)
|
|
|
+ {
|
|
|
+ ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
|
|
|
+ willReadLen = cmState.cbInQue ;
|
|
|
+ if (willReadLen <= 0)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ //分配内存
|
|
|
+ readBuf = new BYTE[willReadLen];
|
|
|
+ ZeroMemory(readBuf,willReadLen);
|
|
|
+ //读取串口数据
|
|
|
+ ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
|
|
|
+
|
|
|
+ //如果读取的数据大于0,
|
|
|
+ if (actualReadLen>0)
|
|
|
+ {
|
|
|
+ //触发读取回调函数
|
|
|
+ if (ceSeries->m_OnSeriesRead)
|
|
|
+ {
|
|
|
+ ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //释放内存
|
|
|
+ delete[] readBuf;
|
|
|
+ readBuf = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //每次读线程执行到该处时,都会等待(或者叫阻塞)10milseconds,看是否关闭串口事件是否发生
|
|
|
+ //在ClosePort()函数体中调用了CloseHandle(m_hReadCloseEvent);来使得该事件有信号,我觉得可以用SetEvent(m_hReadCloseEvent)代替,该函数也是使得事件有信号
|
|
|
+ //当执行了ClosePotr()函数后,说明该事件已经发生了,则当在读线程函数中执行到此处时,
|
|
|
+ //将会跳出while(true),从而退出读线程,
|
|
|
+ if (WaitForSingleObject(ceSeries->m_hReadCloseEvent, 10) == WAIT_OBJECT_0)//
|
|
|
+ {
|
|
|
+ TRACE("线程ReadThreadFunc退出\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //关闭事件
|
|
|
+ CloseHandle( olRead.hEvent );
|
|
|
+ CloseHandle( olWait.hEvent );
|
|
|
+
|
|
|
+ //释放内存
|
|
|
+ if(readBuf)
|
|
|
+ {
|
|
|
+ delete[] readBuf;
|
|
|
+ readBuf = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ExitThread(0);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+//关闭读线程
|
|
|
+void CMyCESeries::CloseReadThread()
|
|
|
+{
|
|
|
+ if( m_hComm != INVALID_HANDLE_VALUE )
|
|
|
+ {
|
|
|
+ // SetEvent(m_hReadCloseEvent);
|
|
|
+ // CloseHandle(m_hReadCloseEvent);
|
|
|
+
|
|
|
+ //WaitForSingleObject(m_hReadThread, 1000);
|
|
|
+
|
|
|
+ // DWORD exitCode;
|
|
|
+ // BOOL ret = GetExitCodeThread(m_hReadThread, &exitCode);
|
|
|
+ //if(ret && exitCode != 0)
|
|
|
+ {
|
|
|
+ TRACE("强行关闭ReadThreadFunc线程\n");
|
|
|
+ TerminateThread(m_hReadThread,0);
|
|
|
+ }
|
|
|
+ // CloseHandle(m_hReadThread);
|
|
|
+
|
|
|
+ m_hReadThread = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+/*
|
|
|
+ if( m_hComm != INVALID_HANDLE_VALUE )
|
|
|
+ {
|
|
|
+ SetEvent(m_hReadCloseEvent);
|
|
|
+ //设置所有事件无效
|
|
|
+ SetCommMask(m_hComm, 0);
|
|
|
+ //清空所有将要读的数据
|
|
|
+ PurgeComm( m_hComm, PURGE_RXCLEAR );
|
|
|
+ //等待4秒,如果读线程没有退出,则强制退出
|
|
|
+ if (WaitForSingleObject(m_hReadThread,4000) == WAIT_TIMEOUT)
|
|
|
+ {
|
|
|
+ TerminateThread(m_hReadThread,0);
|
|
|
+ }
|
|
|
+ m_hReadThread = NULL;
|
|
|
+ }
|
|
|
+//*/
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//函数介绍:打开串口
|
|
|
+//入口参数:pPortOwner :使用此串口类的窗体句柄
|
|
|
+// portNo :串口号
|
|
|
+// baud :波特率
|
|
|
+// parity :奇偶校验
|
|
|
+// databits :数据位
|
|
|
+// stopbits :停止位
|
|
|
+//出口参数:(无)
|
|
|
+//返回值:TRUE:成功打开串口;FALSE:打开串口失败
|
|
|
+BOOL CMyCESeries::OpenPort(void * pOwner,
|
|
|
+ UINT portNo , //串口号
|
|
|
+ UINT baud , //波特率
|
|
|
+ UINT parity , //奇偶校验
|
|
|
+ UINT databits , //数据位
|
|
|
+ UINT stopbits , //停止位
|
|
|
+ bool isASync
|
|
|
+ )
|
|
|
+{
|
|
|
+ m_portNo = portNo; //串口号使用串口1 CAN模块和GPS共用
|
|
|
+ m_baud = baud; //波特率
|
|
|
+ m_parity = parity; //奇偶校验,0-None,1-Odd,2-Even
|
|
|
+ m_databits = databits; //数据位
|
|
|
+ m_stopbits = stopbits; //停止位 0-停止位1,1-停止位1.5,2-停止位2
|
|
|
+
|
|
|
+ m_bSyncOrAsync = isASync;
|
|
|
+
|
|
|
+ DCB commParam;
|
|
|
+ TCHAR szPort[15];
|
|
|
+
|
|
|
+ ASSERT(pOwner!=NULL);
|
|
|
+ m_pOwner = pOwner;
|
|
|
+
|
|
|
+ // 已经打开的话,直接返回
|
|
|
+ if (m_hComm != INVALID_HANDLE_VALUE)
|
|
|
+ {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //设置串口名
|
|
|
+ //wsprintf(szPort, _T("\.\COM%d:"), portNo);
|
|
|
+ wsprintf(szPort, _T("\\\\.\\COM%d"), portNo);
|
|
|
+ //sprintf(szPort, "\\\\.\\COM%d", portNo);
|
|
|
+ //打开串口
|
|
|
+
|
|
|
+ if(m_bSyncOrAsync)//m_bSyncOrAsync值为0,则用同步方式创建,否则以异步方式创建、
|
|
|
+ {
|
|
|
+ m_hComm = CreateFile( //以异步方式创建
|
|
|
+ szPort,
|
|
|
+ GENERIC_READ | GENERIC_WRITE, //允许读和写
|
|
|
+ 0, //独占方式(共享模式)
|
|
|
+ NULL,
|
|
|
+ OPEN_EXISTING, //打开而不是创建(创建方式)
|
|
|
+ FILE_FLAG_OVERLAPPED,
|
|
|
+ 0
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ m_hComm = CreateFile( //以同步方式创建
|
|
|
+ szPort,
|
|
|
+ GENERIC_READ | GENERIC_WRITE, //允许读和写
|
|
|
+ 0, //独占方式(共享模式)
|
|
|
+ NULL,
|
|
|
+ OPEN_EXISTING, //打开而不是创建(创建方式)
|
|
|
+ 0,
|
|
|
+ NULL
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (m_hComm == INVALID_HANDLE_VALUE)
|
|
|
+ {
|
|
|
+ // 无效句柄,返回。
|
|
|
+ TRACE(_T("CreateFile 返回无效句柄\n"));
|
|
|
+ DWORD ErrNo = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 得到打开串口的当前属性参数,修改后再重新设置串口。
|
|
|
+ if (!GetCommState(m_hComm,&commParam))
|
|
|
+ {
|
|
|
+ //关闭串口
|
|
|
+ CloseHandle (m_hComm);
|
|
|
+ m_hComm = INVALID_HANDLE_VALUE;
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m_bSyncOrAsync)//如果是异步方式,每创建一个串口对象,并且成功打开一个串口对象时后,才创建一个相应的发送事件
|
|
|
+ {
|
|
|
+ //异步写串口
|
|
|
+ m_olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,_T("WriteData"));
|
|
|
+// DWORD dwError = GetLastError();
|
|
|
+// if(dwError !=0)
|
|
|
+// {
|
|
|
+// TRACE("异步方式创建串口对象时,为该串口对象所创建的写串口事件对象失败");
|
|
|
+// return FALSE;
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+ //设置串口参数
|
|
|
+ commParam.BaudRate = baud; // 设置波特率
|
|
|
+ commParam.fBinary = TRUE; // 设置二进制模式,此处必须设置TRUE
|
|
|
+ commParam.fParity = TRUE; // 支持奇偶校验
|
|
|
+ commParam.ByteSize = databits; // 数据位,范围:4-8
|
|
|
+ commParam.Parity = parity; // 校验模式
|
|
|
+ commParam.StopBits = stopbits; // 停止位
|
|
|
+
|
|
|
+ commParam.fOutxCtsFlow = FALSE; // No CTS output flow control
|
|
|
+ commParam.fOutxDsrFlow = FALSE; // No DSR output flow control
|
|
|
+ commParam.fDtrControl = DTR_CONTROL_ENABLE;
|
|
|
+ // DTR flow control type
|
|
|
+ commParam.fDsrSensitivity = FALSE; // DSR sensitivity
|
|
|
+ commParam.fTXContinueOnXoff = TRUE; // XOFF continues Tx
|
|
|
+ commParam.fOutX = FALSE; // No XON/XOFF out flow control
|
|
|
+ commParam.fInX = FALSE; // No XON/XOFF in flow control
|
|
|
+ commParam.fErrorChar = FALSE; // Disable error replacement
|
|
|
+ commParam.fNull = FALSE; // Disable null stripping
|
|
|
+ commParam.fRtsControl = RTS_CONTROL_ENABLE;
|
|
|
+ // RTS flow control
|
|
|
+ commParam.fAbortOnError = FALSE; // 当串口发生错误,并不终止串口读写
|
|
|
+
|
|
|
+ //设置串口参数
|
|
|
+ if (!SetCommState(m_hComm, &commParam))
|
|
|
+ {
|
|
|
+ TRACE(_T("SetCommState error\n"));
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+
|
|
|
+ //关闭串口
|
|
|
+ CloseHandle (m_hComm);
|
|
|
+ m_hComm = INVALID_HANDLE_VALUE;
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //设置串口读写时间
|
|
|
+ COMMTIMEOUTS CommTimeOuts;
|
|
|
+ GetCommTimeouts (m_hComm, &CommTimeOuts);
|
|
|
+ CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
|
|
|
+ CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
|
|
|
+ CommTimeOuts.ReadTotalTimeoutConstant = 0;
|
|
|
+ CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
|
|
|
+ CommTimeOuts.WriteTotalTimeoutConstant = 1000;
|
|
|
+ if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
|
|
|
+ {
|
|
|
+ TRACE( _T("SetCommTimeouts 返回错误\n") );
|
|
|
+ //关闭串口
|
|
|
+ CloseHandle (m_hComm);
|
|
|
+
|
|
|
+ m_hComm = INVALID_HANDLE_VALUE;
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //指定端口监测的事件集
|
|
|
+ SetCommMask (m_hComm, EV_RXCHAR);
|
|
|
+ //分配串口设备缓冲区
|
|
|
+ SetupComm(m_hComm,1024,1024);
|
|
|
+ //SetupComm(m_hComm,512,512);
|
|
|
+ //初始化缓冲区中的信息
|
|
|
+ PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
|
|
|
+
|
|
|
+ CString strEvent;
|
|
|
+ strEvent.Format(_T("Com_ReadCloseEvent%d"),portNo);
|
|
|
+ m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,strEvent);
|
|
|
+
|
|
|
+ //创建串口读数据监听线程
|
|
|
+ if( bCanComRead == true )
|
|
|
+ {
|
|
|
+ m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);//通过this指针将串口对象传递给读线程函数ReadThreadFunc的形参
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ TRACE(_T("串口%d打开成功\n"), portNo);
|
|
|
+ m_bOpened = true;
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//函数介绍:关闭串口
|
|
|
+//入口参数:(无)
|
|
|
+//出口参数:(无)
|
|
|
+//返回值: (无)
|
|
|
+void CMyCESeries::ClosePort()
|
|
|
+{
|
|
|
+ //表示串口还没有打开
|
|
|
+ if (m_hComm == INVALID_HANDLE_VALUE)
|
|
|
+ return ;
|
|
|
+
|
|
|
+ //关闭事件
|
|
|
+ //TRACE("关闭串口读事件\n");
|
|
|
+ Sleep(100);
|
|
|
+ //关闭读线程
|
|
|
+ CloseReadThread();
|
|
|
+
|
|
|
+ //关闭串口
|
|
|
+ TRACE("CMyCESeries关闭串口%d句柄\n", m_portNo);
|
|
|
+ CloseHandle (m_hComm);
|
|
|
+
|
|
|
+
|
|
|
+ //关闭事件
|
|
|
+ CloseHandle(m_olWrite.hEvent);
|
|
|
+
|
|
|
+ m_hComm = INVALID_HANDLE_VALUE;
|
|
|
+ m_bOpened = false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//函数介绍:往串口写入数据
|
|
|
+//入口参数:buf :待写入数据缓冲区
|
|
|
+// bufLen : 待写入缓冲区长度
|
|
|
+//出口参数:(无)
|
|
|
+//返回值:TRUE:设置成功;FALSE:设置失败
|
|
|
+BOOL CMyCESeries::WriteSyncPort(const BYTE*buf , DWORD bufLen)
|
|
|
+{
|
|
|
+ if( false == m_bSyncOrAsync )//同步方式
|
|
|
+ {
|
|
|
+ DWORD dwNumBytesWritten;
|
|
|
+ DWORD dwHaveNumWritten =0 ; //已经写入多少
|
|
|
+
|
|
|
+ int iInc = 0; //如果3次写入不成功,返回FALSE
|
|
|
+ ASSERT(m_hComm != INVALID_HANDLE_VALUE);
|
|
|
+ do
|
|
|
+ {
|
|
|
+ if (WriteFile (m_hComm, //串口句柄
|
|
|
+ buf+dwHaveNumWritten, //被写数据缓冲区
|
|
|
+ bufLen - dwHaveNumWritten, //被写数据缓冲区大小
|
|
|
+ &dwNumBytesWritten, //函数执行成功后,返回实际向串口写的个数
|
|
|
+ NULL)) //此处必须设置NULL
|
|
|
+ {
|
|
|
+ dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
|
|
|
+ //写入完成
|
|
|
+ if (dwHaveNumWritten == bufLen)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ iInc++;
|
|
|
+ if (iInc >= 3)
|
|
|
+ {
|
|
|
+ TRACE("CMyCESeries::WriteSyncPort 同步写串口失败3次\n");
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ Sleep(10);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TRACE("CMyCESeries::WriteSyncPort 同步写串口失败\n");
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ }while (TRUE);
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ else//异步方式
|
|
|
+ {
|
|
|
+ DWORD dwNumBytesWritten;
|
|
|
+ DWORD dwHaveNumWritten =0 ; //已经写入多少
|
|
|
+
|
|
|
+// OVERLAPPED olWrite;
|
|
|
+// memset(&olWrite,0,sizeof(OVERLAPPED));
|
|
|
+// m_olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,_T("WriteData"));
|
|
|
+
|
|
|
+ //异步写串口
|
|
|
+ if (WriteFile (m_hComm, //串口句柄
|
|
|
+ buf+dwHaveNumWritten, //被写数据缓冲区
|
|
|
+ bufLen - dwHaveNumWritten, //被写数据缓冲区大小
|
|
|
+ &dwNumBytesWritten, //函数执行成功后,返回实际向串口写的个数
|
|
|
+ &m_olWrite) == FALSE)//并不是表示写入失败,而是没有将所有数据写入到缓冲区中,而只是写入了部分而已
|
|
|
+ {
|
|
|
+ if(GetLastError() != ERROR_IO_PENDING)
|
|
|
+ {
|
|
|
+ TRACE("CMyCESeries::WriteSyncPort 异步写串口0x20\n");
|
|
|
+ return 0x20;
|
|
|
+ }
|
|
|
+ if(GetOverlappedResult(m_hComm,&m_olWrite,&dwNumBytesWritten,TRUE) == FALSE)//这里将一直阻塞,直到将所有数据写入到缓冲区为止
|
|
|
+ {
|
|
|
+ TRACE("CMyCESeries::WriteSyncPort 异步写串口0x25\n");
|
|
|
+ return 0x25;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //else//写入成功
|
|
|
+ {
|
|
|
+ dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
|
|
|
+ //写入完成
|
|
|
+ if (dwHaveNumWritten == bufLen)
|
|
|
+ return TRUE;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TRACE("CMyCESeries::WriteSyncPort 异步写串口%d失败\n", m_portNo);
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//函数介绍:设置串口读取、写入超时
|
|
|
+//入口参数:CommTimeOuts : 指向COMMTIMEOUTS结构
|
|
|
+//出口参数:(无)
|
|
|
+//返回值:TRUE:设置成功;FALSE:设置失败
|
|
|
+BOOL CMyCESeries::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts)
|
|
|
+{
|
|
|
+ ASSERT(m_hComm != INVALID_HANDLE_VALUE);
|
|
|
+ return SetCommTimeouts(m_hComm,&CommTimeOuts);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//得到串口是否打开
|
|
|
+BOOL CMyCESeries::GetComOpened()
|
|
|
+{
|
|
|
+ return m_bOpened;
|
|
|
+}
|