📄 comthread.cpp
字号:
//---------------------------------------------------------------------------
//串口监控线程,用于接收字符
//作者:冯华亮
//最后修改日期:2002年5月
#include <vcl.h>
#pragma hdrstop
#include "ComThread.h"
#include "Com.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//构造函数
__fastcall TComThread::TComThread(bool CreateSuspended,HANDLE AhComm,HWND AParent)
: TThread(CreateSuspended)
{
hComm=AhComm;
Parent=AParent;
//异步读操作中用到的重叠结构中的事件
ov_Read.hEvent=CreateEvent(NULL, true, false, NULL);
FreeOnTerminate=true;
}
//---------------------------------------------------------------------------
//析构函数
__fastcall TComThread::~TComThread()
{
//释放对象,如果句柄有效,则关闭
if(ov_Read.hEvent!=NULL)
{
CloseHandle(ov_Read.hEvent);
ov_Read.hEvent=NULL;
}
if (hComm!=INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
hComm=INVALID_HANDLE_VALUE;
}
}
//---------------------------------------------------------------------------
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE) //串口句柄有效
{
Application->MessageBox("串口句柄无效,串口监控线程无法工作.","错误",MB_ICONSTOP);
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);
COMSTAT ComStat; //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING: //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
ProcessErrorMessage("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0) //输入缓冲队列长为0,无字符
continue;
}
//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
if(dwResult==WAIT_OBJECT_0) //事件产生
{
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR) //有一个字符
ReceiveAChar(); //接收一个字符
}
}
}
//---------------------------------------------------------------------------
//接收一个字符
void __fastcall TComThread::ReceiveAChar()
{
COMSTAT ComStat;
DWORD dwError=0;
bool bResult;
DWORD BytesRead=0;
unsigned char ucRxBuff;
//开始无限循环,因为我不知到需要循环多少次.我的解决方法是开始一个无限循环,
//当我已处理了所有的有效数据后才退出.使用这种方法应小心的保证您的程序能
//正常退出循环.即便如此,我仍觉得这是最有效的解决办法
while(1)
{
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)
{
//缓冲区中已无数据,退出循环
break;
}
//读串口
bResult=ReadFile(hComm, //串口句柄
&ucRxBuff, //输入缓冲区地址
1, //想读入的字符数
&BytesRead, //实际被读入的字符数
&ov_Read); //重叠结构指针
if(!bResult) //读串口失败,调用GetLastError()判断原因
{
switch (dwError=GetLastError())
{
case ERROR_IO_PENDING: //重叠操作在后台进行
{
BytesRead=0;
//等待重叠操作结果
bResult=GetOverlappedResult(hComm, //串口句柄
&ov_Read, //重叠结构
&BytesRead, //实际读入字符数
true); //等待直到串口操作超时
if (!bResult) //重叠操作失败
{
ProcessErrorMessage("(读串口时)获取重叠操作结果");
return;
}
break;
}
default:
{
//其它情况说明出错
ProcessErrorMessage("读串口");
return;
}
}
}
//将收到的字符当作消息的参数投递到父窗口
if(BytesRead!=1) //没有读入要求的字符数
continue;
PostMessage(Parent,WM_COMM_RXCHAR,(WPARAM)ucRxBuff,NULL);
}
}
//----------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -