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

来源:互联网 发布:windows平板电脑吧 编辑:程序博客网 时间:2024/04/29 15:54

* 文件名称: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; //串口读取回调函数

};

 

 

 

原创粉丝点击