use createfile("\\\\.\\COM1",.....);
then use readfile and writefile.
at last closehandle
最近我用Borland C++编了一个串口通讯的程序,
Visual C++ 与此类似,我把我编的串口类贴到此处,
如果有错误或不完善的地方还请大家一起研究 :-)
其中 TCommQueue 是我编的一个队列,我不详细说了 --
不要告诉我不知道什么是队列 :-)
串口通讯用的是32位API函数,(16位的Win3.x API函数早已
不复存在): CreateFile、ReadFile、WriteFile、
CloseHandle等。
因为这些函数如果用查询方法,他们的超时工作(用
SetCommTimeouts 设置)会引起系统访问消息的延时,十分
影响程序运行的效率,因此采用了重叠操作,在另一个线程
里面监视串口通讯情况,如果有数据收到或发送缓存空就向
主线程发一个串口通讯消息,并暂停监视,主线程相应完
消息(读/写)后监视线程继续工作。
这个类使用非常简单,比如要打开两个串口同时通讯,可以
如下定义:
TComm32 *CommA, *CommB;
初始化:
CommA = new TComm32(this); //必须指明在哪个窗口消息里处
CommB = new TComm32(this); //理串口数据,这里用的是this
CommA -> SetPort(1); //用COM1,在使用中可以随时更改
CommB -> SetPort(2); //用COM2,在使用中可以随时更改
CommA -> SetParams(CBR_4800, NOPARITY, 8, ONESTOPBIT);
CommB -> SetParams(CBR_9600, NOPARITY, 8, ONESTOPBIT);
打开串口:
if((Error = CommA -> Open()) != 0)
{
//错误处理
}
if((Error = CommB -> Open()) != 0)
{
//错误处理
}
响应串口消息:
可以在此处读串口,也可以在定时器或其他任何函数里面
本消息的参数 wParam 表示串口进行了读还是写操作
本消息的参数 lParam 是响应操作的串口对象的地址
DEFINE_RESPONSE_TABLE1(TMyWindow, TParentWindow)
EV_MESSAGE(WM_COMMNOTIFY, EvCommNotify),
... //其他消息
END_RESPONSE_TABLE;
LRESULT TMyWindow::EvCommNotify(WPARAM wParam, LPARAM lParam)
{
((TComm32 *)lParam)->CommNotify(wParam); //必须调用这个函数
//可以在此处读串口,也可以在定时器或其他函数里面
//如果在此处读串口数据,可以按如下方法:
while((BytesRead = CommA->Read(Buffer, BufferSize)) != 0)
{
//处理从CommA里面读出的数据
}
while((BytesRead = CommB->Read(Buffer, BufferSize)) != 0)
{
//处理从CommB里面读出的数据
}
return true; //必须返回非零值
}
写串口:可以在任何位置调用:
BytesWrite = CommA->Write(Buffer, BufferSize);
BytesWrite = CommB->Write(Buffer, BufferSize);
关闭串口:
CommA->Close();
CommB->Close();
在程序结束前需要删除CommA、CommB对象,但关闭串口不是必须的,
因为在他们的析构函数里面已经关闭了串口
delete CommA;
delete CommB;
//=========================================================
//我不多说了,看看 TComm32 类的实现就明白了
//TComm32, Copyright (C) ybchen, EMail: ybchen@email.com.cn
//=========================================================
class _OWLCLASS TComm32
{
public:
TComm32(TWindow *Win);
virtual ~TComm32();
virtual int SetPort(int COMn);
virtual int SetParams(DWORD Baud, BYTE Parity, BYTE ByteSize, BYTE StopBits);
virtual int SetBufSize(long InBufSize, long OutBufSize, long HwInSize, long HwOutSize);
virtual int Open(void);
virtual int Close(void);
virtual int Opened(void) { return Handle!=INVALID_HANDLE_VALUE; }
virtual long Read(char far *s, long n=1);
virtual long Write(char far *s, long n=1);
virtual void CommNotify(int NotifyType); //EV_RXCHAR or EV_TXEMPTY
TCommQueue *InBuf;
TCommQueue *OutBuf;
TWindow *ComWin;
HANDLE Handle; //INVALID_HANDLE_VALUE
HANDLE hRecvEvent; //NULL
HANDLE hSendEvent; //NULL
OVERLAPPED read_os;
OVERLAPPED write_os;
volatile long CommThreadId; //-1
volatile bool RunComThread; // 0
volatile bool CommThreadRunning; // 0
int _PortNo;
long _InBufSize, _OutBufSize, _HwInSize, _HwOutSize;
DWORD _Baud;
BYTE _Parity, _ByteSize, _StopBits;
};
void _Comm32_CommWatchThread(void *Param) //监视线程
{
OVERLAPPED os;
DWORD dwTransfer, dwEvtMask;
TComm32 *Comm = (TComm32 *) Param;
Comm->CommThreadRunning = 1;
os.hEvent = CreateEvent(NULL, true, false, NULL);
if(os.hEvent)
{
if(SetCommMask(Comm->Handle, EV_RXCHAR and EV_TXEMPTY))
{
while(Comm->RunComThread)
{
dwEvtMask = 0;
if(!WaitCommEvent(Comm->Handle, &dwEvtMask, &os))
{
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(Comm->Handle, &os, &dwTransfer, true);
}
if(dwEvtMask & EV_RXCHAR)
{
WaitForSingleObject(Comm->hRecvEvent, 0xffffffff);
ResetEvent(Comm->hRecvEvent);
Comm->ComWin->PostMessage(WM_COMMNOTIFY, EV_RXCHAR, (LPARAM)Param);
}
if(dwEvtMask & EV_TXEMPTY)
{
WaitForSingleObject(Comm->hSendEvent, 0xffffffff);
ResetEvent(Comm->hSendEvent);
Comm->ComWin->PostMessage(WM_COMMNOTIFY, EV_TXEMPTY, (LPARAM)Param);
}
}
}
CloseHandle(os.hEvent);
}
Comm->CommThreadRunning = 0;
_endthread();
}
TComm32::TComm32(TWindow *Win)
{
InBuf = NULL;
OutBuf = NULL;
ComWin = Win;
Handle = INVALID_HANDLE_VALUE;
hRecvEvent = NULL;
hSendEvent = NULL;
memset(&read_os, 0, sizeof(OVERLAPPED));
memset(&write_os, 0, sizeof(OVERLAPPED));
CommThreadId = -1;
RunComThread = 0;
CommThreadRunning = 0;
_PortNo = 2; //"COM2"
_InBufSize = 8192;
_OutBufSize = 8192;
_HwInSize = 1200;
_HwOutSize = 1200;
_Baud = CBR_9600;
_Parity = NOPARITY;
_ByteSize = 8;
_StopBits = ONESTOPBIT;
}
TComm32::~TComm32()
{
Close();
}
int TComm32::SetPort(int COMn)
{
bool NeedReopen = Opened();
int Err = 0;
if(NeedReopen)
if((Err=Close())!=0)
return -Err;
_PortNo = COMn;
if(NeedReopen)
if((Err=Open())!=0)
return Err;
return Err;
}
int TComm32::SetParams(DWORD Baud, BYTE Parity, BYTE ByteSize, BYTE StopBits)
{
bool NeedReopen = Opened();
int Err = 0;
if(NeedReopen)
if((Err=Close())!=0)
return -Err;
_Baud = Baud ;
_Parity = Parity ;
_ByteSize = ByteSize;
_StopBits = StopBits;
if(NeedReopen)
if((Err=Open())!=0)
return Err;
return Err;
}
int TComm32::SetBufSize(long InBufSize, long OutBufSize, long HwInSize, long HwOutSize)
{
bool NeedReopen = Opened();
int Err = 0;
if(NeedReopen)
if((Err=Close())!=0)
return -Err;
_InBufSize = InBufSize ;
_OutBufSize = OutBufSize;
_HwInSize = HwInSize ;
_HwOutSize = HwOutSize ;
if(NeedReopen)
if((Err=Open())!=0)
return Err;
return Err;
}
int TComm32::Open(void)
{
int Err = 0;
if(!Opened())
{
DCB dcb;
char Fmt_COMn[] = "COM%d";
char Str[64];
if(!Err)
{
InBuf = new TCommQueue(_InBufSize);
if(!InBuf->Valid())
Err=-1;
}
if(!Err)
{
OutBuf = new TCommQueue(_OutBufSize);
if(!OutBuf->Valid())
Err=-2;
}
if(!Err)
{
sprintf(Str, Fmt_COMn, _PortNo);
Handle=CreateFile(Str, GENERIC_READ and GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL and FILE_FLAG_OVERLAPPED, NULL);
if(Handle==INVALID_HANDLE_VALUE)
Err=-3;
}
if(!Err)
{
if(!SetCommMask(Handle, EV_RXFLAG))
Err=-4;
}
if(!Err)
{
if(!SetupComm(Handle, _HwInSize, _HwOutSize))
Err=-5;
}
if(!Err)
{
if(GetCommState(Handle, &dcb))
{
dcb.BaudRate = _Baud;
dcb.ByteSize = _ByteSize;
dcb.Parity = _Parity;
dcb.StopBits = _StopBits;
if(!SetCommState(Handle, &dcb))
Err = -7;
}
else
{
Err = -6;
}
}
if(!Err)
{
memset(&read_os, 0, sizeof(OVERLAPPED));
hRecvEvent=CreateEvent(NULL,true,true,NULL);
read_os.hEvent=CreateEvent(NULL,true,false,NULL);
if((!hRecvEvent) and and (!read_os.hEvent))
Err=-8;
}
if(!Err)
{
memset(&write_os, 0, sizeof(OVERLAPPED));
hSendEvent=CreateEvent(NULL,true,true,NULL);
write_os.hEvent=CreateEvent(NULL,true,false,NULL);
if((!hSendEvent) and and (!write_os.hEvent))
Err=-9;
}
if(!Err)
{
RunComThread = 1;
CommThreadId = _beginthread(_Comm32_CommWatchThread, 4096, this);
if(CommThreadId == -1)
{
RunComThread = 0;
Err = -10;
}
}
if(Err)
Close();
}
return Err;
}
int TComm32::Close(void)
{
int i, Err = 0;
if(Opened())
for(i=0; (CommThreadRunning) && (i<500); i++)
{
RunComThread = 0;
SetCommMask(Handle, EV_RXFLAG);
Sleep(10);
}
if(CommThreadRunning)
Err=-1;
else
CommThreadId=-1;
if(hRecvEvent)
{
CloseHandle(hRecvEvent);
hRecvEvent = NULL;
}
if(read_os.hEvent)
{
CloseHandle(read_os.hEvent);
memset(&read_os, 0, sizeof(OVERLAPPED));
}
if(hSendEvent)
{
CloseHandle(hSendEvent);
hSendEvent = NULL;
}
if(write_os.hEvent)
{
CloseHandle(write_os.hEvent);
memset(&write_os, 0, sizeof(OVERLAPPED));
}
if(Handle!=INVALID_HANDLE_VALUE)
{
CloseHandle(Handle);
Handle=INVALID_HANDLE_VALUE;
}
if(OutBuf)
{
delete OutBuf;
OutBuf = NULL;
}
if(InBuf)
{
delete InBuf;
InBuf = NULL;
}
return Err;
}
long TComm32::Read(char far *s, long n)
{
return InBuf->Out(s,n);
}
long TComm32::Write(char far *s, long n)
{
long Retv = OutBuf->In(s,n);
ComWin->PostMessage(WM_COMMNOTIFY, EV_TXEMPTY, (LPARAM)this);
return Retv;
}
void TComm32::CommNotify(int NotifyType)
{
if(NotifyType & EV_RXCHAR)
{
DWORD dwErrorFlag, dwLen, dwBytesRd;
COMSTAT ComStat;
char RecvBuf[4096];
ClearCommError(Handle, &dwErrorFlag, &ComStat);
dwLen=ComStat.cbInQue;
if(dwLen>0)
{
if(!ReadFile(Handle, RecvBuf, dwLen, &dwBytesRd, &read_os))
{
if(GetLastError()==ERROR_IO_PENDING)
if(WaitForSingleObject(read_os.hEvent, 1000))
{
}
}
else if(dwBytesRd>0)
{
InBuf->In(RecvBuf, dwBytesRd);
}
}
SetEvent(hRecvEvent);
}
if(NotifyType & EV_TXEMPTY)
{
DWORD dwErrorFlag, dwLen, dwBytesWr;
COMSTAT ComStat;
char SendBuf[4096];
ClearCommError(Handle, &dwErrorFlag, &ComStat);
dwLen=ComStat.cbOutQue;
if(dwLen==0)
{
if(OutBuf->Count())
{
dwLen=OutBuf->Out(SendBuf, 4096);
WriteFile(Handle, SendBuf, dwLen, &dwBytesWr, &write_os);
}
}
SetEvent(hSendEvent);
}
}
串行口是作为文件方式打开的,用CreateFile打开串口,并得到串口句柄
然后设定一个DCB结构指定端口的特性
读写串口文件
关闭串口文件
我曾经开发过交换机计费的项目,当时的串口通信我是用winapi函数做的,太复杂.我发
现用微软的Microsoft Communications Control控件很简单,详细的函数说明MSDN有,我相信它能解决你问题!
同意lov的意见。