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;
    }
  • 相关阅读:
    使用Java和JS访问cookies
    详细介绍Java内存泄露原因
    Java与Unicode
    电子商务那点事
    request的一些常用方法
    一些java当中的名词解释
    rpc远程服务
    war包和jar包的区别
    为什么内存贵硬盘便宜
    分层开发的优势
  • 原文地址:https://www.cnblogs.com/kernel0815/p/2509551.html
Copyright © 2011-2022 走看看