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