串口编程C++实例(CE) .

* 文件名称:CESeries.cpp

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

#include "StdAfx.h"

#include "CESeries1.h"

 

//HANDLE CCESeries1::m_hComm =  INVALID_HANDLE_VALUE;

//BOOL CCESeries11::m_bOpened = FALSE; //串口是否打开
//构造函数
CCESeries1::CCESeries1()

{

    //初始化内部变量
    m_hComm = INVALID_HANDLE_VALUE;

    m_OnSeriesRead = NULL;

    m_bOpened = 0;
}

 

//析构函数
CCESeries1::~CCESeries1()

{

    if (m_bOpened)

    {
        //关闭串口
        ClosePort();

    }
}

 

//串口读线程函数
DWORD CCESeries1::ReadThreadFunc(LPVOID lparam)

{

    CCESeries1 *ceSeries = (CCESeries1*)lparam;

    
    DWORD    evtMask;

    BYTE * readBuf = NULL;//读取的字节
    DWORD actualReadLen=0;//实际读取的字节数
    DWORD willReadLen;

    
    DWORD dwReadErrors;

    COMSTAT  cmState;

 

    // 清空缓冲,并检查串口是否打开。
    ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE); 

    
    //清空串口
    PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );

    
    SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );

    while (TRUE)

    {   
        if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))

        {           
            SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );

            //表示串口收到字符     

            if (evtMask & EV_RXCHAR) 

            {
                ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);

        //willReadLen = cmState.cbInQue-1 ;

                willReadLen = cmState.cbInQue ;

                if (willReadLen <= 0)
                {
                    continue;

                }
                
                //分配内存
        //readBuf = new BYTE[willReadLen-1];

                readBuf = new BYTE[willReadLen];

                ZeroMemory(readBuf,willReadLen);

                //读取串口数据
                ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);

                
                //如果读取的数据大于,
                if (actualReadLen>0)

                {
        //CString Check;            

        //Check.Format(_T("%d %d"),willReadLen,actualReadLen);

        //AfxMessageBox(Check);

                //触发读取回调函数
                    if (ceSeries->m_OnSeriesRead)

                    {
                        ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);

                        actualReadLen = 0;
                    }
                }
 

                //释放内存
                delete[] readBuf;

                readBuf = NULL;

            }
        }
        //如果收到读线程退出信号,则退出线程
        if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)

        {
            break;

        }
    }
    return 0;
}

 

//关闭读线程
void CCESeries1::CloseReadThread()

{

    SetEvent(m_hReadCloseEvent);

    //设置所有事件无效无效
    SetCommMask(m_hComm, 0);

    //清空所有将要读的数据
    PurgeComm( m_hComm,  PURGE_RXCLEAR );

    //等待秒,如果读线程没有退出,则强制退出
    if (WaitForSingleObject(m_hReadThread,4000) == WAIT_TIMEOUT)

    {
        TerminateThread(m_hReadThread,0);

    }
    m_hReadThread = NULL;

}

 

/*

*函数介绍:打开串口
*入口参数:pPortOwner  :使用此串口类的窗体句柄
            portNo     :串口号
            baud            :波特率
            parity     :奇偶校验
            databits        :数据位
            stopbits        :停止位
*出口参数:(无)

*返回值:TRUE:成功打开串口;FALSE:打开串口失败
*/

BOOL CCESeries1::OpenPort(void * pOwner,

                         UINT portNo  ,           /*串口号*/

                         UINT baud       ,           /*波特率*/

                         UINT parity  ,           /*奇偶校验*/

                         UINT databits    ,           /*数据位*/

                         UINT stopbits               /*停止位*/

                         )
{

    DCB commParam;

    TCHAR szPort[15];  

 

    ASSERT(pOwner!=NULL);

    m_pOwner = pOwner;

    
    // 已经打开的话,直接返回
    if (m_hComm != INVALID_HANDLE_VALUE)

    {
        return TRUE;

    }
    
    //设置串口名
    wsprintf(szPort, L"COM%d:", portNo);

    //打开串口
    m_hComm = CreateFile(

        szPort,

        GENERIC_READ | GENERIC_WRITE,   //允许读和写
        0,                              //独占方式(共享模式)
        NULL,

        OPEN_EXISTING,                       //打开而不是创建(创建方式)
        0,
        NULL 
        );
    
    if (m_hComm == INVALID_HANDLE_VALUE)

    {
        // 无效句柄,返回。     

        TRACE(_T("CreateFile 返回无效句柄/n"));

        return FALSE;

        
    }
    
    memset(&commParam,0,sizeof(DCB));

    // 得到打开串口的当前属性参数,修改后再重新设置串口。
    if (!GetCommState(m_hComm,&commParam))

    {       
        //关闭串口
        CloseHandle (m_hComm);

        m_hComm = INVALID_HANDLE_VALUE;

        return FALSE;

    }
    
    //设置串口参数
    commParam.BaudRate = baud;                    // 设置波特率
    commParam.fBinary = TRUE;                     // 设置二进制模式,此处必须设置TRUE

    commParam.fParity = TRUE;                     // 支持奇偶校验
    commParam.ByteSize = databits;                // 数据位,范围:4-8 

    commParam.Parity = NOPARITY;                  // 校验模式
    commParam.StopBits = stopbits;                // 停止位
    
    commParam.fOutxCtsFlow = FALSE;               // No CTS output flow control 

    commParam.fOutxDsrFlow = FALSE;               // No DSR output flow control 

    commParam.fDtrControl = DTR_CONTROL_ENABLE; 

    // DTR flow control type 

    commParam.fDsrSensitivity = FALSE;            // DSR sensitivity 

    commParam.fTXContinueOnXoff = TRUE;           // XOFF continues Tx 

    commParam.fOutX = FALSE;                      // No XON/XOFF out flow control 

    commParam.fInX = FALSE;                            // No XON/XOFF in flow control 

    commParam.fErrorChar = FALSE;                 // Disable error replacement 

    commParam.fNull = FALSE;                      // Disable null stripping 

    commParam.fRtsControl = RTS_CONTROL_ENABLE; 

    // RTS flow control 

    commParam.fAbortOnError = FALSE;              // 当串口发生错误,并不终止串口读写
    
    //设置串口参数
    if (!SetCommState(m_hComm, &commParam))

    {
        TRACE(_T("SetCommState error")); 

        //关闭串口
        CloseHandle (m_hComm);

        m_hComm = INVALID_HANDLE_VALUE;      

        return FALSE;

    }
    
    //设置串口读写时间
    COMMTIMEOUTS CommTimeOuts;

    GetCommTimeouts (m_hComm, &CommTimeOuts);

    CommTimeOuts.ReadIntervalTimeout = MAXDWORD;  

    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;  

    CommTimeOuts.ReadTotalTimeoutConstant = 0;    

    CommTimeOuts.WriteTotalTimeoutMultiplier = 10;  

    CommTimeOuts.WriteTotalTimeoutConstant = 1000;  

    if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))

    {
        TRACE( _T("SetCommTimeouts 返回错误") );

        //关闭串口
        CloseHandle (m_hComm);

 

        m_hComm = INVALID_HANDLE_VALUE;

        return FALSE;

    }
    
    //指定端口监测的事件集
    SetCommMask (m_hComm, EV_RXCHAR);

    //分配串口设备缓冲区
    SetupComm(m_hComm,512,512);

    //初始化缓冲区中的信息
    PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);

    
    CString strEvent;

    strEvent.Format(L"Com_ReadCloseEvent%d",portNo);

    m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,strEvent);

 

    //创建串口读数据监听线程
    m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);

    
    TRACE(_T("串口打开成功"));

    m_bOpened = TRUE;

    return TRUE;

}

 

/*

*函数介绍:关闭串口
*入口参数:(无)

*出口参数:(无)

*返回值: (无)

*/

void CCESeries1::ClosePort()

{    

    //表示串口还没有打开
    if (m_hComm == INVALID_HANDLE_VALUE)

    {
        return ;
    }
    
    //关闭读线程
    CloseReadThread();

    
    //关闭串口
    CloseHandle (m_hComm);

    //关闭事件
    CloseHandle(m_hReadCloseEvent);

 

    m_hComm = INVALID_HANDLE_VALUE;

    m_bOpened = FALSE;

}

 

/*

*函数介绍:往串口写入数据
*入口参数:buf :待写入数据缓冲区
            bufLen : 待写入缓冲区长度
*出口参数:(无)

*返回值:TRUE:设置成功;FALSE:设置失败
*/

BOOL CCESeries1::WriteSyncPort(const BYTE*buf , DWORD bufLen)

{

    //AfxMessageBox(L"WriteSyncPort Start");

    DWORD dwNumBytesWritten;

    DWORD dwHaveNumWritten =0 ; //已经写入多少
    
    int iInc = 0; //如果次写入不成功,返回FALSE

    ASSERT(m_hComm != INVALID_HANDLE_VALUE);

    do

    {
        if (WriteFile (m_hComm,                       //串口句柄
            buf+dwHaveNumWritten,                //被写数据缓冲区
            //"ABCDEFG",

            bufLen - dwHaveNumWritten,          //被写数据缓冲区大小
            //8,

            &dwNumBytesWritten,                       //函数执行成功后,返回实际向串口写的个数  

            NULL))                                    //此处必须设置NULL

        {
            dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

            //写入完成
            if (dwHaveNumWritten == bufLen)

            {
                break;

            }
            iInc++;

            if (iInc >= 3)
            {
                //AfxMessageBox(L"WriteSyncPort >+3 End");

                return FALSE;

            }
            Sleep(10);

        }
        else

        {
            //AfxMessageBox(L"WriteSyncPort Can Not Open");

            return FALSE;

        }
    }while (TRUE);

    //AfxMessageBox(L"WriteSyncPort End");    

    return TRUE;       

}

 

/*

*函数介绍:设置串口读取、写入超时
*入口参数:CommTimeOuts : 指向COMMTIMEOUTS结构
*出口参数:(无)

*返回值:TRUE:设置成功;FALSE:设置失败
*/

BOOL CCESeries1::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts)

{

    ASSERT(m_hComm != INVALID_HANDLE_VALUE);

    return SetCommTimeouts(m_hComm,&CommTimeOuts);

}

 

 

//得到串口是否打开
BOOL CCESeries1::GetComOpened()

{

    return m_bOpened;

}

 

//END OF FILE-----------------------------------

 

 

* 文件名称:CESeries1.h
/* 文件标识:
* 摘要:用于封装WINCE 串口通信
----------------------------------------*/

#pragma once

//定义串口接收数据函数类型,一个函数指针。
typedef void (CALLBACK* ONSERIESREAD)(void * pOwner /*父对象指针*/

                                      ,BYTE* buf  /*接收到的缓冲区*/

                                      ,DWORD dwBufLen /*接收到的缓冲区长度*/);

 

 

class CCESeries1

{

public:

    CCESeries1(void);

    ~CCESeries1(void);

public:

    //打开串口
    BOOL OpenPort(void* pOwner,/*指向父指针*/

                  UINT portNo = 1,        /*串口号*/

                  UINT baud      = 9600, /*波特率*/

                  UINT parity = NOPARITY, /*奇偶校验*/

                  UINT databits   = 8,        /*数据位*/

                  UINT stopbits   = 0        /*停止位*/

                  );
    //关闭串口
    void ClosePort();

    //同步写入数据
    BOOL WriteSyncPort(const BYTE*buf , DWORD bufLen);

    //设置串口读取、写入超时
    BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);

    //得到串口是否打开
    BOOL GetComOpened();

private:

    //串口读线程函数
    static  DWORD WINAPI ReadThreadFunc(LPVOID lparam);

private:

    //关闭读线程
    void CloseReadThread();

private:

    //已打开的串口句柄
    //static HANDLE    m_hComm;

    //HANDLE m_hComm;

    //读线程句柄
    HANDLE m_hReadThread;

    //读线程ID标识
    DWORD m_dwReadThreadID;

    //读线程退出事件
    HANDLE m_hReadCloseEvent;

    //static BOOL m_bOpened; //串口是否打开
    BOOL m_bOpened;

    void * m_pOwner; //指定父对象指针
public:

    HANDLE   m_hComm;

    ONSERIESREAD m_OnSeriesRead; //串口读取回调函数
};

 

 



原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124313.html