⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialprot.cpp

📁 实用串口编程库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        case SERAIL_CLOSEEVENT:
            pComm->m_WriteThread = NULL;
            AfxEndThread(0);
            break;
        }
    }
    return 0;
}
#endif

//正如在《Serial communications in Microsoft Win32》等文章中提到的,同步(NonOverLapped)方式是
//比较简单的一种方式,,编写起来代码的长度要明显少于异步(OverLapped)方式,我开始用同步方式编写
//了整个子程序,在 Windows98 下工作正常,但后来在 Windows2000下测试,发现接收正常,但一发送数
//据,程序就会停在那里,原因应该在于同步方式下如果有一个通讯 Api 在操作中,另一个会阻塞直到上一
//个操作完成,所以当读数据的线程停留在 WaitCommEvent 的时候,WriteFile 就停在那里。我又测试了我
//手上所有有关串行通讯的例子程序,发现所有使用同步方式的程序在 Windows 2000 下全部工作不正常,
//对这个问题我一直找不到解决的办法,后来在 Iczelion 站点上发现一篇文章提到 NT 下对串行通讯的处
//理和 9x 有些不同,根本不要指望在 NT 或 Windows 2000 下用同步方式同时收发数据,我只好又用异步
//方式把整个通讯子程序重新写了一遍。
BOOL CSerialPort::StartPort(LPCTSTR lpszCommName, BOOL bCreateThread, BOOL bOverlapped)
{
    //注意: 强制设置为异步(重叠)I/O方式
    bOverlapped = TRUE;

#ifndef FEATURE_SERIAL_QUEUE
    EnterCriticalSection(&m_csRxQueue);    
    memset(m_RxQueueCtrl.RxBuffer, 0, SERIAL_RXBUFFERSIZE);
    m_RxQueueCtrl.pRead = m_RxQueueCtrl.pWrite = &m_RxQueueCtrl.RxBuffer[0];
    m_RxQueueCtrl.wRxCount = 0;
    LeaveCriticalSection(&m_csRxQueue);

#ifdef FEATURE_SERIAL_ASYNWRITE
    EnterCriticalSection(&m_csTxBuff);    
    memset(m_TxBuff, 0, SERIAL_TXBUFFERSIZE);
    m_wTxCount = 0;
    LeaveCriticalSection(&m_csTxBuff);
#endif
#endif
    
    if(Open(lpszCommName, bOverlapped) && Config())
    {
        m_bIsConnect = TRUE;      

        if(bCreateThread)
        {
            m_ReadThread = AfxBeginThread(CommReadThreadProc, this);
            m_DetectThread = AfxBeginThread(CommDetectThreadProc, this);
#ifdef FEATURE_SERIAL_ASYNWRITE
            m_WriteThread = AfxBeginThread(CommWriteThreadProc, this);
#endif
        }

        m_SerialState = SERIAL_STATE_CMD;        
        return TRUE;
    }
    else
    {
        m_SerialState = SERIAL_STATE_EXCEPTION;        
        return FALSE;        
    }
}

BOOL CSerialPort::StopPort()
{
#ifdef FEATURE_SERIAL_ASYNWRITE
    if(m_WriteThread)
    {
        if(m_hCloseWriteEvent)
            ::SetEvent(m_hCloseWriteEvent);
        m_WriteThread = NULL;
    }
#endif

#if 0
    if(m_ReadThread && m_ReadThread->m_hThread)
    {
        ::TerminateThread(m_ReadThread->m_hThread, 0);
        m_ReadThread = NULL;
    }
#endif

#ifdef FEATURE_SERIAL_QUEUE        
    m_ReadBufQueue.Clear();
    m_WriteBufQueue.Clear();
#endif

    Close();
    m_SerialState = SERIAL_STATE_INI;    
    return TRUE;
}

CHSDPADlg *pSpMainDlg = NULL;

BOOL CSerialPort::WriteToPort(const char *pBuf, WORD wLen, BOOL bReportError)
{
    ASSERT(pBuf != NULL && wLen < SERIAL_TXBUFFERSIZE);

    if(m_SerialState != SERIAL_STATE_CMD)
    {
        if(pSpMainDlg)
        {
            BOOL bSyncInitMask;
            EnterCriticalSection(&pSpMainDlg->m_csSyncInitMask);
            bSyncInitMask = pSpMainDlg->m_bSyncInitMask; //added by wk
            LeaveCriticalSection(&pSpMainDlg->m_csSyncInitMask);
            if(!bSyncInitMask && bReportError)
            {
                if(m_SerialState == SERIAL_STATE_INI)
                    AfxMessageBox(IDS_USB_PORT_INI);
                else if(m_SerialState == SERIAL_STATE_EXCEPTION)
                    AfxMessageBox(IDS_USB_PORT_EXCEPTION);
                else if(m_SerialState == SERIAL_STATE_CMD_WAIT)
                    AfxMessageBox(IDS_USB_PORT_WAIT);
                else if(m_SerialState == SERIAL_STATE_DATA)
                    AfxMessageBox(IDS_USB_PORT_DATA);
                else
                    AfxMessageBox(IDS_USB_PORT_WAIT);
            }  
        }
        return FALSE;
    }

#ifdef FEATURE_SERIAL_ASYNWRITE
#ifdef FEATURE_SERIAL_QUEUE    
    CSerialBuffer *pWriteBuf = new CSerialBuffer;
    pWriteBuf->m_dwBytes = wLen;
    memcpy(pWriteBuf->m_szBuffer, pBuf, wLen);
    m_WriteBufQueue.AddToTail(pWriteBuf);
#else
    EnterCriticalSection(&m_csTxBuff);
    m_wTxCount = wLen;
    memcpy(m_TxBuff, pBuf, wLen);
    LeaveCriticalSection(&m_csTxBuff);
#endif
    ASSERT(m_WriteThread != NULL);
    ::SetEvent(m_hWriteEvent);
    m_SerialState = SERIAL_STATE_CMD_WAIT;
#else
    DWORD dwWrite = 0;
    Purge(PURGE_TXCLEAR);
    m_SerialState = SERIAL_STATE_CMD_WAIT;
    dwWrite = Write(pBuf, wLen);
    if(dwWrite != wLen)
    {
        m_SerialState = SERIAL_STATE_CMD;
        return FALSE;
    }
#endif

#ifdef _DEBUG
    memset(&gStAtMsg, 0, sizeof(gStAtMsg));
    memcpy(gStAtMsg.snd, pBuf, wLen);
#endif

    return TRUE;
}

UINT CSerialPort::CommReadThreadProc(LPVOID pParam)
{
	CSerialPort *pComm = (CSerialPort*)pParam;
    DWORD   dwErrorFlags;
    COMSTAT comStat;
    pComm->Purge(PURGE_RXCLEAR);
    //注册监听的事件
    ::SetCommMask(pComm->m_hComm, EV_RXCHAR | EV_ERR);
    
    while(pComm->IsConnect()) 
    {
        if(pComm->WaitEvent())
        {    
            if(pComm->m_dwEvtMask & EV_RXCHAR)
            {                
				DWORD dwReadBytes = 0;			
                do    //读缓冲区有数据
                {                    
                    BYTE WorkBuff[SERIAL_RXBUFFERSIZE];
                    memset(WorkBuff, 0, SERIAL_RXBUFFERSIZE);
                    if((dwReadBytes = pComm->Read(WorkBuff, 1)) > 0)
                    {
                        DWORD wCopyBytes = 0;
                        BYTE *ptr = WorkBuff;                   
                        EnterCriticalSection(&pComm->m_csRxQueue);
                        WORD wRxCount = pComm->m_RxQueueCtrl.wRxCount;
                        wCopyBytes = min(dwReadBytes, (WORD)(SERIAL_RXBUFFERSIZE - pComm->m_RxQueueCtrl.wRxCount));
                        while(wCopyBytes-- > 0)
                        {
                            *pComm->m_RxQueueCtrl.pWrite++ = *ptr++;
                            if(pComm->m_RxQueueCtrl.pWrite >= &pComm->m_RxQueueCtrl.RxBuffer[SERIAL_RXBUFFERSIZE])
                                pComm->m_RxQueueCtrl.pWrite = &pComm->m_RxQueueCtrl.RxBuffer[0];
                            pComm->m_RxQueueCtrl.wRxCount++;
                        }  
                        LeaveCriticalSection(&pComm->m_csRxQueue);
                        ::SetEvent(g_AtRespEvent);
                    }  
                }while(dwReadBytes > 0);
//Debug
#ifdef _DEBUG
#if 0
                CStdioFile file;
                file.Open("CommTest.txt", CFile::modeCreate | CFile::modeWrite);
                file.WriteString((LPCTSTR)pComm->m_RxQueueCtrl.RxBuffer);
                file.Close();
#endif
#endif
            }
            else if(pComm->m_dwEvtMask & EV_ERR)
            {
                pComm->Purge(PURGE_RXCLEAR);
                ::ClearCommError(pComm->m_hComm, &dwErrorFlags, &comStat);
            }
        }
    }
    pComm->m_ReadThread = NULL;
    return 0;
}

UINT CSerialPort::CommDetectThreadProc(LPVOID pParam)
{
    CSerialPort *pComm = (CSerialPort*)pParam;
    ULONG        event = 0, junk = 0;
    
 //   AfxMessageBox("DECT");
    
    if(!pComm->IsConnect())
        return 0;
    if(pComm->IoControl(IOCTL_QCOMSER_WAIT_NOTIFY_CODE,
                       NULL,
                       0,
                       &event,
                       sizeof(event),
                       &junk))
    {  
//    AfxMessageBox("disc");
        if(!pComm->IsConnect())
            return 0;
        
        if(event & 0x01)
        {
            CHSDPADlg* pMainDlg = (CHSDPADlg*)(theApp.GetMainWnd());
            ASSERT(pMainDlg);
         
#ifdef FEATURE_AUTOQUIT
//			AfxMessageBox(IDS_CARD_DISCONN);
			CHSDPADlg* pMainDlgTemp = (CHSDPADlg*)(theApp.GetMainWnd());
			PreMsg *PreMsgDlgTemp = ((CHSDPAApp*)AfxGetApp())->m_PreMsgDlg;
			
			if (!pMainDlgTemp->m_bPortStatus)
			{
				
				if (NULL == PreMsgDlgTemp)
				{
					CString strDspInfo;
					PreMsg *PreMsgDlg = new PreMsg;
					ASSERT(PreMsgDlg);
					PreMsgDlg->Create(PreMsgDlg->IDD);
					//PreMsgDlg->SetBitmap(IDB_SPLASH,255,0,255);
					//WCharToChar(g_SetData.Main_szSplashBmp, char* cstr);
					PreMsgDlg->SetBitmap(g_SetData.Main_szSplashBmp, 255 ,0 ,255);
					PreMsgDlg->ShowWindow(SW_SHOW);
					strDspInfo.LoadString(IDS_CARD_DISCONN);
					PreMsgDlg->SetText(strDspInfo);
					Sleep(2000);
					PreMsgDlg->DestroyWindow();
					delete PreMsgDlg;
					pMainDlgTemp->PostMessage(WM_QUIT);
				}
				else
				{
					/*
					CString strDspInfo;
					strDspInfo.LoadString(IDS_CARD_DISCONN);
					PreMsgDlgTemp->SetText(strDspInfo);
					Sleep(2000);
					*/
					exit(0);
				}				
			}
			else
			{
				pMainDlgTemp->m_bPortStatus = false;
			}
#else
            pComm->StopPort();
            pComm->m_DetectThread = NULL;
            pMainDlg->m_bInComSms = FALSE;
            pMainDlg->m_bInComCall = FALSE;
            if(g_BGPassEvt)
                ::SetEvent(g_BGPassEvt);
            pMainDlg->ResetSyncData();
            pMainDlg->PostMessage(WM_ICON_UPDATE, ICON_TYPE_RSSI, 6);
            pMainDlg->PostMessage(WM_ICON_UPDATE, ICON_TYPE_NETWORK, NW_TYPE_NOSRV);
            pMainDlg->PostMessage(WM_ICON_UPDATE, ICON_TYPE_ROAM, ROAM_OFF);
            pMainDlg->PostMessage(WM_ICON_UPDATE, ICON_TYPE_PLMN, 0);
		    (theApp.GetMainWnd())->SetTimer(IDT_USB_CONN_DETECT, 1000, NULL);
#endif
        }
    }
    return 0;
}

//打印缓冲区字节数
DWORD CSerialPort::PrintBufBytes(int type) //0: 读缓冲,1: 写缓冲
{
    DWORD   dwErrorFlags;
    COMSTAT comStat;    

    CString str;
    DWORD   dwBytes;

    ::ClearCommError(m_hComm, &dwErrorFlags, &comStat);    

    if(type == 0)
    {
        str.Format(_T("ReadBuf: %d"), comStat.cbInQue);
        dwBytes = comStat.cbInQue;
    }
    else
    {
        str.Format(_T("WriteBuf: %d"), comStat.cbOutQue);
        dwBytes = comStat.cbOutQue;
    }
    AfxMessageBox(str);
    return dwBytes;
}

BOOL CSerialPort::Config()
{
    ASSERT(IsOpen());

    COMMTIMEOUTS TimeOuts;

    ::SetupComm(m_hComm, 1200, 1200);
    
    TimeOuts.ReadIntervalTimeout = MAXDWORD;
    TimeOuts.ReadTotalTimeoutMultiplier = 0;
    TimeOuts.ReadTotalTimeoutConstant = 1000;
    TimeOuts.WriteTotalTimeoutMultiplier = 0;
    TimeOuts.WriteTotalTimeoutConstant = 1000;
    ::SetCommTimeouts(m_hComm, &TimeOuts);

    DCB dcb;    
    dcb.DCBlength = sizeof(DCB);
    
    if(!::GetCommState(m_hComm, &dcb))
        return FALSE;

    dcb.BaudRate = CBR_19200;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    
    return ::SetCommState(m_hComm, &dcb);
}

BOOL CSerialPort::IsConnect() const
{
    return m_bIsConnect;
}
EnSerialState CSerialPort::GetSerialState() const
{
    return m_SerialState;
}

EnSerialState CSerialPort::SetSerialState(const EnSerialState state)
{
    ASSERT(state >= SERIAL_STATE_INI && state < SERIAL_STATE_MAX);

    EnSerialState oldState = m_SerialState;
    m_SerialState = state;
    return oldState;
}

BOOL CSerialPort::CommIsReady()
{   
    EnSerialState state;

    if((state = GetSerialState()) != SERIAL_STATE_CMD)
    {
        if(state == SERIAL_STATE_INI)
            AfxMessageBox(IDS_USB_PORT_INI);
        else if(state == SERIAL_STATE_EXCEPTION)
            AfxMessageBox(IDS_USB_PORT_EXCEPTION);
        else if(state == SERIAL_STATE_CMD_WAIT)
            AfxMessageBox(IDS_USB_PORT_WAIT);
        else if(state == SERIAL_STATE_DATA)
            AfxMessageBox(IDS_USB_PORT_DATA);
        else
            AfxMessageBox(IDS_USB_PORT_WAIT);
        return FALSE;
    }
    else
        return TRUE;
}





















⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -