vc2010下串口函数返回值无效的问题(关闭后再打开即无效) 20C

原来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);
}

1个回答

关闭串口失败造成的,导致第二次createfile返回句柄无效,用这样方法测试一下:打开串口,然后关闭,这时用串口调试工具打开串口,看提示是被占用还是正常打开,这样逐步调试

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问