//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "assert.h"
#include "mmsystem.h" //精确计时
HANDLE hCom = 0;
DCB dcb;
OVERLAPPED OverRead, OverWrite;
COMSTAT comstat;
OVERLAPPED os;
DWORD dwEvtMask=0;
String dat;
hComThread *Read232;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//内部函数
/*常用串行通讯API函数及其作用
函数名 作用
CreateFile 打开串口
GetCommState 检测串口设置
SetCommState 设置串口
BuilderCommDCB 用字符串中的值来填充设备控制块
GetCommTimeouts 检测通信超时设置
SetCommTimeouts 设置通信超时参数
SetCommMask 设定被监控事件
WaitCommEvent 等待被监控事件发生
WaitForMultipleObjects 等待多个被监测对象的结果
WriteFile 发送数据
ReadFile 接收数据
GetOverlappedResult 返回最后重叠(异步)操作结果
PurgeComm 清空串口缓冲区,退出所有相关操作
ClearCommError 更新串口状态结构体,并清除所有串口硬件错误
CloseHandle 关闭串行口 */
//------ Create COM ----------------------------------------------------------
int __stdcall OpenCom(int port)
{
String comname;
comname = "COM" + IntToStr(port);
if (hCom==INVALID_HANDLE_VALUE)
{
ShowMessage("Can not open the port !");
CloseHandle(hCom);
hCom = 0;
return 0;
}
if(hCom != 0)
return 0;
hCom=CreateFile( comname.c_str(), //文件名
GENERIC_READ|GENERIC_WRITE,//访问模式允许读写
0, //此项必须是0
NULL,//无安全参数
OPEN_EXISTING,//创建方式
FILE_FLAG_OVERLAPPED,//异步工作方式
NULL);
if (hCom==INVALID_HANDLE_VALUE)
{
ShowMessage("Can not open the port !");
CloseHandle(hCom);
hCom = 0;
return 0;
}
if(!GetCommState(hCom,&dcb)) //获得串口设置并用它填充dcb结构体
ShowMessage("GetCommState failed");
if (!SetupComm(hCom,1024,1024)) //设置输入输出缓冲区大小
ShowMessage("SetupComm failed");
//设置dcb结构成员变量
dcb.BaudRate=19200;
dcb.fParity=0;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;
dcb.ByteSize=8;
dcb.fNull=FALSE;
if(!SetCommState(hCom,&dcb)) //重新配置串口
ShowMessage("SetCommState failed");
//设置事件掩码,EV_RXCHAR表示接收一个字符并放到缓冲区划
if (!SetCommMask(hCom,EV_RXCHAR))
ShowMessage("SetCommMask failed");
//创建事件对象,在WaitCommEvent使用
COMSTAT comstat;
DWORD dwError=0;
OverRead.hEvent=CreateEvent(NULL,
true,
false,
NULL);
ClearCommError(hCom,&dwError,&comstat);
//清空串口缓冲区,退出所有相关操作
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
Form1->Caption=comname+" 通信成功!";
Form1->RadioGroup1->Enabled=false;
// Form1->Button1->Enabled=false;
// Form1->Button2->Enabled=true;
//创建线程
Read232 = new hComThread(false); // (false/true) (run/not run )WatchThread when begin
return true;
}
void __fastcall SendDatas( char chStr[1024], unsigned long StrLen)
{
//发送数据
BOOL WriteState;
unsigned long Written ;
DWORD dwError;
WriteState = WriteFile(hCom,//用CreateFile 获得的文件句柄
chStr,//输出缓冲区首址
StrLen,//要求输出的字节数
&Written,//实际输出字节数
&OverWrite);//重叠操作方式数据结构地址
if (WriteState && GetLastError()== ERROR_IO_PENDING )
{
ShowMessage("Error !!!");
}
}
bool StopCom()
{
if (hCom) //Stop COM
{
if (CloseHandle(hCom))
{
Read232->Terminate();
ShowMessage("CloseHandle(hCom) successed");
}
else
{ ShowMessage("Can not close the com !!!");
return false;
}
Form1->RadioGroup1->Enabled=true;
Form1->Caption="通信停止中";
}
else ShowMessage("The com has been stoped !!");
hCom=0;
return true;
}
//---------------------------------------------------------------------------
//线程部分
//---------------------------------------------------------------------------
__fastcall hComThread::hComThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
FreeOnTerminate = true;
}
//---------------------------------------------------------------------------
void __fastcall hComThread::Execute()
{
//---- Place thread code here ----
char ReadBuff[1];
memset(&OverRead,0,sizeof(OVERLAPPED));
OverRead.hEvent=CreateEvent(NULL,true,true,NULL);
if (OverRead.hEvent==NULL) Terminate();
if (!SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY)) Terminate();
while (!Terminated)
{
WaitForSingleObject(OverRead.hEvent,INFINITE);
bool WaitComEv;
DWORD dwError;
AnsiString Gotstr;
DWORD ReadStat;
DWORD BytesRead;
//等待被监控事件发生
WaitComEv=WaitCommEvent(hCom,&dwEvtMask,&OverRead);
if (WaitComEv)
ClearCommError(hCom,&dwError,&comstat); //更新串口状态结构体,并清除所有串口硬件错误
else if (!WaitComEv && GetLastError()==ERROR_IO_PENDING)
{
ClearCommError(hCom,&dwError,&comstat);//更新串口状态结构体,并清除所有串口硬件错误
while (comstat.cbInQue>0)// && dwEvtMask==EV_RXCHAR)使用后部分在win98中不行
{
ReadStat=ReadFile(hCom,//用CreateFile 获得的文件句柄
ReadBuff,//输入缓冲区首址
1, //设定读入字节数
&BytesRead,//实际读入字节数
&os); //重叠操作方式数据结构地址
if (!ReadStat && GetLastError()==ERROR_IO_PENDING )
{
while (!GetOverlappedResult(hCom,&os,&BytesRead,true))
{
dwError=GetLastError();
if (dwError==ERROR_IO_INCOMPLETE)
continue;
else
break;
}
}
dat=dat+ReadBuff[0];
//更新串口状态结构体,并清除所有串口硬件错误
ClearCommError(hCom,&dwError,&comstat);
}
}
}
}
//---------------------------------------------------------------------------
//窗体部分
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
//清输入输出缓冲区
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
dat = "";