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


  • 相关阅读:
    C#--带参SQL语句数通用数据访问类
    VS 2017产品密匙
    关于编码中的字符和字节问题
    关于C++中的cin用法
    C++基础(一、基本语法,Hello World)
    Oracle查看用户所在的表空间
    静态变量、枚举、以及静态代码块的使用场景
    Java 枚举(enum) 详解7种常见的用法
    第一章 对象和封装
    摘抄Java反射
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124313.html
Copyright © 2020-2023  润新知