PC 串口通信

这是基于Window SDK封装的串口通信类

// Serial.h

#ifndef __SERIAL_H__
#define __SERIAL_H__

// 
#define DEBUG_VERSION

// 用户消息
#define MSG_SERIAL_OUTPUT_DEBUG         WM_USER+123     // 输出调试信息消息  (说明:消息第一个参数为调试信息串指针,响应这个消息可以知道处理进度)

#define FC_DTRDSR       0x01
#define FC_RTSCTS       0x02
#define FC_XONXOFF      0x04
#define ASCII_BEL       0x07
#define ASCII_BS        0x08
#define ASCII_LF        0x0A
#define ASCII_CR        0x0D
#define ASCII_XON       0x11
#define ASCII_XOFF      0x13

#define CLEAR_IN_BUFFER     0x01
#define CLEAR_OUT_BUFFER    0x02

//#define PACK_SIZE 2048
#define PACK_SIZE  1024   //modify zp

class CSerial
{
public:
    CSerial();
    ~CSerial();

    BOOL    IsOpened(void){ return m_bOpened; }
    BOOL    Open( int nPort, int nBaud, HWND hWndUser=NULL );
    BOOL    Close( void );
    int     WriteData( void *, int );
    int     ReadData ( void *, int );

    void    ClearBuffer(int iFlag);
    void    Flush();

    int MySendData(BYTE* btSendData,int iLen,int iTimeOut,BYTE* byRecvBuf);
    int MySendReadData(BYTE* btSendData,int iLen,int iTimeOut,BYTE* byRecvBuf);//add zp
protected:
    void    OutputDebug( TCHAR * pText );


    HANDLE  m_hComDev;
    BOOL    m_bOpened;

    HWND    m_hWndUser;
};

#endif

实现文件 .cpp

// Serial.cpp

#include "stdafx.h"
#include "Serial.h"

CSerial::CSerial()
{
    m_hComDev = NULL;
    m_bOpened = FALSE;

    m_hWndUser = NULL;
}

CSerial::~CSerial()
{
    Close();
}

/*-----------------------------------------------------------------------------

  功    能:输出调试信息

  参数说明:char * pText  信息串

  返 回 值:无

  说    明:

------------------------------------------------------------------------------*/
void CSerial::OutputDebug( TCHAR * pText )
{
    if( m_hWndUser==NULL || pText==NULL )
        return;

    // 发送调试信息
    SendMessage( m_hWndUser, MSG_SERIAL_OUTPUT_DEBUG, (WPARAM)pText, 0 );
}

BOOL CSerial::Open( int nPort, int nBaud, HWND hWndUser )
{
    DWORD dwError = 0;
    TCHAR  szError[128] = {0};

    m_hWndUser = hWndUser;

    if(m_bOpened) 
        return TRUE;

    TCHAR szPort[32];
    TCHAR sszPort[32];
    _stprintf_s(sszPort, _T("\\\\.\\COM%d"), nPort);
    _stprintf_s( szPort,_T("\\\\.\\COM%d:"), nPort );

    // 创建一个串口设备                                                          
    m_hComDev = CreateFile(  sszPort,                                           
                             GENERIC_READ | GENERIC_WRITE,      //访问模式(写/读)             
                             0,                 //共享模式                              
                             NULL,                          //指向安全属性的指针                 
                             OPEN_EXISTING,                                     
                             NULL,                                                  
                             NULL );                                            
    // 判断创建是否成功
    //if((DWORD)m_hComDev==0xffffffff || (DWORD)m_hComDev==NULL)                    
    if(m_hComDev == INVALID_HANDLE_VALUE)
    {
//      dwError = GetLastError();                                               
//      _stprintf( szError, _T("Open COM%d with baud rate %d failed, error = %d"), nPort, nBaud, dwError );
//      MessageBox( NULL, szError, _T("error"), MB_OK);

        return FALSE;
    }

    //_stprintf( szError, _T("Open COM%d with baud rate %d success."), nPort, nBaud );
    //OutputDebug( szError );

    // 填写通讯设备控制结构
    DCB dcb;                                                                    
    dcb.DCBlength = sizeof( DCB );
    GetCommState( m_hComDev, &dcb );                                                            

    dcb.BaudRate = nBaud;
    dcb.ByteSize = 8;                                                           
    dcb.Parity   = NOPARITY;                                                    
    dcb.StopBits = ONESTOPBIT;  // 原来的                                              
    //dcb.StopBits = TWOSTOPBITS;// 潘相熙更改2008-1-15                                                  

    // 控制设置
    if( !SetCommState( m_hComDev, &dcb ) || !SetupComm( m_hComDev,1024*3,1024*3))   
    {                                                                           
        dwError = GetLastError();                                               
        _stprintf_s( szError, _T("SetCommState failed, error = %d"), dwError );
        OutputDebug( szError );

        CloseHandle(m_hComDev);                                                 
        return FALSE;                                                           
    }                                                                           

    // 填写通讯超时参数
    COMMTIMEOUTS CommTimeOuts;                                                  

    CommTimeOuts.ReadIntervalTimeout         = MAXDWORD;                        
    CommTimeOuts.ReadTotalTimeoutMultiplier  = 11*1000/dcb.BaudRate+1;          
    CommTimeOuts.ReadTotalTimeoutConstant    = 40;                              
    CommTimeOuts.WriteTotalTimeoutMultiplier = 11*1000/dcb.BaudRate+1;          
    //CommTimeOuts.WriteTotalTimeoutConstant   = 0;
    CommTimeOuts.WriteTotalTimeoutConstant   = 1000;//modify zp

    // 超时设置
    if(!SetCommTimeouts( m_hComDev, &CommTimeOuts ))
    {
        dwError = GetLastError();
        _stprintf_s( szError, _T("SetCommTimeouts failed, error = %d"), dwError );
        OutputDebug( szError );

        CloseHandle(m_hComDev);
        return FALSE;
    }

    m_bOpened = TRUE;
    return m_bOpened;
}

BOOL CSerial::Close( void )
{
    if( !m_bOpened || m_hComDev == NULL)
        return TRUE;

    ClearBuffer(CLEAR_IN_BUFFER);
    ClearBuffer(CLEAR_OUT_BUFFER);

    CloseHandle( m_hComDev );
    m_bOpened = FALSE;
    m_hComDev = NULL;

    return TRUE;
}

// 函数功能:往串口写一串字符
int CSerial::WriteData( void *buffer, int size )
{
    if( !m_bOpened || m_hComDev == NULL )
        return -1;

    DWORD dwError = 0;
    TCHAR  szError[128] = {0};

    BYTE * pBuf = (BYTE*)buffer;
    BOOL  bWriteSuccess;
    DWORD dwBytesWritten;

    bWriteSuccess = WriteFile(  m_hComDev,  
                                (LPSTR) pBuf,
                                size,   
                                &dwBytesWritten,
                                NULL );
    if( !bWriteSuccess )                                                            
    {
        dwError = GetLastError();
        _stprintf_s( szError, _T("WriteFile failed, error = %d"), dwError );
        OutputDebug( szError );

        return -1;
    }

    return( (int)dwBytesWritten );
}

// 函数功能:从串口读一串字符
int CSerial::ReadData( void *receBuf, int limit )
{
    if( !m_bOpened || m_hComDev == NULL )
        return -1;

    DWORD dwError = 0;
    TCHAR  szError[128] = {0};

    BOOL  bReadSuccess;
    DWORD dwBytesToRead, dwBytesRead, dwErrorFlags;
    COMSTAT ComStat;

    if( !ClearCommError( m_hComDev, &dwErrorFlags, &ComStat ) )                     
    {
        dwError = GetLastError();
        _stprintf_s( szError, _T("ClearCommError failed, error = %d"), dwError );
        OutputDebug( szError );

        return -1;
    }
    if( !ComStat.cbInQue )  //  串口中有多少数据可以读                                         
        return 0;

    dwBytesToRead = min( ComStat.cbInQue, (DWORD)limit );

    bReadSuccess = ReadFile( m_hComDev,
                             receBuf,
                             dwBytesToRead,
                             &dwBytesRead,
                             NULL );
    if(!bReadSuccess)                                                           
    {
        dwError = GetLastError();
        _stprintf_s( szError, _T("ReadFile failed, error = %d"), dwError );
        OutputDebug( szError );

        return -1;
    }

    return((int)dwBytesRead);
}

void CSerial::ClearBuffer(int iFlag)
{
    if(iFlag & CLEAR_IN_BUFFER)
        PurgeComm(m_hComDev, PURGE_RXCLEAR);

    if(iFlag & CLEAR_OUT_BUFFER)
        PurgeComm(m_hComDev, PURGE_TXCLEAR);
}

void CSerial::Flush()
{
    if (m_hComDev)
    {
        FlushFileBuffers(m_hComDev);
    }
}

int CSerial::MySendData(BYTE* btSendData,int iLen,int iTimeOut,BYTE* byRecvBuf)
{
    int iRet = 0;
    for (int i = 0 ; i < 3 ; i ++)
    {
        memset(byRecvBuf, 0, PACK_SIZE);
        ClearBuffer(CLEAR_IN_BUFFER);
        int iSend = WriteData(btSendData, iLen);
        if(iSend <= 0)
        {
            Sleep(100);
            continue;;
        }       
        DWORD dwStart = ::GetTickCount();
        while(1)
        {
            iRet = ReadData(byRecvBuf, PACK_SIZE);
            if(iRet > 0)
            {
                if((iRet > 2)&&((byRecvBuf[2]&0xF0)==0xE0))
                    return -1;//否定回答
                Sleep(1);
                return iRet;
            }
            DWORD dwEnd = ::GetTickCount();
            if((dwEnd - dwStart) > iTimeOut)
                break;
        }
    }
    return iRet;
}

int CSerial::MySendReadData(BYTE* btSendData,int iLen,int iTimeOut,BYTE* byRecvBuf)
{
    int iRet = 0;
    while(1)
    {
        memset(byRecvBuf, 0, PACK_SIZE);
        ClearBuffer(CLEAR_IN_BUFFER);
        int iSend = WriteData(btSendData, iLen);
        if(iSend <= 0)
        {
            Sleep(100);
            continue;
        }       
        DWORD dwStart = ::GetTickCount();
        while(1)
        {
            iRet = ReadData(byRecvBuf, PACK_SIZE);
            if(iRet > 0)
            {
                if((iRet > 2)&&((byRecvBuf[2]&0xF0)==0xE0))
                    return -1;//否定回答
                Sleep(1);
                return iRet;
            }
            DWORD dwEnd = ::GetTickCount();
            if((dwEnd - dwStart) > iTimeOut)
                break;
        }
    }
    return iRet;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值