连接界面:

    

界面初始操作:

    m_ComboBaudrate.AddString(_T("9600"));
    m_ComboBaudrate.AddString(_T("38400"));
    m_ComboBaudrate.AddString(_T("57600"));
    m_ComboBaudrate.AddString(_T("115200"));
    m_ComboBaudrate.SetCurSel(0);

连接串口,获取系统中可用的COM:

void CMyDialog::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu)
{
    ports.RemoveAll();
    portse.RemoveAll();
    portsu.RemoveAll();

    for(int i = 1; i < 256; i++)
    {
        CString sPort;
        sPort.Format(_T("\\\\.\\COM%d"), i);

        //Try to open the port
        BOOL bSuccess = FALSE;
        HANDLE hPort = ::CreateFile(sPort, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
        if(hPort == INVALID_HANDLE_VALUE)
        {
            DWORD dwError = GetLastError();

            if(dwError == ERROR_ACCESS_DENIED)
            {
                bSuccess = TRUE;
                portsu.Add(i);    //已占用的串口
            }
        }
        else
        {
            //成功打开端口
            bSuccess = TRUE;
            portse.Add(i);

            //关闭端口
            CloseHandle(hPort);
        }

        //增加端口到数组
        if(bSuccess)
            ports.Add(i);
    }
}

void CMyDialog::AddComm()
{
    EnumerateSerialPorts(ports, portse, portsu);
    unsigned short uicounter;
    unsigned short uisetcom;
    CString str;


    //获取可用串口个数
    uicounter = portse.GetSize();
    //如果个数大于0
    if(uicounter > 0)
    {
        //初始化串口列表框
        for(int i = 0; i < uicounter; i++)
        {
            uisetcom = portse.ElementAt(i);
            str.Format(_T("COM%d "), uisetcom);
            m_ComboSerial.AddString(str);
        }
    }
    m_ComboSerial.SetCurSel(0);
}

 

commComPort类中需要的函数:

写串口:

RetCode CCommPort::ComWriteString(BYTE *pReadBuffer)  
{  
    RetCode res;  
    DWORD iWriteMaxLength;  
    DWORD iWriteLength;  
  
    iWriteMaxLength = strlen( (char*)pReadBuffer );  
    res = WriteData( pReadBuffer, iWriteMaxLength, &iWriteLength );  
  
    return res;  
}  

 

//其中有分析异步同步的操作,不需要异步的可以删掉

RetCode CCommPort::WriteData(BYTE* pBuffer,DWORD iNumberBytesToWrite,DWORD* iNumberBytesWritten)  
{  
    if(!m_bSyncComm && (m_hReadEvent==NULL || m_hStopEvent==NULL))  
    {  
        return ERROR_ASYNCCOMMNOTPREPARED;  
    }  
  
    if(pBuffer==NULL || iNumberBytesToWrite<=0)  
    {  
        return ERROR_BUFFERISNULL;  
    }  
  
    BOOL    bResult;  
    DWORD   dwLastError;  
  
    m_olWriteOverlapped.Offset      = 0;  
    m_olWriteOverlapped.OffsetHigh  = 0;  
    m_olWriteOverlapped.hEvent      = NULL;  
  
    OVERLAPPED* pOverlapped=(!m_bSyncComm) ? &m_olReadOverlapped : NULL;  
  
    DWORD tttt;  
    bResult = WriteFile( m_hCommPort,pBuffer,iNumberBytesToWrite,&tttt,pOverlapped );  
    if ( bResult == FALSE )  
    {  
        dwLastError = GetLastError();  
        if ( dwLastError == ERROR_IO_PENDING )  
        {  
            bResult = GetOverlappedResult( m_hCommPort,pOverlapped,&tttt,TRUE);  
            if ( bResult == FALSE )  
            {  
                return ERROR_GETASYNCWRITERES;  
            }  
        }   
        else   
        {   
            return ERROR_SERIALPORTWRITE;  
        }  
    }  
  
    if(iNumberBytesWritten!=NULL)  
        *iNumberBytesWritten=tttt;  
  
    return Result_OK;  
}  

 

其中RetCode定义为:

enum RetCode{  
            Result_OK,  
            ERROR_ASYNCCOMMNOTPREPARED,  
            ERROR_USERABORT,   
            ERROR_COMNOTOPEN,   
            ERROR_OPENCOMFAIL,   
            ERROR_READCOMFAIL,   
            ERROR_READTIMEOUT,   
            ERROR_SERIALPURGE,   
            ERROR_BUFFERISNULL,   
            ERROR_SETUPCOMFAIL,  
            ERROR_RESETREADEVENT,  
            ERROR_GETCOMSTATEFAIL,   
            ERROR_SETCOMSTATEFAIL,   
            ERROR_SERIALPORTWRITE,  
            ERROR_GETASYNCWRITERES,   
            ERROR_CLEARCOMERRORFAIL,  
            ERROR_SETCOMTIMEOUTFAIL,  
            ERROR_NOTREADENOUGHDATA,   
            ERROR_READOPEREXCEPTION
};

 

 读串口信息:

RetCode CCommPort::ComReadString(BYTE *pReadBuffer, DWORD iReadMaxLength, DWORD* piReadLength, DWORD n_Timeout)  
{  
    RetCode res;  
  
    memset(pReadBuffer, '\0', iReadMaxLength + 1);  
    res = ReadData( pReadBuffer, iReadMaxLength, piReadLength, n_Timeout );  
      
    pReadBuffer[*piReadLength] = '\0';  
    return res;  
      
}  

 

RetCode CCommPort::ReadData(BYTE* pBuffer,DWORD iNumberBytesToRead,DWORD* iNumberBytesRead,DWORD n_Timeout)  
{  
    if(!m_bSyncComm && (m_hReadEvent==NULL || m_hStopEvent==NULL))  
    {  
        return ERROR_ASYNCCOMMNOTPREPARED;  
    }  
  
    if(pBuffer==NULL || iNumberBytesToRead<=0)  
    {  
        return ERROR_BUFFERISNULL;  
    }  
  
    if(!m_bSyncComm)  
    {  
        if ( ResetEvent( m_hReadEvent ) == FALSE )  
        {  
            return ERROR_RESETREADEVENT;  
        }  
    }  
  
    if(iNumberBytesRead!=NULL)  
        *iNumberBytesRead=0;  
  
    m_olReadOverlapped.Offset       = 0;  
    m_olReadOverlapped.OffsetHigh   = 0;  
    m_olReadOverlapped.hEvent       = m_hReadEvent;  
  
    OVERLAPPED* pOverlapped=(!m_bSyncComm) ? &m_olReadOverlapped : NULL;  
  
    DWORD tttt;  
    BOOL res= ReadFile( m_hCommPort,  
        pBuffer,  
        iNumberBytesToRead,  
        &tttt,  
        pOverlapped );  
  
    if ( res == FALSE )  
    {  
        DWORD dwLastError = GetLastError();  
        if ( dwLastError != ERROR_IO_PENDING )  
        {  
            return ERROR_READCOMFAIL;  
        }  
    }  
  
    if(m_bSyncComm)//如果同步通信则直接返回  
    {  
        if(iNumberBytesRead!=NULL)  
            *iNumberBytesRead=tttt;  
  
        if(tttt != 0)  
        {  
            return Result_OK;  
        }  
        /* 
        if(tttt==iNumberBytesToRead) 
            return Result_OK; 
        else 
            return ERROR_NOTREADENOUGHDATA; 
        */  
    }  
  
    HANDLE  ahEventTable[2];  
    ahEventTable[0] = m_hReadEvent;  
    ahEventTable[1] = m_hStopEvent;  
  
    DWORD dwResult = WaitForMultipleObjects( 2, ahEventTable, FALSE, n_Timeout );  
    if ( dwResult == WAIT_TIMEOUT )//读取超时  
    {  
        CancelIo(m_hCommPort);  
        return ERROR_READTIMEOUT;  
    }   
    else  
    {  
        DWORD dwSignalledHandleIndex = dwResult - WAIT_OBJECT_0;  
        switch ( dwSignalledHandleIndex )  
        {  
        case 0://读取到数据  
            GetOverlappedResult(m_hCommPort, &m_olReadOverlapped, &tttt,FALSE);  
            if ( tttt != iNumberBytesToRead )  
            {  
                CancelIo(m_hCommPort);  
                return ERROR_NOTREADENOUGHDATA;  
            }  
  
            if(iNumberBytesRead!=NULL)  
                *iNumberBytesRead=tttt;  
  
            CancelIo(m_hCommPort);  
            return Result_OK;  
  
        case 1://终止读取  
            CancelIo(m_hCommPort);  
            return ERROR_USERABORT;  
  
        default:  
            CancelIo(m_hCommPort);  
            return ERROR_READOPEREXCEPTION;  
        }  
    }  
}  

 

 

 



 

 

 

 主类界面操作:

发送消息到串口:

m_StringSendInfo为发送端的CEdit消息内容

m_StringRecvInfo为发送端的CEdit消息内容

void CSerial_ComputerDlg::SendMessage()  
{  
    int i;  
    BYTE* pBuffer;  
  
    pBuffer = (BYTE*)malloc(MAX_BYTES + 1);  
    memset(pBuffer, '\0', MAX_BYTES + 1);  
  
    UpdateData(TRUE);  
  
    if(m_StringSendInfo == "")    
    {  
        MessageBox(_T("不能发送空数据"));  
        free(pBuffer);  
        return;  
    }  
  
    for(i = 0; i < m_StringSendInfo.GetLength(); i++)  
    {  
        pBuffer[i] = m_StringSendInfo[i];  
    }  
  
    RetCode ret;  
    ret = commComPort.ComWriteString(pBuffer);  
      
    if(ret != Result_OK)  
    {  
        MessageBox(_T("写入数据失败"));  
    }  
    else  
    {  
          
        CTime time;  
        time = CTime::GetCurrentTime();  
        CString temp;  
        if(m_StringRecvInfo != "")  
        {  
            m_StringRecvInfo += "\r\n";  
            m_StringRecvInfo += "\r\n";  
        }  
        temp = "发送: ";  
        m_StringRecvInfo += temp;  
        m_StringRecvInfo += time.Format("%Y-%m-%d  %H:%M:%S");  
        m_StringRecvInfo += "\r\n";  
  
        temp = pBuffer;  
        m_StringRecvInfo += temp;  
        m_StringSendInfo = "";  
  
        UpdateData(FALSE);  
    }  
    free(pBuffer);  
}  

 

从串口接收消息: 

int CSerial_ComputerDlg::RecvMessage()  
{  
    RetCode ret;  
    DWORD iNumberBytesRead = 0;  
    BYTE *pBuffer;  
    CString tempStr;  
  
    ret = commComPort.ComWriteString((BYTE*)"\n");  
  
    CString temp("");  
    CTime time;  
  
    time = CTime::GetCurrentTime();  
    UpdateData(TRUE);  
  
    if(m_StringRecvInfo.GetLength() >= MAX_BYTES)  
    {  
        m_StringRecvInfo.Right(m_StringRecvInfo.GetLength() / 2);  
    }  
  
    pBuffer = (BYTE*)malloc(MAX_BYTES + 1);  
    memset(pBuffer, '\0', MAX_BYTES + 1);  
          
    //ret = pThisDlg->commComPort.ComWriteString((BYTE*)" ");  
    ret = commComPort.ComReadString(pBuffer, MAX_BYTES, &iNumberBytesRead,100);  
      
    if(ret != Result_OK)  
    {  
        cprintf("   Release For ret != Result_OK\n");  
        MessageBox(_T("Read Message Failed!"));  
        free(pBuffer);  
        return -1;  
    }  
          
    temp  = pBuffer;  
      
    temp.Remove(' ');  
    temp.Remove('\n');  
    temp.Remove('\r');  
          
    if(temp.GetLength() != 0)  
    {  
        m_StringRecvInfo += "\r\n\r\n";  
        temp = "接收: ";  
        m_StringRecvInfo += temp;  
        temp = time.Format("%Y-%m-%d  %H:%M:%S");  
        m_StringRecvInfo += temp;  
        m_StringRecvInfo += "\r\n";  
        temp = pBuffer;  
        m_StringRecvInfo += temp;  
          
  
        UpdateData(FALSE);  
        m_EditRecvInfo.LineScroll(m_EditRecvInfo.GetLineCount());//保证接收端的滚动条一直在最下  
  
        MSG msg;  
        while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))  
        {  
            TranslateMessage(&msg);  
            DispatchMessage(&msg);  
        }         
    }  
    free(pBuffer);  
          
    return 0;  
}  


 此代码不支持后台循环读,由于串口的读写具有阻塞性,而尝试过线程去循环读总是阻塞在读上,因此放弃,只实现了发送一次接收一次。

posted on 2013-08-06 18:05  二师兄89  阅读(1985)  评论(0)    收藏  举报