原来vc6下的代码,可以正常使用,现在移植到2010和2013下,问题出现,具体描述如下:
因为要读取一个设备的数据(该数据由软件操作控制发送数据,可持续不断以一定格式发);vc2010环境,用API函数(createfile)打开串口,期间用afxbeginthread开启了一个线程,运行进程函数,该函数主要为只要联机变量为真(连上了串口),就等待串口的字符串,然后把字符串放到缓存,回调函数完成字符串的处理和显示。
现在,当我第一次打开串口(没有连设备,只是用一根USB-RS232线转了一个串口),正常打开,关闭后(CloseHandle函数)再次打开,createfile返回的句柄即显示无效:错误代码6,句柄为0xfffffff。只能重新运行程序,然后还是第一次正常打开,关闭后即无法打开!
BOOL CComLink::NewConnection(BYTE nRetType, WORD UserID, BYTE nPort, LPVOID pOwner, LPVOID pParam)
{
if(m_bConnected)
return FALSE;
m_hCom = OpenConnection(CommProc, nPort);
m_UserID = UserID;
m_nRetType = nRetType;
m_pWnd = (CWnd *)pOwner;
m_pMsgFunc = (_CALLBACK_MSG *)pParam;
return m_bConnected;
}
HANDLE CComLink::OpenConnection(AFX_THREADPROC pfnThreadProc, BYTE nPort)
{
HANDLE h_Com;
wchar_t szPort[15];
COMMTIMEOUTS CommTimeOuts;
wsprintf(szPort,_T("\\\\.\\COM%d"),nPort);
h_Com = CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if(h_Com == INVALID_HANDLE_VALUE)
return NULL;
else
{
SetCommMask(h_Com,EV_RXCHAR);
SetupComm(h_Com,4096,4096);
PurgeComm(h_Com, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR );
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts(h_Com, &CommTimeOuts);
m_bConnected = true;
}
if(SetCom(h_Com))
{
m_pThread = AfxBeginThread(pfnThreadProc, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL);
if(m_pThread == NULL)
{
CloseCom();
return NULL;
}
else
{
m_bConnected = true;
}
}
else
{
CloseCom();
return NULL;
}
return h_Com;
}
UINT CommProc(LPVOID pParam)
{
DWORD dwMask = 0;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwLength;
CComLink *pVoid=(CComLink*)pParam;
SetCommMask(pVoid->m_hCom,EV_RXCHAR);
while(pVoid->m_bConnected)
{
WaitCommEvent(pVoid->m_hCom, &dwMask, NULL); // 等待串口消息
if((dwMask & EV_RXCHAR)==EV_RXCHAR) // 如果是字符消息
{
ClearCommError(pVoid->m_hCom, &dwErrorFlags, &ComStat);
if(ComStat.cbInQue)
{
dwLength=min(sizeof(pVoid->m_DataBuf) - pVoid->m_nDataLen, ComStat.cbInQue); // 取缓冲区数据,确保分配的缓冲区能足够存储
if(!ReadFile(pVoid->m_hCom, &pVoid->m_DataBuf[pVoid->m_nDataLen], dwLength, &dwLength, &pVoid->osRead)) // 读取数据,存储到当前缓冲区位置之后
{
if(GetLastError()==ERROR_IO_PENDING)
{
GetOverlappedResult(pVoid->m_hCom, &pVoid->osRead, &dwLength, true);
}
}
pVoid->m_nDataLen += dwLength; // 数据长度累加
if(pVoid->m_nRetType == DATA_BY_MESSAGE) // 消息模式返回数据
{
pVoid->m_pWnd -> SendMessage(WM_COM_RECMSG, pVoid->m_UserID);
}
else if(pVoid->m_nRetType == DATA_BY_CALLBACK) // 回调函数返回数据
{
pVoid->m_pMsgFunc(WM_COM_RECMSG, (long)pVoid->m_pWnd, pVoid->m_UserID);
}
}
}// end if
}
return 0;
}
BOOL CComLink::CloseCom()
{
FindClose(m_hCom);
CloseHandle(m_hCom);
m_bConnected = false;
m_hCom =INVALID_HANDLE_VALUE;
return TRUE;
}
BOOL CComLink::SetCom(HANDLE h_Com)
{
DCB dcb;
GetCommState(h_Com,&dcb);
dcb.BaudRate = m_ComSet.BaudRate;
dcb.ByteSize = m_ComSet.ByteSize;
dcb.Parity = m_ComSet.Parity;
dcb.StopBits = m_ComSet.StopBits;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
return SetCommState(h_Com,&dcb);
}