📄 serialport.cpp
字号:
// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SerialPort.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerialPort::CSerialPort()
{
m_hComm = NULL;
// initialize overlapped structure members to zero
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// create events
m_ov.hEvent = NULL;
m_hWriteEvent = NULL;
m_hShutdownEvent = NULL;
m_szWriteBuffer = NULL;
m_szReadBuffer = NULL;
m_nWriteSize = 1;
// m_nReadSize = 1;
m_bThreadAlive = FALSE;
}
CSerialPort::~CSerialPort()
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
delete [] m_szWriteBuffer;
delete [] m_szReadBuffer;
}
UINT CSerialPort::CommThread(LPVOID pParam)
{
//---定义一个CSerialPort类指针,使得传给线程一个空的指针
//返回一个CSerialPort类指针
CSerialPort* port = (CSerialPort*) pParam;
port->m_bThreadAlive = TRUE; //表明线程在运行
DWORD BytesTansfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
//清除Comm的缓冲区
if(port->m_hComm)
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR
| PURGE_RXABORT | PURGE_TXABORT);
//---无线等待,除非线程终止
for(;;)
{
//---调用WaitCommEvent函数查询Com的事件
bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
if(!bResult)
{
//--如果返回为假,查询最后一个错误的原因
switch(dwError = GetLastError())
{
case ERROR_IO_PENDING: //如果串口没有待读字节,这是一个正常返回结果,继续
break;
case 87: //有效的返回
break;
default:
{
//其他的返回说明存在严重的错误,处理错误
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
if(0 == comstat.cbInQue)
continue;
}
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
switch(Event)
{
case 0:
{
//关闭串口
CloseHandle(port->m_hComm);
port->m_hComm = NULL;
port->m_bThreadAlive = FALSE;
AfxEndThread(100);
break;
}
case 1:
{
GetCommMask(port->m_hComm, &CommEvent);
//如果接受到数据
if(CommEvent & EV_RXCHAR)
ReadComm(port, comstat);
if (CommEvent & EV_CTS)
::SendMessage(port->m_hWnd->m_hWnd, WM_COMM_CTS_DETECTED,
(WPARAM) 0, (LPARAM) port->m_nPortID);
if (CommEvent & EV_BREAK)
::SendMessage(port->m_hWnd->m_hWnd, WM_COMM_BREAK_DETECTED,
(WPARAM) 0, (LPARAM) port->m_nPortID);
if (CommEvent & EV_ERR)
::SendMessage(port->m_hWnd->m_hWnd, WM_COMM_ERR_DETECTED,
(WPARAM) 0, (LPARAM) port->m_nPortID);
if (CommEvent & EV_RING)
::SendMessage(port->m_hWnd->m_hWnd, WM_COMM_RING_DETECTED,
(WPARAM) 0, (LPARAM) port->m_nPortID);
if (CommEvent & EV_RXFLAG)
::SendMessage(port->m_hWnd->m_hWnd, WM_COMM_RXFLAG_DETECTED,
(WPARAM) 0, (LPARAM) port->m_nPortID);
break;
}
case 2:
{
WriteComm(port);
break;
}
default:
break;
}
}
return 0;
}
int CSerialPort::InitialPort(CWnd* pPortwnd,
UINT nMinPort, UINT nMaxPort,
UINT baud,
char parity,
UINT databits,
UINT stopbits,
DWORD dwCommEvents,
UINT writebuffersize,
UINT readbuffersize)
{
BOOL bFinded = FALSE;
while(!InitialPort(pPortwnd, nMinPort, baud, parity, databits,stopbits,
dwCommEvents, writebuffersize,
readbuffersize) && (nMinPort < nMaxPort))
{
nMinPort ++;
}
if(nMinPort == nMaxPort)
return -1;
return m_nPortID;
}
BOOL CSerialPort::InitialPort(CWnd* pPortwnd,
UINT portnr,
UINT baud,
char parity,
UINT databits,
UINT stopbits,
DWORD dwCommEvents,
UINT writebuffersize,
UINT readbuffersize)
{
ASSERT(portnr>0 && portnr<9);
ASSERT(pPortwnd);
if(m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
//---创建事件
if(m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL)
ResetEvent(m_hWriteEvent);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL)
ResetEvent(m_hShutdownEvent);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//---初始化事件对象
m_hEventArray[0] = m_hShutdownEvent;
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
//---
InitializeCriticalSection(&m_csCommunicationSync);
m_hWnd = pPortwnd;
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
if (m_szReadBuffer != NULL)
delete [] m_szReadBuffer;
m_szWriteBuffer = new char[writebuffersize];
m_szReadBuffer = new char[readbuffersize];
m_nPortID = portnr;
m_dwWriteBufferSize = writebuffersize;
m_dwReadBufferSize = readbuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
char *szPort = new char[50];
char *szBaud = new char[50];
EnterCriticalSection(&m_csCommunicationSync);
// 如果串口已经打开,关闭串口
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
// AfxMessageBox("Nothing");
m_hComm = NULL;
}
sprintf(szPort, "COM%d", portnr);
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
//打开串口
m_hComm = CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (m_hComm == INVALID_HANDLE_VALUE)
{
// 串口没找到
delete [] szPort;
delete [] szBaud;
// MessageBox(NULL, "没找到串口", "警告", MB_ICONINFORMATION);
return FALSE;
}
// 设置时间
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
//---配置串口
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
if (SetCommMask(m_hComm, dwCommEvents))
{
if (GetCommState(m_hComm, &m_hDcb))
{
m_hDcb.EvtChar = 'q';
m_hDcb.fRtsControl = RTS_CONTROL_ENABLE;
if (BuildCommDCB(szBaud, &m_hDcb))
{
if (SetCommState(m_hComm, &m_hDcb));
else ProcessErrorMessage("SetCommState()");
}
else ProcessErrorMessage("BuildCommDCB()");
}
else ProcessErrorMessage("GetCommState()");
}
else ProcessErrorMessage("SetCommMask()");
}
else ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort;
delete [] szBaud;
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);
return TRUE;
}
void CSerialPort::ReadComm(CSerialPort* port, COMSTAT ComStat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff;
for (;;)
{
//确定串口资源没有被其他程序所用
EnterCriticalSection(&port->m_csCommunicationSync);
// 清除错误
bResult = ClearCommError(port->m_hComm, &dwError, &ComStat);
LeaveCriticalSection(&port->m_csCommunicationSync);
if (ComStat.cbInQue == 0)
{
// 读完退出
break;
}
EnterCriticalSection(&port->m_csCommunicationSync);
if (bRead)
{
bResult = ReadFile(port->m_hComm,
&RXBuff,
1,
&BytesRead,
&port->m_ov);
//
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
bRead = FALSE;
break;
}
default:
{
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
bRead = TRUE;
}
}
if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(port->m_hComm,
&port->m_ov,
&BytesRead,
TRUE);
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
}
LeaveCriticalSection(&port->m_csCommunicationSync);
// 通知窗体
::SendMessage((port->m_hWnd)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortID);
}
}
void CSerialPort::WriteComm(CSerialPort* port)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
ResetEvent(port->m_hWriteEvent);
EnterCriticalSection(&port->m_csCommunicationSync);
if (bWrite)
{
// 初始化变量
port->m_ov.Offset = 0;
port->m_ov.OffsetHigh = 0;
// 清除缓冲区
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
bResult = WriteFile(port->m_hComm,
port->m_szWriteBuffer,
port->m_nWriteSize, //要发送的字符串的长度
&BytesSent, //应尽发送的长度
&port->m_ov);
if (!bResult)
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
port->ProcessErrorMessage("WriteFile()");
}
}
}
else
{
LeaveCriticalSection(&port->m_csCommunicationSync);
}
}
if (!bWrite)
{
bWrite = TRUE;
bResult = GetOverlappedResult(port->m_hComm,
&port->m_ov,
&BytesSent,
TRUE);
LeaveCriticalSection(&port->m_csCommunicationSync);
}
::SendMessage((port->m_hWnd)->m_hWnd, WM_COMM_TXEMPTY_DETECTED,0,(LPARAM) port->m_nPortID);
}
//--发送字符串
void CSerialPort::SendString(CString str)
{
CString strtemp;
String2Hex(str, strtemp);
WriteToPort((LPCTSTR)strtemp);
}
void CSerialPort::WriteToPort(LPCTSTR string)
{
ASSERT(m_hComm != 0);
memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
strcpy(m_szWriteBuffer, string);
m_nWriteSize=strlen(string);
// set event for write
SetEvent(m_hWriteEvent);
}
//---错误的处理
void CSerialPort::ProcessErrorMessage(char *ErrorText)
{
char *Temp = new char[200];
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(Temp, "WARNING: %E Failed with the following error: \n%s\nPort: %d\n",
(char*)ErrorText, lpMsgBuf, m_nPortID);
MessageBox(NULL, Temp, "Application Error", MB_ICONINFORMATION);
LocalFree(lpMsgBuf);
delete [] Temp;
}
//---获取当前事件
DWORD CSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}
//----------------
DWORD CSerialPort::GetWriteBufferSize()
{
return m_dwWriteBufferSize;
}
//-----------------
void CSerialPort::ClosePort()
{
SetEvent(m_hShutdownEvent);
SetCommMask(m_hComm, 0);
EscapeCommFunction( m_hComm, CLRDTR );
PurgeComm( m_hComm, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
CloseHandle( m_hComm ) ;
m_hComm = NULL;
// change the selectable items in the menu
CloseHandle(m_ov.hEvent);
}
DCB CSerialPort::GetDCB()
{
return m_hDcb;
}
//---启动线程
BOOL CSerialPort::StartThread()
{
if (!(m_pThread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started\n");
return TRUE;
}
//---重新启动线程
BOOL CSerialPort::RestartThread()
{
TRACE("Thread resumed\n");
m_pThread->ResumeThread();
return TRUE;
}
//---停止线程
BOOL CSerialPort::PauseThread()
{
TRACE("Thread suspended\n");
m_pThread->SuspendThread();
return TRUE;
}
char CSerialPort::ConvertHexChar(char ch)
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='A')&&(ch<='F'))
return ch-'A'+10;
else if((ch>='a')&&(ch<='f'))
return ch-'a'+10;
else return (-1);
}
void CSerialPort::String2Hex(CString str, CString &senddata)
{
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.GetLength();
for(int i=0;i<len;)
{
char lstr,hstr=str[i];
if(hstr==' ')
{
i++;
continue;
}
i++;
if(i>=len)
break;
lstr = str[i];
hexdata=ConvertHexChar(hstr);
lowhexdata=ConvertHexChar(lstr);
if((hexdata==16)||(lowhexdata==16))
break;
else
hexdata=hexdata*16+lowhexdata;
i++;
senddata+=(char)hexdata;
hexdatalen++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -