📄 serialport.cpp
字号:
{
TRACE("Thread suspended\n");
m_Thread->SuspendThread();
return TRUE;
}
//
// 获取并显示以指定格式显示错误信息
//
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), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);
MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
LocalFree(lpMsgBuf);
delete[] Temp;
}
//
// 向串口写一个字符
//
void CSerialPort::WriteChar(CSerialPort* port)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
// 使该事件回到无信号状态
ResetEvent(port->m_hWriteEvent);
// 进入临界区
EnterCriticalSection(&port->m_csCommunicationSync);
if (bWrite)
{
// 初始化OVERLAPPED结构
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, // 要发送的数据地址
strlen((char*)port->m_szWriteBuffer), // 要发送的数据长度
&BytesSent, // 返回实际发送的数据长度
&port->m_ov); // Overlapped 重叠结构
// 错误处理
if (!bResult)
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
// 正常返回值,写未完成,使用GetOverlappedResults()继续下一步
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
// 其它错误返回值显示错误信息
port->ProcessErrorMessage("WriteFile()");
}
}
}
else
{
// 若写操作以完成,则离开临界区
LeaveCriticalSection(&port->m_csCommunicationSync);
}
} // end if(bWrite)
if (!bWrite)
{
bWrite = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // 串口句柄
&port->m_ov, // Overlapped 重叠结构
&BytesSent, // 以发送字节数
TRUE); // 等待标志
//清空临界区
LeaveCriticalSection(&port->m_csCommunicationSync);
// 处理错误
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
}
} // end if (!bWrite)
// Verify that the data size send equals what we tried to send
// 检验发出的数据大小是否等于我们要发的数据大小
if (BytesSent != strlen((char*)port->m_szWriteBuffer))
{
TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));
}
}
//
// 收到字符,通知所有者
// ReceiveChar不需用户调用,串口主线程在有数据到达串口时自动调用改函数,
// 它将读取到的数据通过自定义消息WM_COMM_RXCHAR发送给父窗口m_pOwner,
// 调用着只需在该窗口内处理WM_COMM_RXCHAR消息即可.
//
void CSerialPort::ReceiveChar(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:
{
// 正常返回值,读未完成,
//调用个 GetOverlappedResults()继续下一步
bRead = FALSE;
break;
}
default:
{
// 其他错误返回值,显示错误信息
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
//读操作已完成,不必再调用 GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)
if (!bRead)
{
bRead = TRUE;
// 继续完成读操作
bResult = GetOverlappedResult(port->m_hComm, // 串口句柄
&port->m_ov, // Overlapped 重叠结构
&BytesRead, // 实际读取字节数
TRUE); // 等待标志
// 错误处理
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)
// 离开临界区
LeaveCriticalSection(&port->m_csCommunicationSync);
// 收到一个字节后,发送WM_COMM_RXCHAR消息到父窗口,通知数据到达
::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
} // end forever loop结束无限循环
}
//
// 向串口写一个字符串,主要用途是把Edit中的内容发送出去
//
void CSerialPort::WriteToPort(char* string)
{
assert(m_hComm != 0); // 当结果有错误时,输出此错误的诊断信息
// 将待发送数据复制到CSerialPort 发送缓冲区中
memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
strcpy(m_szWriteBuffer, string); // 拷贝字符串
// 触发写事件
SetEvent(m_hWriteEvent);
}
//
// 返回设备控制块
//
DCB CSerialPort::GetDCB()
{
return m_dcb;
}
//
// 返回串口状态事件
//
DWORD CSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}
//
// 返回输出缓冲区大小
//
DWORD CSerialPort::GetWriteBufferSize()
{
return m_nWriteBufferSize;
}
//
// ReadBlock 采用与ReceiveChar 不同的由用户显示调用的方式读取窗口
//
BYTE* CSerialPort:: ReadBlock(CSerialPort* port,int &readLen)
{
COMSTAT comstat;
BOOL bRead=TRUE;
BOOL bResult=TRUE;
DWORD dwError=0;
DWORD BytesRead=0;
DWORD BytesToRead=readLen;
BYTE * pRec;
EnterCriticalSection(&port->m_csCommunicationSync); // 进入临界区
bResult=ClearCommError(port->m_hComm,&dwError,&comstat); // 检测并且清除错误条件
LeaveCriticalSection(&port->m_csCommunicationSync); // 离开临界区
if(comstat.cbInQue == 0)
{
//若缓冲区为空,则返回NULL
readLen=0;
return NULL;
}
else
{
//若缓冲区为非空,则为返回数据开辟缓冲区
BytesToRead=BytesToRead+2>comstat.cbInQue?comstat.cbInQue:BytesToRead+2;
pRec=new BYTE[BytesToRead];
}
//进入临界区
EnterCriticalSection(&port->m_csCommunicationSync);
if(bRead)
{
bResult=ReadFile(port->m_hComm,
pRec,
BytesToRead,
&BytesRead,
&port->m_ov);
//错误处理
if(!bResult)
{
switch(dwError=GetLastError())
{
case ERROR_IO_PENDING:
{
bRead=FALSE;
break;
}
default:
{
//其他错误返回值显示错误信息
port->ProcessErrorMessage("ReadFile()");
break;
}
} // end if switch
} // end if !bResult
else
{
//读操作已完成,不必再调用GetOverlappedResults()
bRead=TRUE;
}
} // end if bRead
if(!bRead)
{
bRead=TRUE;
//继续完成读操作
bResult=GetOverlappedResult(port->m_hComm,
&port->m_ov,
&BytesRead,
TRUE);
//错误处理
if(!bRead)
{
port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // end if (!Read)
LeaveCriticalSection(&port->m_csCommunicationSync); // 离开临界区
readLen=BytesRead; // 返回实际读取的字节数
return pRec;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -