BOOL OnInit()
{
m_nBaud=115200;//数据传输速率
m_nDataBits=8;//数据位
m_nParity=0;//校验位
m_nStopBits=0;//停止位
memset(&m_osRead,0,sizeof(OVERLAPPED));
memset(&m_osWrite,0,sizeof(OVERLAPPED));
m_isconnect=FALSE;
m_isreceive=FALSE;
m_rxlen=0;
if (ComOpen()==FALSE)
{
return FALSE;
}
unsigned int threadid;
m_pThread=(HANDLE)_beginthreadex(NULL,0,ComProce,0,0,&threadid);
// CloseHandle(m_pThread);
if(m_pThread==NULL)
{
CloseHandle(m_hCom);
return FALSE;
}
return TRUE;
}unsigned _stdcall ComProce(void* pParam)
{
// AfxMessageBox("建立线程开始!");
OVERLAPPED os;
DWORD dwMask;//dwTrans;
COMSTAT ComStat;
DWORD dwErrorFlags;
// m_ThredConnected=pDlg->m_bConnected;
memset(&os,0,sizeof(OVERLAPPED));
os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(os.hEvent==NULL)
{
//AfxMessageBox(L"不能建立事件对象!");
//return (UINT)-1;
return FALSE;
}
if (m_bConnected==TRUE)
{
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
if (ComStat.cbInQue)
{
ProcessCOMMNotification(EV_RXCHAR,0);
}
// AfxMessageBox("no data in!");
dwMask=0;
if(!WaitCommEvent(m_hCom,&dwMask,NULL))
{
// AfxMessageBox("wait event");
if(GetLastError()==ERROR_IO_PENDING)
{ }
else
{
CloseHandle(os.hEvent);
//return(UINT)-1;
return FALSE;
}
}
CloseHandle(os.hEvent);
}
return TRUE;
}BOOL ProcessCOMMNotification (UCHAR wParam,UCHAR lParam)
{
if((EV_RXCHAR&wParam)!=EV_RXCHAR)
return FALSE;
unsigned char abIn[MAXBLOCK];
BOOL len=ReadBlock(abIn,MAXBLOCK);
if(!len)
{
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
memcpy(turndata,abIn,sizeof(abIn));
memset(abIn,NULL,sizeof(abIn));
return TRUE;
}
BOOL ComOpen()
{
m_hCom=CreateFile("COM3",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,
0,NULL);
if(m_hCom==INVALID_HANDLE_VALUE)
{
return FALSE;
}
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_osRead.hEvent==NULL)
{
return FALSE;
}
m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_osWrite.hEvent==NULL)
{
return FALSE;
}
if (ConfigCom()!=0)
{
m_isconnect=TRUE;
m_bConnected=TRUE;
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ConfigCom()
{
//SetupComm(m_hCom,1024,1024);
//设置工作者线程响应的事件
SetCommMask(m_hCom,EV_RXCHAR);
//设置读写缓冲区
SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
COMMTIMEOUTS Timeouts;
//DCB dcb;
Timeouts.ReadIntervalTimeout=50;
Timeouts.ReadTotalTimeoutConstant=500;
Timeouts.ReadTotalTimeoutMultiplier=50;
Timeouts.WriteTotalTimeoutConstant=500;
Timeouts.WriteTotalTimeoutMultiplier=50;
SetCommTimeouts(m_hCom,&Timeouts);
DCB dcb;
if(!GetCommState(m_hCom, &dcb))
return FALSE;
dcb.fBinary=TRUE;
dcb.BaudRate = m_nBaud; // 数据传输速率
dcb.ByteSize = m_nDataBits; // 每字节位数
dcb.fParity = TRUE;
switch(m_nParity) // 校验设置
{
case 0:
dcb.Parity=NOPARITY;
break;
case 1:
dcb.Parity=EVENPARITY;
break;
case 2:
dcb.Parity=ODDPARITY;
break;
default:;
}
switch(m_nStopBits) // 停止位
{
case 0:
dcb.StopBits=ONESTOPBIT;
break;
case 1:
dcb.StopBits=ONE5STOPBITS;
break;
case 2:
dcb.StopBits=TWOSTOPBITS;
break;
default:;
}
// 硬件流控制设置
dcb.fOutxCtsFlow = FALSE;
dcb.fRtsControl = FALSE;
return SetCommState(m_hCom, &dcb);
}
BOOL ReadBlock(unsigned char *abIn, int MaxLength)
{ memset(abIn,NULL,MaxLength);
DWORD wCount=100;//读取的字节数
BOOL bReadStat;
bReadStat=ReadFile(m_hCom,abIn,wCount,&wCount,NULL);
if(!bReadStat)
{
//cout<<"读串口失败!"<<endl;
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
//PurgeComm(m_hCom, PURGE_TXABORT|
//PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
// cout<<str<<endl;
return TRUE;
// UpdateData(FALSE);
}BOOL WriteBlock(unsigned char *abOut, int MaxLength)
{
DWORD dwErrorFlags,dwLength,lentest;
dwLength=MaxLength;
COMSTAT ComStat;
lentest=0;
BOOL bWriteStat;
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);//一到这里就挂了
bWriteStat=WriteFile(m_hCom,abOut,dwLength,&lentest,NULL);
if(!bWriteStat)
{
//cout<<"写串口失败!"<<endl;
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
return TRUE;
}BOOL Openlight()
{
unsigned char abOut[MAXBLOCK];
abOut[0]=0x1b;
abOut[1]=0x3e;
abOut[2]=0x61;
if (WriteBlock(abOut,3)<=0)
{
//cout<<"写入失败"<<endl;
//CloseConnection();
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
return TRUE;
}Openlight()是dll导出函数,调试到ClearCommError(m_hCom,&dwErrorFlags,&ComStat)就挂了,进不去了,是不是线程开的有问题啊 各位大哥小弟第一次做串口?那位大哥能解决或是能给相应的例子多线程读串口的例子小弟一定重分酬谢!
{
m_nBaud=115200;//数据传输速率
m_nDataBits=8;//数据位
m_nParity=0;//校验位
m_nStopBits=0;//停止位
memset(&m_osRead,0,sizeof(OVERLAPPED));
memset(&m_osWrite,0,sizeof(OVERLAPPED));
m_isconnect=FALSE;
m_isreceive=FALSE;
m_rxlen=0;
if (ComOpen()==FALSE)
{
return FALSE;
}
unsigned int threadid;
m_pThread=(HANDLE)_beginthreadex(NULL,0,ComProce,0,0,&threadid);
// CloseHandle(m_pThread);
if(m_pThread==NULL)
{
CloseHandle(m_hCom);
return FALSE;
}
return TRUE;
}unsigned _stdcall ComProce(void* pParam)
{
// AfxMessageBox("建立线程开始!");
OVERLAPPED os;
DWORD dwMask;//dwTrans;
COMSTAT ComStat;
DWORD dwErrorFlags;
// m_ThredConnected=pDlg->m_bConnected;
memset(&os,0,sizeof(OVERLAPPED));
os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(os.hEvent==NULL)
{
//AfxMessageBox(L"不能建立事件对象!");
//return (UINT)-1;
return FALSE;
}
if (m_bConnected==TRUE)
{
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
if (ComStat.cbInQue)
{
ProcessCOMMNotification(EV_RXCHAR,0);
}
// AfxMessageBox("no data in!");
dwMask=0;
if(!WaitCommEvent(m_hCom,&dwMask,NULL))
{
// AfxMessageBox("wait event");
if(GetLastError()==ERROR_IO_PENDING)
{ }
else
{
CloseHandle(os.hEvent);
//return(UINT)-1;
return FALSE;
}
}
CloseHandle(os.hEvent);
}
return TRUE;
}BOOL ProcessCOMMNotification (UCHAR wParam,UCHAR lParam)
{
if((EV_RXCHAR&wParam)!=EV_RXCHAR)
return FALSE;
unsigned char abIn[MAXBLOCK];
BOOL len=ReadBlock(abIn,MAXBLOCK);
if(!len)
{
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
memcpy(turndata,abIn,sizeof(abIn));
memset(abIn,NULL,sizeof(abIn));
return TRUE;
}
BOOL ComOpen()
{
m_hCom=CreateFile("COM3",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,
0,NULL);
if(m_hCom==INVALID_HANDLE_VALUE)
{
return FALSE;
}
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_osRead.hEvent==NULL)
{
return FALSE;
}
m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_osWrite.hEvent==NULL)
{
return FALSE;
}
if (ConfigCom()!=0)
{
m_isconnect=TRUE;
m_bConnected=TRUE;
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ConfigCom()
{
//SetupComm(m_hCom,1024,1024);
//设置工作者线程响应的事件
SetCommMask(m_hCom,EV_RXCHAR);
//设置读写缓冲区
SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
COMMTIMEOUTS Timeouts;
//DCB dcb;
Timeouts.ReadIntervalTimeout=50;
Timeouts.ReadTotalTimeoutConstant=500;
Timeouts.ReadTotalTimeoutMultiplier=50;
Timeouts.WriteTotalTimeoutConstant=500;
Timeouts.WriteTotalTimeoutMultiplier=50;
SetCommTimeouts(m_hCom,&Timeouts);
DCB dcb;
if(!GetCommState(m_hCom, &dcb))
return FALSE;
dcb.fBinary=TRUE;
dcb.BaudRate = m_nBaud; // 数据传输速率
dcb.ByteSize = m_nDataBits; // 每字节位数
dcb.fParity = TRUE;
switch(m_nParity) // 校验设置
{
case 0:
dcb.Parity=NOPARITY;
break;
case 1:
dcb.Parity=EVENPARITY;
break;
case 2:
dcb.Parity=ODDPARITY;
break;
default:;
}
switch(m_nStopBits) // 停止位
{
case 0:
dcb.StopBits=ONESTOPBIT;
break;
case 1:
dcb.StopBits=ONE5STOPBITS;
break;
case 2:
dcb.StopBits=TWOSTOPBITS;
break;
default:;
}
// 硬件流控制设置
dcb.fOutxCtsFlow = FALSE;
dcb.fRtsControl = FALSE;
return SetCommState(m_hCom, &dcb);
}
BOOL ReadBlock(unsigned char *abIn, int MaxLength)
{ memset(abIn,NULL,MaxLength);
DWORD wCount=100;//读取的字节数
BOOL bReadStat;
bReadStat=ReadFile(m_hCom,abIn,wCount,&wCount,NULL);
if(!bReadStat)
{
//cout<<"读串口失败!"<<endl;
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
//PurgeComm(m_hCom, PURGE_TXABORT|
//PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
// cout<<str<<endl;
return TRUE;
// UpdateData(FALSE);
}BOOL WriteBlock(unsigned char *abOut, int MaxLength)
{
DWORD dwErrorFlags,dwLength,lentest;
dwLength=MaxLength;
COMSTAT ComStat;
lentest=0;
BOOL bWriteStat;
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);//一到这里就挂了
bWriteStat=WriteFile(m_hCom,abOut,dwLength,&lentest,NULL);
if(!bWriteStat)
{
//cout<<"写串口失败!"<<endl;
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
return TRUE;
}BOOL Openlight()
{
unsigned char abOut[MAXBLOCK];
abOut[0]=0x1b;
abOut[1]=0x3e;
abOut[2]=0x61;
if (WriteBlock(abOut,3)<=0)
{
//cout<<"写入失败"<<endl;
//CloseConnection();
PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
return FALSE;
}
return TRUE;
}Openlight()是dll导出函数,调试到ClearCommError(m_hCom,&dwErrorFlags,&ComStat)就挂了,进不去了,是不是线程开的有问题啊 各位大哥小弟第一次做串口?那位大哥能解决或是能给相应的例子多线程读串口的例子小弟一定重分酬谢!
去掉这句 写串口不用这句 只有读的时候用
看看这个串口的同步接收例子吧http://www.vckbase.com/document/viewdoc/?id=1734
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_MYCOM_H__BF6B4ECC_762F_48D2_9365_F123560D9CAA__INCLUDED_)
#define AFX_MYCOM_H__BF6B4ECC_762F_48D2_9365_F123560D9CAA__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000#include <afxmt.h>// flow control
#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04#define ASCII_XON 0x11
#define ASCII_XOFF 0x13class MyCom;
typedef struct _CONNECTION
{
HANDLE hCommDev; //当前的通讯连接句柄
HANDLE hEventCancel;//当前退出信号事件
DWORD dwRefCount; //当前通讯连接的引用次数
MyCom* pCom; //MyCom类对象指针
OVERLAPPED olWrite; //写重叠I/O对象
OVERLAPPED olRead; //读重叠I/O对象
CCriticalSection CSec; //当前结构支持多线程访问的互拆量
}CONNECTION, *LPCONNECTION;
typedef const CONNECTION* LPCCONNECTION;typedef struct _COMM_INFO{
BYTE byCommPort; //通讯端口名称,可为COM1-4
BYTE byByteSize; //数据位数,必须为8
BYTE byParity; //奇偶检验方式,必须为0
BYTE byStopBits; //停止位,必须为1
DWORD dwBaudRate; //波特率,必须为38400
BYTE byXonXoff;
BYTE byFlowCtrl; //流控制方式
}COMM_INFO;//当前用到的串口通讯处理状态
typedef enum{
PS_NOREADY, //当前状态还没定(初始状态)
PS_READY, //当前处于就绪状态
PS_WAITTING, //当前处理数据等待状态
PS_RECEIVINGDATA, //当前正在接收数据
PS_RECEIVED_FAULT //当前接收数据错误
}PROCESS_STATUS;class MyCom
{
public:
enum{
//当前与通信缓存区一次性最多读取数据的内存缓存大小
MAX_BUF_BLOCK = 128,
//异常终止当前在打开的端口上正进行的输入和输出操作类型
PURGE_FLAG = PURGE_TXABORT | PURGE_RXABORT
| PURGE_TXCLEAR | PURGE_RXCLEAR,
//当前串口的通信时需要串口通知的事件类型
COMM_MASK = EV_RXCHAR,
//当前最长等待时间(毫秒)
MAX_WAITTING = 500,
//当前最小等待时间(毫秒)
MIN_WAITTING = 100,
//重新连接同一串时的时间间隔
RECONNECT_TIME = 1000
};
//当前串口的设置信息
COMM_INFO m_CommInfo;
CONNECTION m_Connection; MyCom();
virtual ~MyCom(); //建立当前的通讯连接
virtual BOOL Connect();
//重新建立当前的通讯连接
virtual BOOL ReConnect();
//取消当前的通讯连接
virtual void DisConnect();
//初始化当前的串口信息
virtual BOOL InitCommInfo();
//处理接收回来的数据
virtual void ProcessReceivedData(LPCSTR lpcByte/*从串口接收回来的数据*/,
DWORD dwDataLenght/*从串口接收回来的数据的长度*/);
//向串口发送数据
virtual BOOL WriteData2Comm(LPCSTR lpcByte/*想要写入串口的数据*/,
DWORD dwDataLenght/*想要写入串口的数据的长度*/); //当前的通讯端口监听线程函数
static UINT CommMonitorProc(void* pData/*主线程传递给监听(接收)线程的参数*/);
//读取当前通讯端口缓存中的数据
static UINT CommReadBlock(HANDLE hFile/*打开的串口文件句柄*/,
LPOVERLAPPED lpOL/*用于读串口时的异步通讯事件*/,
LPSTR lpszBlock/*用于读串口数据的缓存区*/,
UINT nMaxLength/*用于读串口数据的缓存区的大小*/);
//向当前通讯端口发送数据
static BOOL CommWriteBlock(HANDLE hFile/*打开的串口文件句柄*/,
LPCSTR lpcByte/*想要写往串口的数据*/,
DWORD dwBytesToWrite/*想要写往串口的数据的字节数*/,
OVERLAPPED *pOLWrite/*用于写串口时的异步通讯事件*/);
//获取当前的通讯连接指针,并锁定于当前线程
//(此函数必须与UnLockConnection()配对调用, 时间间隔不宜太久)
LPCONNECTION LockConnection();
//释放当前的通讯连接指针(解除当前线程的锁定)
//(此函数必须与LockConnection()配对调用, 时间间隔不宜太久)
void UnLockConnection(); //判断当前的通讯连接是否已经建立
BOOL IsConnected();
//设定当前的处理状态
inline void SetProcessStatus(PROCESS_STATUS ePStatus)
{m_ePStatus = ePStatus;}
//获取当前的处理状态
inline PROCESS_STATUS GetProcessStatus()
{return m_ePStatus;}
//将当前对象锁定于当前线程
BOOL LockThread(){return m_CSec.Lock();}
//将当前对象解锁于当前线程
void UnlockThread(){m_CSec.Unlock();}protected:
//当前通讯对象的通讯连接状态(true连接, false不连接)
volatile BOOL m_bConnected;
//当前的监听线程句柄
HANDLE m_hMonitorThread;
//当前线程通讯所处于的状态
volatile PROCESS_STATUS m_ePStatus;
//当前对象用于线程互锁的的临界量
CCriticalSection m_CSec; //获取当前的通讯端口名称
CString GetCommName();
//根据串口的序号获取当前串口的名称
CString GetCommName(BYTE bySN);
//设定当前延时处理
void DelayReply(DWORD dwTime);private:
//设定当前串口的通信参数
BOOL SetCommState(HANDLE hFile);
//设置当前串口的读写超时
BOOL SetCommTimeouts(HANDLE hFile);
//打开串口
BOOL OpenComm(HANDLE &hFile);
};#endif // !defined(AFX_MYCOM_H__BF6B4ECC_762F_48D2_9365_F123560D9CAA__INCLUDED_)
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "am40c.h"
#include "MyCom.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif#include "MyDlgRun.h"//错误信息输出
inline int MessageError(LPCSTR lpcszError, UINT nType = MB_OK | MB_ICONWARNING)
{
CWnd *pWnd = ::AfxGetMainWnd();
if(pWnd != NULL)
return pWnd->MessageBox(lpcszError, "Error", nType);
else
return ::MessageBox(NULL, lpcszError, "Error", nType);
}//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////MyCom::MyCom()
: m_bConnected(false),
m_ePStatus(PS_NOREADY)
{
memset(&m_Connection, 0, sizeof(m_Connection) - sizeof(CCriticalSection));
}MyCom::~MyCom()
{}//读取当前通讯端口缓存中的数据
UINT MyCom::CommReadBlock(HANDLE hFile, LPOVERLAPPED lpOLRead, LPSTR lpszBlock, UINT nMaxLength)
{
BOOL fReadStat;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError; if(hFile == NULL)
return false; //查询当前通讯缓存区的队列中的数据字节数
::ClearCommError(hFile, &dwErrorFlags, &ComStat);
//计算当前所需读取数据的字节数
//如果缓存区中的数据字节数较当前内存缓存字节数小,
//就读取当前所有数据;
//如果缓存区中的数据字节数较当前内存缓存字节数大,
//就读取当前内存缓存区所支持的最大字节数.)
dwLength = min(nMaxLength, ComStat.cbInQue);
if(dwLength <= 0)
return 0; //请求从当前的通讯缓存区读取数据
fReadStat = ::ReadFile(hFile, lpszBlock, dwLength, &dwLength, lpOLRead);
if(fReadStat)
return dwLength; if(GetLastError() == ERROR_IO_PENDING)
{
//当前发生I/O重叠操作,继续等待I/O操作...
while(!GetOverlappedResult(hFile, lpOLRead, &dwLength, true))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
continue;
else
{
//当前通讯有其它的错误发生
TRACE("<CE-%u>", dwError);
::ClearCommError(hFile, &dwErrorFlags, &ComStat);
if(dwErrorFlags > 0)
TRACE("<CE-%u>", dwErrorFlags);
break;
}
}
}
else
{
//当前通讯发生了一些其它的错误
dwLength = 0 ;
::ClearCommError(hFile, &dwErrorFlags, &ComStat);
if(dwErrorFlags > 0)
TRACE("<CE-%u>", dwErrorFlags);
} return dwLength;
}//当前的通讯端口监听线程函数
UINT MyCom::CommMonitorProc(void* pData)
{
LPCONNECTION pMPParam = (LPCONNECTION)pData;
int nLength;
char szBuffer[MAX_BUF_BLOCK + 1];
//监听当前串口数据通讯区的数据输入
while(pMPParam->hCommDev != NULL)
{
DWORD dwEvtMask = 0; //等待当前串口通讯的一个读事件被触发
WaitCommEvent(pMPParam->hCommDev, &dwEvtMask, NULL);
if((dwEvtMask & EV_RXCHAR) != EV_RXCHAR)
continue;
//从串口读取数据并处理
while((nLength = CommReadBlock(pMPParam->hCommDev,
&pMPParam->olRead, (LPSTR)szBuffer, MAX_BUF_BLOCK)) > 0)
{
//处理从串口读出的数据
if(pMPParam->pCom != NULL)
{
pMPParam->pCom->LockThread();
pMPParam->pCom->ProcessReceivedData(szBuffer, nLength);
pMPParam->pCom->UnlockThread();
} if(::WaitForSingleObject(pMPParam->hEventCancel, 0) == WAIT_OBJECT_0)
break;
}
} //通知主线程当前线程已结束
//.... //当前线程正确结束,返回0
return 0;
}//建立当前的通讯连接
BOOL MyCom::Connect()
{
//当前已经通讯连接已经建好
if(m_bConnected)
return true;
__try
{
m_Connection.CSec.Lock(); //初始化当前串口信息的设置
if(!this->InitCommInfo())
{
ASSERT(false);
__leave;
}
if(m_Connection.hCommDev != NULL)
{
ASSERT(false);
__leave;
} //创建当前的通讯连接 //创建用于I/O异步通讯时的读、写和取消事件
m_Connection.olRead.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
m_Connection.olWrite.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
m_Connection.hEventCancel = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(m_Connection.olRead.hEvent == NULL
|| m_Connection.olWrite.hEvent == NULL
|| m_Connection.hEventCancel == NULL)
__leave; //打开通讯端口
if(!this->OpenComm(m_Connection.hCommDev))
__leave; //设置当前串口的通信,当COMM_MASK指定的事件
//由WaitCommEvent调用发生时,来报告这些事件
if(!::SetCommMask(m_Connection.hCommDev, COMM_MASK))
{
ASSERT(false);
__leave;
} //设置串口驱动的输入和输出缓冲区的大小
if(!::SetupComm(m_Connection.hCommDev, 1024, 1024))
{
ASSERT(false);
__leave;
}
//异常终止当前在打开的端口上正进行的输入和输出操作
if(!::PurgeComm(m_Connection.hCommDev, PURGE_FLAG))
{
ASSERT(false);
__leave;
} //设置当前串口的读写超时
if(!this->SetCommTimeouts(m_Connection.hCommDev))
{
ASSERT(false);
__leave;
} //设定当前串口的通信参数
if(!this->SetCommState(m_Connection.hCommDev))
{
ASSERT(false);
__leave;
} m_Connection.pCom = this; //创建侦听线程
DWORD dwThreadID;
m_hMonitorThread = CreateThread(
(LPSECURITY_ATTRIBUTES)NULL,
0, (LPTHREAD_START_ROUTINE)CommMonitorProc,
&m_Connection, 0, &dwThreadID);
if(m_hMonitorThread == NULL)
{
ASSERT(false);
__leave;
} //声明串口上的DTR线
EscapeCommFunction(m_Connection.hCommDev, SETDTR); m_Connection.dwRefCount++;
m_bConnected = true;
m_ePStatus = PS_READY;
}
__finally
{
//当前连接创建失败
if(!m_bConnected)
{
//如果端口已经打开,则关闭已打开的端口
if(m_Connection.hCommDev != NULL)
{
::CloseHandle(m_Connection.hCommDev);
m_Connection.hCommDev = NULL;
} //如果读、写事件已经创建,则删除当前的读、写事件
if(m_Connection.olRead.hEvent != NULL)
{
//关闭读事件
::CloseHandle(m_Connection.olRead.hEvent);
m_Connection.olRead.hEvent = NULL;
} if(m_Connection.olWrite.hEvent != NULL)
{
//关闭写事件
::CloseHandle(m_Connection.olWrite.hEvent);
m_Connection.olWrite.hEvent = NULL;
} if(m_Connection.hEventCancel != NULL)
{
//关闭取消事件
::CloseHandle(m_Connection.hEventCancel);
m_Connection.hEventCancel = NULL;
}
} m_Connection.CSec.Unlock();
return m_bConnected;
}
}//重新建立当前的通讯连接
BOOL MyCom::ReConnect()
{
//当前已经通讯连接已经建好
if(m_bConnected)
{
this->DisConnect();
this->DelayReply(RECONNECT_TIME);
}
return this->Connect();
}//取消当前的通讯连接
void MyCom::DisConnect()
{
m_Connection.CSec.Lock(); //当前本没有通讯连接,直接返回
if(!m_bConnected)
{
m_Connection.CSec.Unlock();
return;
} m_Connection.dwRefCount--;
//关闭通讯事件
if(m_Connection.dwRefCount == 0
&& m_Connection.hCommDev != INVALID_HANDLE_VALUE)
{
::CloseHandle(m_Connection.hCommDev);
::CloseHandle(m_Connection.olRead.hEvent);
::CloseHandle(m_Connection.olWrite.hEvent);
m_Connection.hCommDev = NULL;
m_Connection.olRead.hEvent = NULL;
m_Connection.olWrite.hEvent = NULL; ::SetEvent(m_Connection.hEventCancel);
::CloseHandle(m_Connection.hEventCancel);
m_Connection.hEventCancel = NULL;
} //置当前的通讯连接标志
m_bConnected = false;
m_ePStatus = PS_NOREADY;
m_Connection.CSec.Unlock();
}//获取当前的通讯端口名称
CString MyCom::GetCommName()
{
return this->GetCommName(m_CommInfo.byCommPort);
}//判断当前的通讯连接是否已经建立
BOOL MyCom::IsConnected()
{
return m_bConnected;
}//获取当前的通讯连接指针,并锁定于当前线程
//(此函数必须与UnLockConnection()配对调用, 时间间隔不宜太久)
LPCONNECTION MyCom::LockConnection()
{
m_Connection.CSec.Lock();
return &m_Connection;
}//释放当前的通讯连接指针(解除当前线程的锁定)
//(此函数必须与LockConnection()配对调用, 时间间隔不宜太久)
void MyCom::UnLockConnection()
{
m_Connection.CSec.Unlock();
}//初始化当前的串口信息
BOOL MyCom::InitCommInfo()
{
if(m_bConnected)
return false; memset(&m_CommInfo, 0, sizeof(m_CommInfo)); m_CommInfo.byByteSize = 8;
m_CommInfo.byCommPort = 1;
m_CommInfo.byParity = NOPARITY;
m_CommInfo.byStopBits = TWOSTOPBITS;
m_CommInfo.dwBaudRate = CBR_9600;
m_CommInfo.byFlowCtrl = FC_XONXOFF;
m_CommInfo.byXonXoff = false; return true;
}//根据串口的序号获取当前串口的名称
CString MyCom::GetCommName(BYTE bySN)
{
CString strOut;
if(bySN <= 0 || bySN > 20)
{
ASSERT(false);
bySN = 1;
} strOut.Format("COM%d", bySN);
return strOut;
}//设定当前串口的通信参数
BOOL MyCom::SetCommState(HANDLE hFile)
{
DCB dcb;
::ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if(!::GetCommState(hFile, &dcb))
return false;
dcb.BaudRate = this->m_CommInfo.dwBaudRate;
dcb.ByteSize = this->m_CommInfo.byByteSize;
dcb.Parity = this->m_CommInfo.byParity;
dcb.StopBits = this->m_CommInfo.byStopBits;
//setup hardware flow control
/* dcb.fOutxDsrFlow = (BYTE)((m_CommInfo.byFlowCtrl & FC_DTRDSR) != 0);
if(dcb.fOutxDsrFlow)
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
else
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutxCtsFlow = (BYTE)((m_CommInfo.byFlowCtrl & FC_RTSCTS) != 0);
if(dcb.fOutxCtsFlow)
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
else
dcb.fRtsControl = RTS_CONTROL_ENABLE;
//setup software flow control
dcb.fInX = dcb.fOutX = (BYTE)((m_CommInfo.byFlowCtrl & FC_XONXOFF) != 0);
dcb.XonChar = ASCII_XON;
dcb.XoffChar = ASCII_XOFF;
dcb.XonLim = 100;
dcb.XoffLim = 100;
//other various settings
dcb.fBinary = TRUE;
dcb.fParity = m_CommInfo.byParity;
*/
return ::SetCommState(hFile, &dcb);
}//设置当前串口的读写超时
BOOL MyCom::SetCommTimeouts(HANDLE hFile)
{
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 20;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
return ::SetCommTimeouts(hFile, &CommTimeOuts);
}//打开串口
BOOL MyCom::OpenComm(HANDLE &hFile)
{
CString strError; //找开串口
HANDLE h = ::CreateFile(
this->GetCommName(),
GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
//打开指定串口失败
if(h == INVALID_HANDLE_VALUE)
{
strError.Format("打开通讯端口%s出错!\n",
this->GetCommName());
MessageError(strError);
return false;
} hFile = h;
return true;
}
BOOL MyCom::CommWriteBlock(HANDLE hFile, LPCSTR lpcByte,
DWORD dwBytesToWrite,
OVERLAPPED *pOLWrite)
{
DWORD dwBytesWritten;
DWORD dwError;
DWORD dwBytesSent = 0;
COMSTAT ComStat;
char szError[128];
//向串口写入数据
if(WriteFile(hFile, lpcByte, dwBytesToWrite,
&dwBytesWritten, pOLWrite))
return true;
//检测写数据函数运行后的全局系统错误信息
//如果有非重叠信息错误,则报错并退出当前函数的运行
if(GetLastError() != ERROR_IO_PENDING)
{
ClearCommError(hFile, &dwError, &ComStat);
if(dwError > 0)
{
sprintf(szError, "<CE-%x>", dwError);
TRACE0(szError);
}
return false;
} //获取当前IO重叠操作的结果
while(!GetOverlappedResult(hFile, pOLWrite,
&dwBytesWritten, true))
{
dwError = GetLastError(); //依旧处于IO重叠操作过程中,继续等待
if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesSent += dwBytesWritten;
continue;
}
//发生了其它错误,退出当前函数的执行
else
{
sprintf(szError, "<CE-%x>\n", dwError);
TRACE0(szError);
ClearCommError(hFile, &dwError, &ComStat);
if(dwError > 0)
{
sprintf(szError, "<CE-%x>\n", dwError);
TRACE0(szError);
}
break;
}
}
//计算已写入数据的字节数,并判断是否写串口数据成功
dwBytesSent += dwBytesWritten;
if(dwBytesSent != dwBytesToWrite)
{
sprintf(szError, "Probable Write Timeout: Total of %ld bytes sent\n", dwBytesSent);
TRACE0(szError);
return false;
}
else
{
// sprintf(szError, "%ld bytes written\n", dwBytesSent);
// TRACE0(szError);
return true;
}
}//处理接收回来的数据
void MyCom::ProcessReceivedData(LPCSTR lpcByte,
DWORD dwDataLenght)
{
if(g_DlgDebugTrace.IsTrace())
{
char szBuf[128];
char szTemp[8];
CTime timeCur = time(NULL);
sprintf(szBuf, "(R_%2d:%2d:%2d)", timeCur.GetHour(), timeCur.GetMinute(), timeCur.GetSecond());
for(DWORD i = 0; i < dwDataLenght; i++)
{
sprintf(szTemp, "%02x ", (unsigned char)lpcByte[i]);
strcat(szBuf, szTemp);
} ::g_DlgDebugTrace.TraceString(szBuf);
}
}//向串口发送数据
BOOL MyCom::WriteData2Comm(LPCSTR lpcByte,
DWORD dwDataLenght)
{
if(g_DlgDebugTrace.IsTrace())
{
char szBuf[128];
char szTemp[8];
CTime timeCur = time(NULL);
sprintf(szBuf, "(S_%2d:%2d:%2d)", timeCur.GetHour(), timeCur.GetMinute(), timeCur.GetSecond());
for(DWORD i = 0; i < dwDataLenght; i++)
{
sprintf(szTemp, "%02x ", (unsigned char)lpcByte[i]);
strcat(szBuf, szTemp);
} ::g_DlgDebugTrace.TraceString(szBuf);
} BOOL bRet = false;
//将当前对象锁定于当前线程
m_CSec.Lock(); __try
{
if(!m_bConnected)
{
TRACE("请先建立正确的串口通讯连接!\n");
__leave;
}
LPCONNECTION lpConnection = this->LockConnection();
bRet = MyCom::CommWriteBlock(lpConnection->hCommDev,
lpcByte, dwDataLenght, &lpConnection->olWrite);
this->UnLockConnection();
}
__finally
{
m_CSec.Unlock();
return bRet;
}
}//设定当前延时处理
void MyCom::DelayReply(DWORD dwTime)
{
DWORD dwStart = GetTickCount(); while(1)
{
MSG msg;
//响应其它消息的处理
while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
} if(GetTickCount() - dwStart > dwTime)
return;
::Sleep(1);
}
}