多线程串口管理代码(2)
// CommPort.cpp: implementation of the XCommPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XCommPort.h"
#include <stdio.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//#define COM_BUGWRITE 1
#ifdef COM_BUGWRITE
static void ComWritePrintf(const BYTE *str,const int Len )
{
char szFileName[256];
char buf[512];
strcpy( szFileName, "c:\\WritePrintf.txt" );
FILE *fpDebug = fopen( szFileName, "a" );
memset(buf,0,Len * 3 +2);
for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
fprintf( fpDebug, "%s\n", buf );
fclose( fpDebug );
}
static void ComReadPrintf(const BYTE *str,const int Len )
{
char szFileName[256];
char buf[512];
strcpy( szFileName, "c:\\ReadPort.txt" );
FILE *fpDebug = fopen( szFileName, "a" );
memset(buf,0,Len * 3 +2);
for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
fprintf( fpDebug, "%s\n", buf );
fclose( fpDebug );
}
#endif //BUG
XCommPort::XCommPort(): m_bThreadAlive(0),
m_dwThreadID(NULL),
m_hComm(NULL),
m_nSizeToWrite(0)
{
m_pWriteBuffer = new BYTE[200];
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
m_ovOverLapped.hEvent = NULL;
}
XCommPort::~XCommPort()
{
CloseCommPort();
SafeDeleteArray( m_pWriteBuffer );
}
//---------------------------------------------------------------------------
BOOL XCommPort::CloseCommPort()
{
while (m_bThreadAlive)
{
SetEvent( m_hShutdownEvent );
}
::CloseHandle(m_hComm);
m_hComm = NULL;
return TRUE;
}
//---------------------------------------------------------------------------
DWORD XCommPort::CommThread(LPVOID pParame)
{
XCommPort *Port = (XCommPort*)pParame;
Port->m_bThreadAlive = true;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
BOOL bResult = TRUE;
//.................................................
if (Port->m_hComm)
{
::PurgeComm( Port->m_hComm,
PURGE_RXCLEAR|
PURGE_TXCLEAR|
PURGE_RXABORT|
PURGE_TXABORT);
}
for(;;)
{
bResult = WaitCommEvent(Port->m_hComm,
&Event,
&Port->m_ovOverLapped);
Event = WaitForMultipleObjects(3,
Port->m_hEventArray,
false,
INFINITE);
switch( Event )
{
case 0:
{
Port->m_bThreadAlive = false;
ExitThread( 100 );
break;
}
case 1:
{
GetCommMask(Port->m_hComm,&CommEvent);
if (CommEvent & EV_RXCHAR)
Port->ReadData();
break;
}
case 2:
{
Port->WriteData();
break;
}
case WAIT_FAILED:
{
char *msg= new char[20];
sprintf(msg,"%8X\n",::GetLastError());
ATLTRACE(msg);
::Sleep(1);
break;
}
}
}
return 0;
}
//---------------------------------------------------------------------------
int XCommPort::Create(const DWORD dwThreadID,
const char *szPath,
const BYTE bComID,const BYTE bSerialNo,
const DWORD dwBaudRate,const BYTE bByteSize,
const BYTE bParity,const BYTE bStopBits,
const int nWaitTime,const short bHaveMID)
{
if( !(InitCommPort(dwThreadID, bComID,bSerialNo,dwBaudRate,
bByteSize,bParity,bStopBits)) )
{
CloseCommPort();
return SERIAL_ERROR;
}
InitSerial(dwThreadID,bComID,bSerialNo,szPath,nWaitTime,bHaveMID); //(0)
DetectComm();
//SafeDelete(pInfo);
return SERIAL_OK;
}
//---------------------------------------------------------------------------
BOOL XCommPort::DetectComm()
{
DWORD ThreadID;
m_hThread = CreateThread(NULL,0,CommThread,this,0,&ThreadID);
if ( m_hThread == NULL )
{
return FALSE;
}
SetThreadPriority( m_hThread,THREAD_PRIORITY_TIME_CRITICAL );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::InitCommPort(DWORD dwThreadID,
BYTE bComID,
BYTE bSerialNo,
DWORD dwBaudRate,
BYTE bByteSize,
BYTE bParity,
BYTE bStopBits )
{
char szSerialPortName[20];
if( m_hShutdownEvent != NULL )
ResetEvent( m_hShutdownEvent );
m_hShutdownEvent = CreateEvent( NULL, true, false, NULL );
while( m_bThreadAlive )
{
SetEvent( m_hShutdownEvent );
}
sprintf( szSerialPortName, "\\\\.\\COM%d", bComID );
m_dwThreadID = dwThreadID;
if( m_ovOverLapped.hEvent != NULL )
ResetEvent( m_ovOverLapped.hEvent );
m_ovOverLapped.hEvent = CreateEvent( NULL, true, false, NULL );
if( m_hWriteEvent != NULL )
ResetEvent( m_hWriteEvent );
m_hWriteEvent = CreateEvent( NULL, true, false, NULL );
m_hEventArray[0] = m_hShutdownEvent;
m_hEventArray[1] = m_ovOverLapped.hEvent;
m_hEventArray[2] = m_hWriteEvent;
InitializeCriticalSection( &m_csCommunicationSync );
EnterCriticalSection( &m_csCommunicationSync );
m_hComm = CreateFile( szSerialPortName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL );
if( m_hComm == INVALID_HANDLE_VALUE )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
COMMTIMEOUTS CommTimeouts;
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutConstant =0;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant =0;
CommTimeouts.WriteTotalTimeoutMultiplier =0;
if( !SetCommTimeouts( m_hComm, &CommTimeouts ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
//if( !SetCommMask( m_hComm,
// EV_BREAK | EV_ERR | EV_RING
// | EV_RXCHAR | EV_RXFLAG | EV_CTS ) )
if( !SetCommMask( m_hComm, EV_RXCHAR ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
if( !SetupComm( m_hComm, 4096, 2048 ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
if( !GetCommState( m_hComm, &m_dcb ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
m_dcb.BaudRate =dwBaudRate;
m_dcb.ByteSize =bByteSize;
m_dcb.Parity = bParity;
m_dcb.StopBits = bStopBits;
m_dcb.fBinary = true;
m_dcb.fParity = false;
m_dcb.fInX = false;
m_dcb.fOutX = false;
m_dcb.fRtsControl = RTS_CONTROL_DISABLE; //ENABLE;
m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fOutxDsrFlow = FALSE;
if( !SetCommState( m_hComm, &m_dcb ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
m_bSerialNo = bSerialNo;
PurgeComm( m_hComm, PURGE_RXCLEAR|PURGE_TXCLEAR
|PURGE_RXABORT|PURGE_TXABORT );
LeaveCriticalSection( &m_csCommunicationSync );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::ReadData()
{
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD dwBytesRead = 0;
DWORD dwByteToRead = 0;
COMSTAT comstat;
EnterCriticalSection( &m_csCommunicationSync );
bResult = ClearCommError( m_hComm,&dwError,&comstat );
LeaveCriticalSection( &m_csCommunicationSync );
Sleep(27); //(0)
dwByteToRead = comstat.cbInQue;
BYTE *pBuf = new BYTE[dwByteToRead];
if ( comstat.cbInQue > 0 )
{
EnterCriticalSection( &m_csCommunicationSync );
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
bResult = ::ReadFile( m_hComm,pBuf, comstat.cbInQue,
&dwBytesRead, &m_ovOverLapped );
if ( !bResult)
{
if ( ERROR_IO_PENDING == GetLastError() )
{
::GetOverlappedResult( m_hComm, &m_ovOverLapped,&dwBytesRead,TRUE );
}
}
LeaveCriticalSection(&m_csCommunicationSync);
}
#ifdef COM_BUGWRITE
ComReadPrintf(pBuf,dwBytesRead);
#endif
ReceiveBuf(dwBytesRead,pBuf);
delete[] pBuf;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::WriteData()
{
BOOL bResult = TRUE;
DWORD dwBytesSent = 0;
ResetEvent( m_hWriteEvent );
EnterCriticalSection( &m_csCommunicationSync );
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
#ifdef COM_BUGWRITE
ComWritePrintf(m_pWriteBuffer,m_nSizeToWrite);
#endif
::PurgeComm( m_hComm,
PURGE_RXCLEAR|
PURGE_TXCLEAR|
PURGE_RXABORT|
PURGE_TXABORT );
bResult = ::WriteFile( m_hComm,
m_pWriteBuffer,
m_nSizeToWrite,
&dwBytesSent,
&m_ovOverLapped );
if ( !bResult )
{
DWORD dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
::GetOverlappedResult( m_hComm,
&m_ovOverLapped,
&dwBytesSent,
TRUE );
}
WriteCompleted( false );
LeaveCriticalSection( &m_csCommunicationSync );
return TRUE;
}
//---------------------------------------------------------------------------
int XCommPort::WriteToPort(BYTE *Buf,int Length)
{
if ( !m_bThreadAlive) return -1;
EnterCriticalSection( &m_csCommunicationSync );
m_nSizeToWrite = Length;
ATLASSERT(Length < 200 );
if ( Length>= 200 )
{
MessageBox(NULL,"write length >200","提示",MB_ICONWARNING);
return 1;
}
memcpy( m_pWriteBuffer, Buf,Length );
LeaveCriticalSection( &m_csCommunicationSync );
SetEvent( m_hWriteEvent );
return 0;
}
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
40W超紧凑DC-DC转换器,适用于空间受限的严苛应用场合
纳芯微携手联合电子与英诺赛科,共创新能源汽车功率电子新格局
嵌入式Linux在消费电子领域的发展与应用 下
COMPAQ 460/461型VGA多频彩色显示器的电源电路图
高性能评估板为沉浸式音频体验快速便捷构建声场工具
嵌入式Linux在消费电子领域的发展与应用 上
X40420_X40421 带看门狗4K 位EEPROM 的双电压监控芯片
常用场效应管IRF参数表
尼得科仪器开发出支持令牌化的安全认证读卡器
嵌入式Linux图形界面开发 上
基于motorola系列5282 5272强劲功能的开发板!
长沙理工大学计算机学院全球人才招聘公告
常用场效应管参数表(2SJ)
嵌入系统开发软件如要从速
北斗创新平台支持大理州深挖文旅等场景
嵌入式Linux网络开发 上
COMPAQ 472P型多频显示器的电源电路图
松下致力于将汽车电池容量提升25%
谁知道AT89C51的
嵌入式Linux网络开发 中
CTX C2型双频高分辨率彩色显示器的电源电路图
CONPAQ 420G型SVGA彩色显示器的电源电路图
将触感转化为真实体验:TITAN Haptics以科学精度赋能触觉设计
[求助]44b0与SDRAM的连接
COMPAQ TE-1420Q型VGA多频显示器的电源电路图
中国企业展示电动汽车电池弹出技术
一些让人流泪的故事
提升用户信心,确保电动汽车电池纯正可靠
常用场效应管和晶体管参数
X40430_X40431带看门狗4K 位EEPROM 的三路电压监控芯片