串口编程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; //串口读取回调函数

};

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
书名:《C/C++串口通信典型应用实例编程实践》(电子工业出版社.曹卫杉) PDF扫描版,全书共分10章,共316页。 内容介绍 本书从工程应用的角度出发,对目前流行的三种不同类型的C/C++语言(包括C++ Builder、Visual C++和LabWindows/CVI)开发串口通信(也称为串行通信)程序进行了阐述。 基础篇简单介绍了C/C++语言实现串口通信需要的基本知识;应用篇通过PC与PC、PC与单片机、PC与智能仪器、PC与PLC、PC与GSM短信模块、PC与远程I/O模块等典型应用实例,详细介绍了C/C++语言利用MSComm控件、API函数实现串口通信的程序设计方法。每个实例的设计任务同时采用C++ Builder、Visual C++和Labgrmdows/CVI实现。 本书内容丰富,结构清晰,文字叙述深入浅出,通俗易懂,以实践应用为主,突出程序设计,重在功能实现,有较强的实用性和可操作性。 本书可作为高等院校计算机应用、测控技术、机电一体化、自动化等专业的研究生、本科生以及计算机测控系统研发的工程技术人员等学习C/C++串口通信编程技术的参考书。 目录 基础篇   第1章 串口通信基础   1.1 串口通信的基本概念   1.2 串口通信及其标准   1.3 串口通信调试   第2章 C/C++编程语言与串口通信   2.1 串行通信控件MSComm   2.2 API函数   2.3 线程   2.4 LabWindows/CVI串口通信函数 应用篇   第3章 PC与PC串口通信程序设计   3.1 设计说明   3.2 任务实现   第4章 PC与单片机串口通信程序设计   4.1 设计说明   4.2 任务实现   第5章 PC与智能仪器串口通信程序设计   5.1 设计说明   5.2 任务实现   第6章 PC与PLC串口通信程序设计   6.1 设计说明   6.2 任务实现   第7章 PC与GSM短信模块串口通信程序设计   7.1 设计说明   7.2 任务实现   第8章 PC与读卡器串口通信程序设计   8.1 设计说明   8.2 任务实现   第9章 PC与智能仪器构成的DCS程序设计   9.1 设计说明   9.2 任务实现   第10章 PC与远程I/O模块构成的DCS程序设计   参考文献

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值