zoukankan      html  css  js  c++  java
  • 简单封装的串口通信类

    #include "stdafx.h"
    #include "SerialPort.h"
    
    #include "assert.h"
    
    CSerialPort::CSerialPort()
    {
        memset(&m_OverlappedRead, 0, sizeof(m_OverlappedRead));
        memset(&m_OverlappedWrite, 0, sizeof(m_OverlappedWrite));
        m_bOpened = false;
        m_ReadComThread = NULL;
        m_hIDCom = NULL;
        m_dwReadLen = 0;
    }
    
    CSerialPort::~CSerialPort()
    {
    
    }
    
    BOOL CSerialPort::OpenPort(UINT nPort, UINT nBaud)
    {
        ASSERT(nPort > 0 && nPort < 5);  
        if(m_bOpened)
            return true;
        
        TCHAR szPort[15];
        TCHAR szComParams[50];
        DCB dcb;
    
        wsprintf(szPort, _T("COM%d"), nPort);
        m_hIDCom = ::CreateFile(szPort, 
            GENERIC_READ | GENERIC_WRITE, 
            0, 
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
            NULL);
        if(m_hIDCom == NULL)
            return false;
    
        memset(&m_OverlappedRead, 0, sizeof(OVERLAPPED));
        memset(&m_OverlappedWrite, 0, sizeof(OVERLAPPED));
    
        COMMTIMEOUTS CommTimeOuts;
        CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
        CommTimeOuts.ReadTotalTimeoutConstant = 0;
        CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
        CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
        CommTimeOuts.WriteTotalTimeoutConstant = 5000;
        ::SetCommTimeouts(m_hIDCom, &CommTimeOuts);
    
        wsprintf(szComParams, _T("COM%d:%d,N,8,1"), nPort, nBaud);
        m_OverlappedRead.Offset = 0;
        m_OverlappedRead.OffsetHigh = 0;
        m_OverlappedRead.hEvent = ::CreateEvent(NULL, true, false, NULL);
        m_OverlappedWrite.Offset = 0;
        m_OverlappedWrite.OffsetHigh = 0;
        m_OverlappedWrite.hEvent = ::CreateEvent(NULL, true, false, NULL);
    
        dcb.DCBlength = sizeof(DCB);
        ::GetCommState(m_hIDCom, &dcb);
        dcb.BaudRate = nBaud;
        dcb.ByteSize = 8;
        dcb.Parity = 0;
    
        if(!SetCommState(m_hIDCom, &dcb) || !SetupComm(m_hIDCom, 4096, 4096) ||
            m_OverlappedRead.hEvent == NULL || m_OverlappedWrite.hEvent == NULL)
        {
            DWORD dwError = ::GetLastError();
            if(m_OverlappedRead.hEvent != NULL)
                ::CloseHandle(m_OverlappedRead.hEvent);
            if(m_OverlappedWrite.hEvent != NULL)
                ::CloseHandle(m_OverlappedWrite.hEvent);
            ::CloseHandle(m_hIDCom);
            return false;
        }
        ::SetCommMask(m_hIDCom, EV_RXCHAR);
        ::PurgeComm(m_hIDCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        ::EscapeCommFunction(m_hIDCom, SETDTR);
    
        m_bOpened =true;
        m_bExitThread =false;
    
        StartMonitoring();
        return m_bOpened;
    }
    
    BOOL CSerialPort::Close()
    {
        if(!m_bOpened || m_hIDCom == NULL)
            return true;
        m_bExitThread = true;
        ::SetCommMask(m_hIDCom, 0);
        StopMonitoring();
        
        if(m_OverlappedRead.hEvent != NULL)
            ::CloseHandle(m_OverlappedRead.hEvent);
    
        if(m_OverlappedWrite.hEvent != NULL)
            ::CloseHandle(m_OverlappedWrite.hEvent);
    
        ::CloseHandle(m_hIDCom);
    
        m_bOpened = false;
        m_hIDCom = NULL;
    
        return true;
    }
    
    
    //向串口写数据
    void CSerialPort::WriteToPort(BYTE *Byte, int Len)
    {
        if(!m_bOpened || m_hIDCom == NULL)
            return;
    
        BOOL bWriteStat;
        DWORD dwBytesWritten;
        ClearReadBuf();
        bWriteStat = ::WriteFile(m_hIDCom, Byte, Len, &dwBytesWritten, &m_OverlappedWrite);
    
        if(!bWriteStat && (::GetLastError() == ERROR_IO_PENDING))
        {
            //WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就
            //返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
            //否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。
            DWORD dw = ::WaitForSingleObject(m_OverlappedWrite.hEvent, INFINITE );
            if(dw == WAIT_TIMEOUT)
            {
                dwBytesWritten = 0;
                DCB dcb;
                ::GetCommState(m_hIDCom, &dcb);
                ::PurgeComm(m_hIDCom, PURGE_TXCLEAR);
                return;
            }
            else
            {
                ::GetOverlappedResult(m_hIDCom, &m_OverlappedWrite, &dwBytesWritten, false);//等待服务器完成IO操作
                m_OverlappedWrite.Offset += dwBytesWritten;
            }
        }
        return ;
    }
    
    
    //从串口读取数据
    int CSerialPort::ReadFromPort(BYTE *lpszBlock, int nRLen)
    {
        if(!m_bOpened || m_hIDCom == NULL)
            return 0;
    
        BOOL bReadStat;
        DWORD dwBytesRead, dwErrorFlags;
        COMSTAT ComStat;
        ::ClearCommError(m_hIDCom, &dwErrorFlags, &ComStat);
        if(!ComStat.cbInQue)
            return 0;
    
        dwBytesRead = (DWORD) ComStat.cbInQue;
        if(nRLen < (int)dwBytesRead)
            dwBytesRead = (DWORD) nRLen;
    
        bReadStat = ::ReadFile(m_hIDCom, lpszBlock, dwBytesRead, &dwBytesRead, &m_OverlappedRead);
        if(!bReadStat)
        {
            if(::GetLastError() == ERROR_IO_PENDING)
            {
                ::WaitForSingleObject(m_OverlappedRead.hEvent, INFINITE);
                return (int)dwBytesRead;
            }
            return 0;
        }
        return (int)dwBytesRead;
    }
    
    
    
    UINT CSerialPort::CommThread(LPVOID pParam)
    {
        CSerialPort* pSerialPort = (CSerialPort*)pParam;
        BYTE Buffer[4096];
        DWORD dwEvent, dwError;
        COMSTAT ComStat;
        int ReadLen = 0;
        memset(pSerialPort->m_ReadBuf, '\0', sizeof(pSerialPort->m_ReadBuf));
        ::SetCommMask(pSerialPort->m_hIDCom, EV_RXCHAR);
        while(!pSerialPort->m_bExitThread)
        {
            memset(Buffer, '\0', 4096);
            ::WaitCommEvent(pSerialPort->m_hIDCom, &dwEvent, NULL);
            ::ClearCommError(pSerialPort->m_hIDCom, &dwError, &ComStat);
            if((dwEvent & EV_RXCHAR) && ComStat.cbInQue)
            {
                pSerialPort->m_dwReadLen = pSerialPort->ReadFromPort(Buffer,4096);
                pSerialPort->m_dwReadLen = ReadLen >4096 ? 4096 : ReadLen;
                if(pSerialPort->m_dwReadLen > 0)
                {
                    memcpy(pSerialPort->m_ReadBuf, Buffer,pSerialPort->m_dwReadLen);
                }
            }
            ::PurgeComm(pSerialPort->m_hIDCom, PURGE_RXCLEAR);
        }
        return 0;
    }
    
    BOOL CSerialPort::StartMonitoring()
    {
        if(m_ReadComThread == NULL)
        {
            if(!(m_ReadComThread = ::AfxBeginThread(CommThread, this)))
                return false;
        }
        return true;
    }
    
    BOOL CSerialPort::StopMonitoring()
    {
        if(m_ReadComThread != NULL)
        {
            ::TerminateThread(m_ReadComThread->m_hThread, 0); //终结线程
            m_ReadComThread = NULL;
        }
        return true;
    }
    
    void CSerialPort::ClearReadBuf()
    {
        memset(m_ReadBuf, '\0', sizeof(m_ReadBuf));
        m_dwReadLen = 0;
    }
  • 相关阅读:
    HDU 1501 Zipper(DFS)
    HDU 2181 哈密顿绕行世界问题(DFS)
    HDU 1254 推箱子(BFS)
    HDU 1045 Fire Net (DFS)
    HDU 2212 DFS
    HDU 1241Oil Deposits (DFS)
    HDU 1312 Red and Black (DFS)
    HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
    HDU 1022 Train Problem I(栈)
    HDU 1008 u Calculate e
  • 原文地址:https://www.cnblogs.com/kernel0815/p/2509551.html
Copyright © 2011-2022 走看看