⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comthread.cpp

📁 一个简明的串口通讯例子
💻 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 + -