📄 mywin32port.cpp
字号:
/************************************************************************/
/* 类名称: 串口操作类 */
/* 功 能: 实现对串口的基本操作 */
/* 设计者: Jinlong|Luo */
/* 修订记录: */
/* 设计时间: 2007-9-24 */
/************************************************************************/
#include<StdAfx.h>
#include "MyWin32Port.h"
//全局变量定义
CRITICAL_SECTION g_cslistReceiveInfoMutex; //接收队列关键代码段的同步变量
CList< CInfoCell, CInfoCell& > g_listReceiveInfo; //接收队列
CFile m_ycDataFile;//遥测数据文件
/************************************************************************/
// 函数名称: ReceiveThread()
// 函数描述: 接收线程
// 入口参数:
// 出口参数:
// 返 回 值:
// 其 它:
/************************************************************************/
UINT MyWin32Port::ReceiveThread( PVOID pParameter )
{
MyWin32Port* pSerialPort = (MyWin32Port*)pParameter;
ASSERT(pSerialPort->m_hCom != INVALID_HANDLE_VALUE);//检测串口是否打开
//清空串口
PurgeComm(pSerialPort->m_hCom,PURGE_RXCLEAR | PURGE_TXCLEAR);
if( pSerialPort->m_hCom )
SetCommMask( pSerialPort->m_hCom, EV_RXCHAR );//输入设备接受字符
int i=0;
int j=0;
short sCurLoc = 0;//临时缓冲区中的当前位置
UWord16 wHead = 0;
DWORD dwReadNum = 0;
char* pSegment = NULL;
CString strDateTime;
CTime time = CTime::GetCurrentTime();
strDateTime.Format("%d-%d-%d",time.GetYear(),time.GetMonth(),time.GetDay());
CString strFileName = "GPSData";
strFileName+=strDateTime;
strFileName+=".yc";
BOOL bCreateFile = m_ycDataFile.Open(strFileName,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
while( TRUE )
{
//如果收到接收线程退出信号,则退出线程
if (WaitForSingleObject(pSerialPort->m_hReceiveCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
//从串口读取数据
ReadFile( pSerialPort->m_hCom, pSerialPort->m_csRevBuf, RECEIVE_CHAR_BUFFER_MAX, &dwReadNum, NULL ); //读字符
pSerialPort->m_csRevBuf[dwReadNum] = '\0';
if (dwReadNum<=0) //dwReadNum<=0
{
Sleep(20);
continue;
}
//保存当前数据
if( bCreateFile )
{
m_ycDataFile.Write( pSerialPort->m_csRevBuf,dwReadNum);
}
//处理数据
if (sCurLoc>(SERIAL_CHAR_BUFFER_MAX*2-dwReadNum))
{
sCurLoc = 0;//防止溢出
}
memcpy(&pSerialPort->m_csTempBuf[sCurLoc],&pSerialPort->m_csRevBuf[0],dwReadNum);//保存当前数据到临时缓冲区中
for (i=0;i<(dwReadNum+sCurLoc-1);i++)
{
wHead = (pSerialPort->m_csTempBuf[i]<<8) | pSerialPort->m_csTempBuf[i+1];
if (0xEB90 == wHead)//帧同步头
{
if ((i+50)<=(dwReadNum+sCurLoc))//当前数据为一条完整的数据帧,遥测一帧数据为50byte
{
if ((pSerialPort->m_csTempBuf[i+46]==0x55) && (pSerialPort->m_csTempBuf[i+47]==0x55)
&& (pSerialPort->m_csTempBuf[i+48]==0x55) && (pSerialPort->m_csTempBuf[i+49]==0x55))//帧尾标志
{
EnterCriticalSection(&g_cslistReceiveInfoMutex);
pSegment = (char*)&pSerialPort->m_csTempBuf[i];
CInfoCell oCell(pSegment,50);
g_listReceiveInfo.AddTail(oCell);
LeaveCriticalSection(&g_cslistReceiveInfoMutex);
i+=49;
j = i+1;
}
}
}
}
if (j<(dwReadNum+sCurLoc))//当前数据未处理完,保存不完整帧
{
sCurLoc = dwReadNum+sCurLoc-j;
memmove(&pSerialPort->m_csTempBuf[0],&pSerialPort->m_csTempBuf[j],sCurLoc);
j=0;
}
else//当前数据处理完毕
{
sCurLoc = 0;
j = 0;
}
pSerialPort->m_csRevBuf[0] = '\0'; //接收缓冲区置空
}
return 0;
}
/************************************************************************/
// 函数名称: InfoProcessThread()
// 函数描述: 信息处理线程
// 入口参数:
// 出口参数:
// 返 回 值:
// 其 它:
/************************************************************************/
UINT MyWin32Port::InfoProcessThread( PVOID pParameter )
{
MyWin32Port* pSerialPort = (MyWin32Port*)pParameter;
ASSERT(pSerialPort->m_hCom != INVALID_HANDLE_VALUE);
int iCount = 0;
//处理接收缓冲区中的数据
while( true )
{
EnterCriticalSection( &g_cslistReceiveInfoMutex );
iCount = g_listReceiveInfo.GetCount();
while(iCount>0 )
{
CInfoCell& oCell = g_listReceiveInfo.GetHead();
pSerialPort->Process( oCell.csInfo, oCell.nLength ); //信息处理
g_listReceiveInfo.RemoveHead();
iCount = g_listReceiveInfo.GetCount();
}
LeaveCriticalSection( &g_cslistReceiveInfoMutex );
//如果收到解析线程退出信号,则退出线程
if (WaitForSingleObject(pSerialPort->m_hInfoProcessCloseEvent,500) == WAIT_OBJECT_0)
{
pSerialPort->m_hInfoProcessThread = NULL;
break;
}
Sleep(10);
}
return 0;
}
/************************************************************************/
/* 构造/析构 */
/************************************************************************/
MyWin32Port::MyWin32Port()
{
//串口句柄
m_hCom = INVALID_HANDLE_VALUE;
//串口占用标示
m_bIsOpen = FALSE;
//窗口句柄
m_hWnd = NULL;
//接收线程句柄
m_hReceiveThread = NULL;
//解析线程句柄
m_hInfoProcessThread = NULL;
//接收队列关键代码段的同步变量初始化
InitializeCriticalSection(&g_cslistReceiveInfoMutex);
//当前解析的协议指令字符串
m_pCurParsedContent = NULL;
//接收字符串缓冲区
memset(m_csRevBuf,0,(SERIAL_CHAR_BUFFER_MAX+1)*sizeof(BYTE));
//临时缓冲区
memset(m_csTempBuf,0,(SERIAL_CHAR_BUFFER_MAX*2+1)*sizeof(BYTE));
}
MyWin32Port::~MyWin32Port()
{
//关闭串口
if (m_bIsOpen)
{
CloseMyWin32Port();
m_bIsOpen = FALSE;
}
//清除接收队列关键代码段的同步变量
if ((NULL==m_hInfoProcessThread) && (NULL==m_hReceiveThread))
{
DeleteCriticalSection( &g_cslistReceiveInfoMutex );
}
//当前解析的协议指令字符串
if (m_pCurParsedContent!=NULL)
{
delete m_pCurParsedContent;
m_pCurParsedContent = NULL;
}
}
/************************************************************************/
// 函数名称: Open(HWND hWnd,char btID,long dwBaudRate, char btParity ,char btSize,
// char btStopBits,long ReadIntervalTimeout,long ReadTotalTimeoutMultiplier,
// long ReadTotalTimeoutConstant,long WriteTotalTimeoutMultiplier,
// long WriteTotalTimeoutConstant,long dwCommMask )
// 函数描述: 根据指定的参数打开串口并开启串口读、写及解析线程
// 入口参数:
// HWND hWnd 传入的窗口句柄
// char btID 待打开串口ID号 1--COM1:、2--COM2:...
// long dwBaudRate 待打开串口数据传输率 4800、9600、19200...
// char btParity 待打开串口奇偶校验 默认为无校验。
// char btSize 待打开串口数据位 默认为8
// char btStopBits 待打开串口停止位 默认为1
// long ReadIntervalTimeout
// long ReadTotalTimeoutMultiplier
// long ReadTotalTimeoutConstant
// long WriteTotalTimeoutMultiplier
// long WriteTotalTimeoutConstant 串口通讯占用端口超时结构参数
// long dwCommMask 待打开串口串口响应事件
// 出口参数:
// 返 回 值: 串口打开成功或已打开,返回TRUE;否则返回FALSE
// 其 它:
/************************************************************************/
BOOL MyWin32Port::OpenMyWin32Port(HWND hWnd,char btID,long dwBaudRate, char btParity /* = NOPARITY */,char btSize /* = 8 */,
char btStopBits /* = ONESTOPBIT */,long ReadIntervalTimeout, long ReadTotalTimeoutMultiplier,
long ReadTotalTimeoutConstant,long WriteTotalTimeoutMultiplier,
long WriteTotalTimeoutConstant,long dwCommMask /* = EV_RXCHAR|EV_TXEMPTY */)
{
//打开串口
DCB dcb ;
long dwError = 0 ;
CString szPort = _T("") ;
COMMTIMEOUTS CommTimeOuts ;
if( FALSE != m_bIsOpen )
{
AfxMessageBox(_T("串口已打开或未找到!")) ;
return 0 ;
}
szPort.Format("COM%d:",btID) ;// 确定待打开的串口名称完整性(COM1:)
m_hCom = INVALID_HANDLE_VALUE ;// 设置串口通讯占用端口的句柄为占用模式
m_hCom = CreateFile( szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ) ;// 根据输入的串口通讯参数打开串口
if( INVALID_HANDLE_VALUE == m_hCom )
{
return FALSE ;
}
// 设置串口通讯占用端口超时结构参数
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 5000 ;
// 设置串口通讯占用端口超时结构
SetCommTimeouts(m_hCom,&CommTimeOuts) ;
// 设置串口通讯占用端口DCB结构
dcb.DCBlength = sizeof( DCB ) ;
GetCommState( m_hCom, &dcb ) ;
dcb.BaudRate = dwBaudRate ;
dcb.ByteSize = btSize ;
if (1==btStopBits)
{
dcb.StopBits = ONESTOPBIT;
}
else if (2== btStopBits)
{
dcb.StopBits = TWOSTOPBITS;
}
else if (5 == btStopBits)
{
dcb.StopBits = ONE5STOPBITS;
}
else
{
dcb.StopBits = ONESTOPBIT;
}
switch(btParity)
{
case 'N': //无奇偶校验位
dcb.Parity = NOPARITY;
break;
case 'O':
dcb.Parity = ODDPARITY;
break;
case 'E':
dcb.Parity = EVENPARITY;
break;
case 'M':
dcb.Parity = MARKPARITY;
break;
case 'S':
dcb.Parity = SPACEPARITY;
break;
default:
dcb.Parity = NOPARITY ;
break;
}
// 如果设置串口通讯占用端口选项参数失败直接返回FALSE
if( 0 == SetCommState(m_hCom,&dcb) || 0 == SetupComm(m_hCom,10000,10000) || 0 == SetCommMask(m_hCom,dwCommMask) )
{
// 获取错误标示
dwError = GetLastError() ;
// 关闭串口通讯并释放其占用端口
m_hWnd = NULL;
CloseMyWin32Port() ;
return FALSE ;
}
// 清空串口通讯占用端口的缓冲区
PurgeComm(m_hCom,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT) ;
//启动接收线程
if (!StartReceiveThread())
{
CloseMyWin32Port() ;//关闭串口
return FALSE;
}
//启动解析线程
if (!StartInfoProcessThread())
{
CloseMyWin32Port() ;//关闭串口
return FALSE;
}
// 设置串口通讯是否占用端口的标识
m_hWnd = hWnd ;
m_bIsOpen = TRUE ;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -