您的位置:首页 > 编程语言 > C语言/C++

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

2011-10-11 22:48 381 查看
* 文件名称: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; //串口读取回调函数
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: