WINCE 5.0 VC++ 串口通信类(修正版)

最近因为工作需要,在网上找了个VC++ 的串口通讯类,修改后编译通过,现在贴出来共享
原文:http://blog.csdn.net/shmilyprince/archive/2008/05/20/2462673.aspx
CESeries.h文件
ExpandedBlockStart.gifCESeries.h
//  CESeries.h: interface for the CCESeries class.
//
/ /

#if  !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)
#define  AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

// 定义串口接收数据函数类型
typedef  void  (CALLBACK *  ONSERIESREAD)(CWnd * ,BYTE *  buf, int  bufLen);

// CE串口通讯类
class  CCESeries  
{
public :
    CCESeries();
    
virtual   ~ CCESeries();

    
// 打开串口
    BOOL OpenPort(CWnd *  pPortOwner,             // 使用串口类,窗体句柄
                  UINT portNo     =   1 ,         // 串口号
                  UINT baud         =   19200 ,         // 波特率
                  UINT parity     =  NOPARITY,  // 奇偶校验
                  UINT databits     =   8 ,         // 数据位
                  UINT stopbits     =   1          // 停止位
                  );
    
// 关闭串口
     void  ClosePort();
    
// 设置串口读取、写入超时
    BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);
    
// 向串口写入数据
    BOOL WritePort( const  BYTE  * buf,DWORD bufLen);
    
// 串口读取回调函数
    ONSERIESREAD m_OnSeriesRead; 

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

    
// 向串口写入数据
     static  BOOL WritePort(HANDLE hComm, const  BYTE  * buf,DWORD bufLen);

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

    
// 已打开的串口句柄
    HANDLE    m_hComm;
    CWnd
*  m_pPortOwner;

    
// 读写线程句柄
    HANDLE m_hReadThread;
    HANDLE m_hWriteThread;

    
// 读写线程ID标识
    DWORD m_dwReadThreadID;
    DWORD m_dwWriteThreadID;

    
// 读线程退出事件
    HANDLE m_hReadCloseEvent;
    
// 写线程退出事件
    HANDLE m_hWriteCloseEvent;
};
#endif  
//  !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)

 

CESeries.cpp 文件

 

ggg
ExpandedBlockStart.gifCESeries.cpp
// CESeries.cpp: implementation of the CCESeries class. 
#include "stdafx.h" 
#include 
"CESeries.h" 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
//定义向写线程发送的消息常量 
const int CM_THREADCOMMWRITE = WM_USER+110
/
// Construction/Destruction 
/
//类CCESeries构造函数 
CCESeries::CCESeries() 

    m_hComm 
= INVALID_HANDLE_VALUE;

//类CCESeries析构函数 
CCESeries::~CCESeries() 


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

    SetEvent(m_hReadCloseEvent); 
    
//设置所有事件无效无效 
    SetCommMask(m_hComm, 0); 
    
//清空所有将要读的数据     
    PurgeComm( m_hComm,  PURGE_RXCLEAR );     
    
//等待10秒,如果读线程没有退出,则强制退出    
    if (WaitForSingleObject(m_hReadThread,10000== WAIT_TIMEOUT)
    { 
        TerminateThread(m_hReadThread,
0);
    } 
    m_hReadThread 
= NULL; 

//关闭写线程 
void CCESeries::CloseWriteThread() 

    SetEvent(m_hWriteCloseEvent); 
    
//清空所有将要写的数据     
    PurgeComm( m_hComm,  PURGE_TXCLEAR );     
    
//等待10秒,如果写线程没有退出,则强制退出     
    if (WaitForSingleObject(m_hWriteThread,10000== WAIT_TIMEOUT) 
    { 
        TerminateThread(m_hWriteThread,
0); 
    } 
    m_hWriteThread 
= NULL; 

/* 
*函数介绍:关闭串口 
*入口参数:(无) 
*出口参数:(无) 
*返回值:  (无) 
*/ 
void CCESeries::ClosePort() 

    
//表示串口还没有打开 
    if (m_hComm == INVALID_HANDLE_VALUE) { return ; } 
    
//关闭读线程 
    CloseReadThread(); 
    
//关闭写线程 
    CloseWriteThread(); 
    
//关闭串口 
    if (!CloseHandle (m_hComm)) 
    { 
        m_hComm 
= INVALID_HANDLE_VALUE; 
        
return ; 
    }

/* 
*函数介绍:设置串口读取、写入超时 
*入口参数:CommTimeOuts : 指向COMMTIMEOUTS结构 
*出口参数:(无) 
*返回值:TRUE:设置成功;FALSE:设置失败 
*/ 
BOOL CCESeries::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts) 

    ASSERT(m_hComm 
!= INVALID_HANDLE_VALUE); 
    
return SetCommTimeouts(m_hComm,&CommTimeOuts); 
}
/* 
*函数介绍:打开串口 
*入口参数:pPortOwner :使用此串口类的窗体句柄    
           portNo :串口号    
           baud :波特率    
           parity :奇偶校验    
           databits :数据位    
           stopbits :停止位 
*出口参数:(无) 
*返回值:TRUE:成功打开串口;
         FALSE:打开串口失败
*/ 
BOOL CCESeries::OpenPort(CWnd
* pPortOwner, /*使用串口类,窗体句柄*/  
                         UINT portNo  , 
/*串口号*/  
                         UINT baud , 
/*波特率*/  
                         UINT parity , 
/*奇偶校验*/  
                         UINT databits  , 
/*数据位*/  
                         UINT stopbits
/*停止位*/

    DCB commParam; 
    TCHAR szPort[
15]; 
    
// 已经打开的话,直接返回 
    if (m_hComm != INVALID_HANDLE_VALUE) 
    { 
        
return TRUE; 
    } 
    ASSERT(pPortOwner 
!= NULL); 
    ASSERT(portNo 
> 0 && portNo< 5); 
    
//设置串口名 
    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) 
    { 
        
// 无效句柄,返回。 
        return FALSE; 
    } 
    
// 得到打开串口的当前属性参数,修改后再重新设置串口。 
    
// 设置串口的超时特性为立即返回。 
    if (!GetCommState(m_hComm,&commParam)) 
    { 
        
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)) { 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 )) 
    { 
        
return FALSE; 
    } 
    m_pPortOwner 
= pPortOwner; 
    
//指定端口监测的事件集 
    SetCommMask (m_hComm, EV_RXCHAR); 
    
//分配设备缓冲区 
    SetupComm(m_hComm,512,512);
    
//初始化缓冲区中的信息 
    PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); 
    m_hReadCloseEvent 
= CreateEvent(NULL,TRUE,FALSE,NULL); 
    m_hWriteCloseEvent 
= CreateEvent(NULL,TRUE,FALSE,NULL); 
    
//创建读串口线程 
    m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID); 
    
//创建写串口线程 
    m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID); 
    
return TRUE; 

//串口读线程函数 
DWORD CCESeries::ReadThreadFunc(LPVOID lparam) 
{
    CCESeries 
*ceSeries = (CCESeries*)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 ; 
                
if (willReadLen  <= 0)
                { 
                    
continue
                } 
                readBuf 
= new BYTE[willReadLen]; 
                ReadFile(ceSeries
->m_hComm, readBuf, willReadLen, &actualReadLen,0); 
                
//如果读取的数据大于0, 
                if (actualReadLen>0) { 
                    
//触发读取回调函数 
                    ceSeries->m_OnSeriesRead(ceSeries->m_pPortOwner,readBuf,actualReadLen);
                }
            }
        } 
        
//如果收到读线程退出信号,则退出线程 
        if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500== WAIT_OBJECT_0)
        { 
            
break
        } 
    }
    
return 0

//串口写线程函数 
DWORD CCESeries::WriteThreadFunc(LPVOID lparam)

    CCESeries 
*ceSeries = (CCESeries*)lparam; 
    MSG msg; DWORD dwWriteLen 
= 0; BYTE * buf= new BYTE();
    
while (TRUE) { 
        
//如果捕捉到线程消息 
        if (PeekMessage(&msg, 000, PM_REMOVE)) 
        { 
            
if (msg.hwnd != 0 ) { 
                TranslateMessage(
&msg); 
                DispatchMessage(
&msg); 
                
continue
            }
            
if (msg.message==CM_THREADCOMMWRITE)
            { 
                
//向串口写 
                buf = (BYTE*)msg.lParam; dwWriteLen = msg.wParam; 
                
//向串口写 
                WritePort(ceSeries->m_hComm,buf,dwWriteLen);
                
//删除动态分配的内存 
                delete[] buf; 
            } 
        } 
        
//如果收到写线程退出信号,则退出线程 
        if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500== WAIT_OBJECT_0) 
        {
            
break
        } 
        ceSeries
->m_hWriteThread = NULL; 
    } 
    
return 0

//私用方法,用于向串口写数据,被写线程调用 
BOOL CCESeries::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen) 

    DWORD dwNumBytesWritten; 
    DWORD dwHaveNumWritten 
=0 ; 
    
//已经写入多少 
    ASSERT(hComm!=INVALID_HANDLE_VALUE);
    CString s(buf);
    AfxMessageBox(s);
    
do { 
        
if (WriteFile (hComm, //串口句柄  
            buf+dwHaveNumWritten, //被写数据缓冲区  
            bufLen - dwHaveNumWritten,  //被写数据缓冲区大小 
            &dwNumBytesWritten, //函数执行成功后,返回实际向串口写的个数 
            NULL))
            
//此处必须设置NULL
        { 
            dwHaveNumWritten 
= dwHaveNumWritten + dwNumBytesWritten; 
            
//写入完成 
            if (dwHaveNumWritten == bufLen) 
            { 
break; } 
            Sleep(
10); 
        } 
        
else { return FALSE; } 
    }
while (TRUE); 
    
return TRUE; 

/* 
*函数介绍:向串口发送数据 
*入口参数:buf : 将要往串口写入的数据的缓冲区    
          bufLen : 将要往串口写入的数据的缓冲区长度 
*出口参数:(无) 
*返回值: TRUE:表示成功地将要发送的数据传递到写线程消息队列。  
          FALSE:表示将要发送的数据传递到写线程消息队列失败。 
注:此处的TRUE,不直接代表数据一定成功写入到串口了。 
*/ 
BOOL CCESeries::WritePort(
const BYTE *buf,DWORD bufLen) 

    
//将要发送的数据传递到写线程消息队列 
    return PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,WPARAM(bufLen), LPARAM(buf)); 

 

示例代码:

m_ceSeries.ClosePort();
m_ceSeries.OpenPort(this,1,19200,NOPARITY,8,1);
CString strUnlogall("UNLOGALL\r\n");

int length=strUnlogall.GetLength();
char *cUnlogall=new char[length+1];
WideCharToMultiByte(CP_ACP, 0, (const unsigned short*)strUnlogall,
-1, cUnlogall, length+1, NULL, NULL);

if (!m_ceSeries.WritePort((BYTE*)cUnlogall,length+1))
{
AfxMessageBox(L"写入失败");
}

转载于:https://www.cnblogs.com/outman2008/archive/2010/01/29/1659104.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值