SerialPort类

做个记录自己看。

串口:USB-232(最好使用最新版的驱动)

SerialPort.h

#ifndef __SERIALPORT_H__  
#define __SERIALPORT_H__  
  
#define WM_COMM_BREAK_DETECTED      WM_USER+1     
#define WM_COMM_CTS_DETECTED            WM_USER+2     
#define WM_COMM_DSR_DETECTED            WM_USER+3  
#define WM_COMM_ERR_DETECTED            WM_USER+4     
#define WM_COMM_RING_DETECTED           WM_USER+5     
#define WM_COMM_RLSD_DETECTED           WM_USER+6     
#define WM_COMM_RXCHAR                      WM_USER+7     
#define WM_COMM_RXFLAG_DETECTED     WM_USER+8     
#define WM_COMM_TXEMPTY_DETECTED    WM_USER+9     
  
class CSerialPort  
{  
public:  
    void CloseComm();//2  
    //  
    CSerialPort();  
    virtual     ~CSerialPort();  
  
    //                                        
    BOOL        InitPort(CWnd* pPortOwner, UINT portnr, UINT baud,  
        char parity, UINT databits, UINT stopsbits,  
        DWORD dwCommEvents, UINT nBufferSize);  
  
    //  
    BOOL        StartMonitoring();  
    BOOL        RestartMonitoring();  
    BOOL        StopMonitoring();  
  
    DWORD       GetWriteBufferSize();  
    DWORD       GetCommEvents();  
    DCB         GetDCB();  
  
    void        WriteToPort(char* string);  
protected:  
  
    //   
    void        ProcessErrorMessage(char* ErrorText);  
    static UINT CommThread(LPVOID pParam);  
    static void ReceiveChar(CSerialPort* port, COMSTAT comstat);  
    static void WriteChar(CSerialPort* port);  
  
    //   
    CWinThread*         m_Thread;  
  
    //   
    CRITICAL_SECTION    m_csCommunicationSync;  
    BOOL                m_bThreadAlive;  
  
    //   
    HANDLE              m_hShutdownEvent;  
    HANDLE              m_hComm;  
    HANDLE              m_hWriteEvent;  
  
    //   
    HANDLE              m_hEventArray[3];  
  
    //   
    OVERLAPPED          m_ov;  
    COMMTIMEOUTS        m_CommTimeouts;  
    DCB                 m_dcb;  
  
    //  
    CWnd*               m_pOwner;  
  
    //   
    UINT                m_nPortNr;  
    char*               m_szWriteBuffer;  
    DWORD               m_dwCommEvents;  
    DWORD               m_nWriteBufferSize;  
};  
  
#endif __SERIALPORT_H__  

SerialPort.cpp

#include "stdafx.h"  
#include "SerialPort.h"  
  
#include <assert.h>  
  
  
CSerialPort::CSerialPort()  
{  
    m_hComm = NULL;  
  
  
    m_ov.Offset = 0;  
    m_ov.OffsetHigh = 0;  
  
  
    m_ov.hEvent = NULL;  
    m_hWriteEvent = NULL;  
    m_hShutdownEvent = NULL;  
  
    m_szWriteBuffer = NULL;  
  
    m_bThreadAlive = FALSE;  
}  
  
//  
//  
//  
CSerialPort::~CSerialPort()  
{  
    do  
    {  
        SetEvent(m_hShutdownEvent);  
    } while (m_bThreadAlive);  
  
    TRACE("Thread ended\n");  
  
    delete[] m_szWriteBuffer;  
  
}  
  
//  
//   
//  
BOOL CSerialPort::InitPort(CWnd* pPortOwner,    //   
    UINT  portnr,       //   
    UINT  baud,         //   
    char  parity,       //   
    UINT  databits,     //   
    UINT  stopbits,     //   
    DWORD dwCommEvents, //   
    UINT  writebuffersize)  //   
{  
    assert(portnr > 0 && portnr <= 256);  
    assert(pPortOwner != NULL);  
    unsigned int t = 0;  
    //   
    if (m_bThreadAlive)  
    {  
        MSG message;  
        while (m_bThreadAlive)  
        {  
            if (::PeekMessage(&message, m_pOwner->m_hWnd, 0, 0, PM_REMOVE))  
            {  
                ::TranslateMessage(&message);  
                ::DispatchMessage(&message);  
            }  
            SetEvent(m_hShutdownEvent);  
        }  
  
        TRACE("Thread ended\n");  
    }  
  
    //   
    if (m_ov.hEvent != NULL)  
        ResetEvent(m_ov.hEvent);  
    m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  
    if (m_hWriteEvent != NULL)  
        ResetEvent(m_hWriteEvent);  
    m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  
    if (m_hShutdownEvent != NULL)  
        ResetEvent(m_hShutdownEvent);  
    m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  
    //   
    m_hEventArray[0] = m_hShutdownEvent;    //   
    m_hEventArray[1] = m_ov.hEvent;  
    m_hEventArray[2] = m_hWriteEvent;  
  
    //   
    InitializeCriticalSection(&m_csCommunicationSync);  
  
    //   
    m_pOwner = pPortOwner;  
  
    if (m_szWriteBuffer != NULL)  
        delete[] m_szWriteBuffer;  
    m_szWriteBuffer = new char[writebuffersize];  
  
    m_nPortNr = portnr;  
  
    m_nWriteBufferSize = writebuffersize;  
    m_dwCommEvents = dwCommEvents;  
  
    BOOL bResult = FALSE;  
    char *szPort = new char[50];  
    char *szBaud = new char[50];  
  
    //   
    EnterCriticalSection(&m_csCommunicationSync);  
  
    //   
    if (m_hComm != NULL)  
    {  
        CloseHandle(m_hComm);  
        m_hComm = NULL;  
    }  
  
    //   
    //  
    if (portnr<10)  
    {  
        sprintf(szPort, "COM%d", portnr);  
    }  
    else  
    {  
        sprintf(szPort, "\\\\.\\COM%d", portnr);  
    }  
    sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);  
  
    //  
    m_hComm = CreateFile(szPort,                        //   
        GENERIC_READ | GENERIC_WRITE,   //   
        0,                              //   
        NULL,                           //  
        OPEN_EXISTING,                  //   
        FILE_FLAG_OVERLAPPED,           //  
        0);                         //   
  
    if (m_hComm == INVALID_HANDLE_VALUE)  
    {  
        //   
        delete[] szPort;  
        delete[] szBaud;  
  
        return FALSE;  
    }  
  
    //   
    m_CommTimeouts.ReadIntervalTimeout = 1000;  
    m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;  
    m_CommTimeouts.ReadTotalTimeoutConstant = 1000;  
    m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;  
    m_CommTimeouts.WriteTotalTimeoutConstant = 1000;  
  
    //  
    if (SetCommTimeouts(m_hComm, &m_CommTimeouts))  
    {  
        if (SetCommMask(m_hComm, dwCommEvents))  
        {  
            if (GetCommState(m_hComm, &m_dcb))  
            {  
                m_dcb.fRtsControl = RTS_CONTROL_ENABLE;     //  
                if (BuildCommDCB(szBaud, &m_dcb))  
                {  
  
                    m_dcb.XonLim = 2048;  
                    m_dcb.XoffLim = 2048;  
                    if (SetCommState(m_hComm, &m_dcb))  
                        ; //   
                    else  
                        ProcessErrorMessage("SetCommState()");  
                }  
                else  
                    ProcessErrorMessage("BuildCommDCB()");  
            }  
            else  
                ProcessErrorMessage("GetCommState()");  
        }  
        else  
            ProcessErrorMessage("SetCommMask()");  
    }  
    else  
        ProcessErrorMessage("SetCommTimeouts()");  
  
    delete[] szPort;  
    delete[] szBaud;  
  
    //   
    PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  
    //   
    LeaveCriticalSection(&m_csCommunicationSync);  
  
    TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);  
  
    return TRUE;  
}  
  
//  
//    
//  
UINT CSerialPort::CommThread(LPVOID pParam)  
{  
    //   
    //   
    CSerialPort *port = (CSerialPort*)pParam;  
  
    //   
    //   
    port->m_bThreadAlive = TRUE;  
  
    //   
    DWORD BytesTransfered = 0;  
    DWORD Event = 0;  
    DWORD CommEvent = 0;  
    DWORD dwError = 0;  
    static COMSTAT comstat;  
    BOOL  bResult = TRUE;  
  
    //   
    if (port->m_hComm)       //   
        PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  
    //   
    for (;;)  
    {  
  
  
  
        bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);  
  
        if (!bResult)  
        {  
            //   
            //   
            switch (dwError = GetLastError())  
            {  
            case ERROR_IO_PENDING:  
            {  
                                     //   
                                     //   
                                     //   
                                     break;  
            }  
            case 87:  
            {  
                       //   
                       //   
                       //   
                       break;  
            }  
            default:  
            {  
                       //   
                       //   
                       port->ProcessErrorMessage("WaitCommEvent()");  
                       break;  
            }  
            }  
        }  
        else  
        {  
  
  
            bResult = ClearCommError(port->m_hComm, &dwError, &comstat);  
  
            if (comstat.cbInQue == 0)  
                continue;  
        }   //   
  
        //   
        //   
        Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);  
  
        switch (Event)  
        {  
        case 0:  
        {  
                  //   
                  //   
  
                  port->m_bThreadAlive = FALSE;  
  
                  //   
                  AfxEndThread(100);  
                  break;  
        }  
        case 1: //   
        {  
                    GetCommMask(port->m_hComm, &CommEvent);  
                    if (CommEvent & EV_CTS)  
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);  
                    if (CommEvent & EV_RXFLAG)  
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);  
                    if (CommEvent & EV_BREAK)  
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);  
                    if (CommEvent & EV_ERR)  
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);  
                    if (CommEvent & EV_RING)  
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);  
  
                    if (CommEvent & EV_RXCHAR)  
                        //   
                        ReceiveChar(port, comstat);  
  
                    break;  
        }  
        case 2: //   
        {  
                    //  
                    WriteChar(port);  
                    break;  
        }  
  
        } //   
  
    } //  
  
    return 0;  
}  
  
//  
//   
//  
BOOL CSerialPort::StartMonitoring()  
{  
    if (!(m_Thread = AfxBeginThread(CommThread, this)))  
        return FALSE;  
    TRACE("Thread started\n");  
    return TRUE;  
}  
  
//  
//   
//  
BOOL CSerialPort::RestartMonitoring()  
{  
    TRACE("Thread resumed\n");  
    m_Thread->ResumeThread();  
    return TRUE;  
}  
  
  
//  
//  
//  
BOOL CSerialPort::StopMonitoring()  
{  
    TRACE("Thread suspended\n");  
    m_Thread->SuspendThread();  
    return TRUE;  
}  
  
  
//  
//   
//  
void CSerialPort::ProcessErrorMessage(char* ErrorText)  
{  
    char *Temp = new char[200];  
  
    LPVOID lpMsgBuf;  
  
    FormatMessage(  
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,  
        NULL,  
        GetLastError(),  
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //   
        (LPTSTR)&lpMsgBuf,  
        0,  
        NULL  
        );  
  
    sprintf(Temp, "WARNING:  %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);  
    MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);  
  
    LocalFree(lpMsgBuf);  
    delete[] Temp;  
}  
  
//  
//   
//  
void CSerialPort::WriteChar(CSerialPort* port)  
{  
    BOOL bWrite = TRUE;  
    BOOL bResult = TRUE;  
  
    DWORD BytesSent = 0;  
  
    ResetEvent(port->m_hWriteEvent);  
  
    //   
    EnterCriticalSection(&port->m_csCommunicationSync);  
  
    if (bWrite)  
    {  
        //   
        port->m_ov.Offset = 0;  
        port->m_ov.OffsetHigh = 0;  
  
        //   
        PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  
        bResult = WriteFile(port->m_hComm,                           //   
            port->m_szWriteBuffer,                   //   
            strlen((char*)port->m_szWriteBuffer),    //   
            &BytesSent,                             //   
            &port->m_ov);                            //   
  
        //   
        if (!bResult)  
        {  
            DWORD dwError = GetLastError();  
            switch (dwError)  
            {  
            case ERROR_IO_PENDING:  
            {  
                                     //   
                                     BytesSent = 0;  
                                     bWrite = FALSE;  
                                     break;  
            }  
            default:  
            {  
                       //   
                       port->ProcessErrorMessage("WriteFile()");  
            }  
            }  
        }  
        else  
        {  
            LeaveCriticalSection(&port->m_csCommunicationSync);  
        }  
    } //   
  
    if (!bWrite)  
    {  
        bWrite = TRUE;  
  
        bResult = GetOverlappedResult(port->m_hComm, //   
            &port->m_ov,     //  
            &BytesSent,     //   
            TRUE);          //  
  
        LeaveCriticalSection(&port->m_csCommunicationSync);  
  
        //  
        if (!bResult)  
        {  
            port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");  
        }  
    } //   
  
    //  
    if (BytesSent != strlen((char*)port->m_szWriteBuffer))  
    {  
        TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));  
    }  
}  
  
//  
//   
//  
void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)  
{  
    BOOL  bRead = TRUE;  
    BOOL  bResult = TRUE;  
    DWORD dwError = 0;  
    DWORD BytesRead = 0;  
    unsigned char RXBuff;  
  
    for (;;)  
    {  
        //   
        //  
        //   
  
        EnterCriticalSection(&port->m_csCommunicationSync);  
  
        //   
        //   
  
        bResult = ClearCommError(port->m_hComm, &dwError, &comstat);  
  
        LeaveCriticalSection(&port->m_csCommunicationSync);  
  
  
  
        if (comstat.cbInQue == 0)  
        {  
            //   
            break;  
        }  
  
        EnterCriticalSection(&port->m_csCommunicationSync);  
  
        if (bRead)  
        {  
            bResult = ReadFile(port->m_hComm,        //   
                &RXBuff,                //  
                1,                  //   
                &BytesRead,         //  
                &port->m_ov);        //  
            //  
            if (!bResult)  
            {  
                switch (dwError = GetLastError())  
                {  
                case ERROR_IO_PENDING:  
                {  
                                         //   
                                         //   
                                         bRead = FALSE;  
                                         break;  
                }  
                default:  
                {  
                           //   
                           port->ProcessErrorMessage("ReadFile()");  
                           break;  
                }  
                }  
            }  
            else  
            {  
                //   
                bRead = TRUE;  
            }  
        }  //   
  
        if (!bRead)  
        {  
            bRead = TRUE;  
            bResult = GetOverlappedResult(port->m_hComm, //   
                &port->m_ov,     //   
                &BytesRead,     //  
                TRUE);          //  
  
            //  
            if (!bResult)  
            {  
                port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");  
            }  
        }  //  
  
        LeaveCriticalSection(&port->m_csCommunicationSync);  
  
        //  
        ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM)RXBuff, (LPARAM)port->m_nPortNr);  
    } //  
  
}  
  
//  
//   
//  
void CSerialPort::WriteToPort(char* string)  
{  
    assert(m_hComm != 0);  
    memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));  
    strcpy(m_szWriteBuffer, string);  
  
  
    //   
    SetEvent(m_hWriteEvent);  
}  
  
//  
//   
//  
DCB CSerialPort::GetDCB()  
{  
    return m_dcb;  
}  
  
//  
//   
//  
DWORD CSerialPort::GetCommEvents()  
{  
    return m_dwCommEvents;  
}  
  
//  
//   
//  
DWORD CSerialPort::GetWriteBufferSize()  
{  
    return m_nWriteBufferSize;  
}  
  
  
void CSerialPort::CloseComm()  
{  
    CloseHandle(m_hComm);  
}  





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值