?? 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 + -