请问:有没有BCB的COM口通讯的例程?

fido 2000-02-01 12:40:00
请给出一个详细的例子,谢谢。
...全文
279 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
我用的是 C++ Builder 的哥哥 Borland C++ 5 编的串口类,
使用非常简单,稍加改动就可以在 C++ Builder 里面运行,
因为 C++ Builder 仍然用的是 Borland C++ 5.x 的编译器,
这里有完整的代码,如果发现有bug请告诉我,同样我也会
感谢你的,因为这段代码正在使用中。

串口通讯用的是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 类的实现就明白了, TCommQueue 是保存数据的队列
//TComm32 & TCommQueue, Copyright (C) ybchen, EMail: ybchen@email.com.cn
//======================================================================

class TCommQueue
{
public:
TCommQueue(long BufSize=8192);
virtual ~TCommQueue();

long In(char far *s, long n=1); //RetVal: num of chars pushed in
long Out(char far *s, long n=1); //RetVal: num of chars poped out
long Read(char far *s, long n=1, long Offs=0); //RetVal: num of chars read

void Clear(void) { _First = _Count = 0; }
long Count(void) { return _Count; }
long QSize(void) { return _BufSize; }
bool Valid(void) { return _Buffer != 0; }

protected:
long _BufSize, _First, _Count;
char far *_Buffer;
};

//-----------------------------------------------------------------//
// To use TComm32, The message WM_COMMNOTIFY must be processed //
// in the user's window as following: //
//-----------------------------------------------------------------//
// EV_MESSAGE(WM_COMMNOTIFY, EvCommNotify), //
// LRESULT TUserWindow::EvCommNotify(WPARAM wParam, LPARAM lParam) //
// { //
// ((TComm32 *)lParam)->CommNotify(wParam); //
// ... ... // add your code here (bytes received or transed) //
// return true; //
// } //
//-----------------------------------------------------------------//

class 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;
};

//============================================================================//
// TCommQueue //
//============================================================================//
TCommQueue::TCommQueue(long BufSize)
{
_BufSize = BufSize;
_First = 0;
_Count = 0;
_Buffer = (char far *)malloc(_BufSize);
}

TCommQueue::~TCommQueue()
{
if(_Buffer)
{
free(_Buffer);
_Buffer=0;
}
}

long TCommQueue::In(char far *c, long n)
{
if(_Buffer)
{
long i, k, i0;

i0=(_First+_Count)%_BufSize;
if((i=_BufSize-_Count)>n)
i=n;
if((k=i0+i-_BufSize)<0)
k=0;
i-=k;

if(c)
{
memcpy(_Buffer+i0, c, i);
memcpy(_Buffer, c+i, k);
}

_Count+=i+k;
return i+k;
}

return 0;
}

long TCommQueue::Out(char far *c, long n)
{
if(_Buffer)
{
long i, k;

if((i=_Count)>n)
i=n;
if((k=_First+i-_BufSize)<0)
k=0;
i-=k;

if(c)
{
memcpy(c , _Buffer+_First, i);
memcpy(c+i, _Buffer , k);
}

_Count-=i+k;
_First+=i+k;
_First%=_BufSize;
return i+k;
}

return 0;
}

long TCommQueue::Read(char far *c, long n, long Offs)
{
if(_Buffer)
{
if((Offs>=_Count) and and (Offs<0))
return 0;

long i, k, i0;

i0=(_First+Offs)%_BufSize;
if((i=_Count-Offs)>n)
i=n;
if((k=i0+i-_BufSize)<0)
k=0;
i-=k;

if(c)
{
memcpy(c , _Buffer+i0, i);
memcpy(c+i, _Buffer , k);
}

return i+k;
}

return 0;
}

//============================================================================//
// TComm32 //
//============================================================================//
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<100); 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);
}
}

Firing_Sky 2000-02-13
  • 打赏
  • 举报
回复
#include <windows.h>
#pragma hdrstop
#include "ICCDevice.h"
static HANDLE ComHandle;
//static HANDLE hCom[4];
static COMMTIMEOUTS MyCommTimeouts;
DCB dcb;
HINSTANCE hInstance;
//---------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
hInstance=hinst;
return 1;
}
//------------------------------------------------------------------------
HINSTANCE __declspec(dllexport) __stdcall GetDLLInstance()
{
return(hInstance);
}
//------------------------------------------------------------------------------

bool ReceiveByteFromComDev(double TimeReceiveDelay, unsigned char* ByteBuf, HANDLE hCom)
{
unsigned long dwNumRead ;
unsigned long dwNumtoRead ;
unsigned char TempCommRead[3];
GetCommTimeouts(hCom,&MyCommTimeouts);
MyCommTimeouts.ReadIntervalTimeout = TimeReceiveDelay;
MyCommTimeouts.ReadTotalTimeoutMultiplier = 1;
MyCommTimeouts.ReadTotalTimeoutConstant = TimeReceiveDelay;
SetCommTimeouts(hCom ,&MyCommTimeouts );
dwNumtoRead = 1 ;
BOOL Fcom=ReadFile(hCom,&TempCommRead,dwNumtoRead ,&dwNumRead,NULL);
if (Fcom && dwNumRead!= 0) {*ByteBuf = TempCommRead[0] ;return true;}
else return false;
}
//-------------------------------------------------
bool SendByteToComm(unsigned char ByteToSend, HANDLE hCom)
{
int TimeSendDelay=1;
unsigned long dwNumWrite ;
unsigned long dwNumtoWrite ;
unsigned char TempCommWrite[3];
GetCommTimeouts(hCom,&MyCommTimeouts);
MyCommTimeouts.WriteTotalTimeoutMultiplier = TimeSendDelay;
MyCommTimeouts.WriteTotalTimeoutConstant = 1;
SetCommTimeouts(hCom,&MyCommTimeouts);
dwNumtoWrite = 1 ;
TempCommWrite[0] = ByteToSend ;
if(WriteFile(hCom, &TempCommWrite , dwNumtoWrite,&dwNumWrite,NULL)) return true;
else return false;
}

int __declspec(dllexport) __stdcall CloseComm(HANDLE hCom)
{
if(CloseHandle( hCom )) return 1;
else return 0;
}
//-------------------------------------------------------------------------------
int __declspec(dllexport) __stdcall SetComm(int CommID,HANDLE *sendhcom)
{
if(CommID<1 and and CommID>4)return 0;
char ComName[]="COM1";
switch(CommID)
{
case 1:{ComName[3]='1';break;}
case 2:{ComName[3]='2';break;}
case 3:{ComName[3]='3';break;}
case 4:{ComName[3]='4';break;}
default: return 0;
}
ComHandle = CreateFile(ComName,
GENERIC_READ and GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (!SetupComm( ComHandle ,1024,1024)){ CloseHandle(ComHandle);return 0;}
GetCommState(ComHandle, &dcb);//Read com' dcb setting
dcb.BaudRate = CBR_19200;
dcb.ByteSize = 8; // number of bits/byte, 4-8
dcb.Parity = EVENPARITY; // 0-4=no,odd,even,mark,space
dcb.StopBits = ONESTOPBIT;
dcb.fDtrControl = DTR_CONTROL_DISABLE;//make DTR disable
dcb.XonChar = 0x17; // XON ASCII char
dcb.XoffChar = 0x19; // XOFF ASCII char
dcb.XonLim = 256 ;
dcb.XoffLim = 1;
SetCommMask(ComHandle , EV_TXEMPTY and EV_RXCHAR and EV_ERR );
PurgeComm(ComHandle , PURGE_TXCLEAR);
PurgeComm(ComHandle , PURGE_RXCLEAR);
if (!SetCommState(ComHandle, &dcb))return 0;
*sendhcom = ComHandle;
// hCom[CommID-1]=ComHandle;
return 1;
}
//------------------------------------------------------------------------------
int __declspec(dllexport) __stdcall Reset(HANDLE hCom)
{
GetCommState(hCom, &dcb);
dcb.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(hCom, &dcb))return 0;
GetCommState(hCom, &dcb);
dcb.fDtrControl = DTR_CONTROL_DISABLE;
if (!SetCommState(hCom, &dcb))return 0;
else return 1;
}

int __declspec(dllexport) __stdcall ShutDown(HANDLE hCom)
{
unsigned char p1=0x00,p2=0x00;
if(!SendByteToComm(0xfa, hCom))return 0;
if(!SendByteToComm(0x46, hCom))return 0;
if(!ReceiveByteFromComDev(2000,&p1, hCom));
if(!ReceiveByteFromComDev(500,&p2, hCom));
if(!ReceiveByteFromComDev(500,&p2, hCom));
if(!ReceiveByteFromComDev(500,&p2, hCom));
if(!ReceiveByteFromComDev(500,&p2, hCom));
PurgeComm(hCom, PURGE_TXCLEAR);
PurgeComm(hCom, PURGE_RXCLEAR);
return 1;
}
nil 2000-02-13
  • 打赏
  • 举报
回复
我有,请与我联系:bcb4zp@21cn.com
ysh 2000-02-05
  • 打赏
  • 举报
回复
我正在用BCB串口通信程序,已做出现成的程序,但不知是否符合你的要求。查询请E到yangsh_sky@371.net
bunny 2000-02-04
  • 打赏
  • 举报
回复
我记得在程序员大本营里有的说!
AutoAsm 2000-02-03
  • 打赏
  • 举报
回复
例程没有,不过COM 通讯 RING 3 就够了,不是太难。
radish 2000-02-01
  • 打赏
  • 举报
回复
在我的网页上有一个DELPHI的,不知道你要不要(radsworld.myrice.com)

13,824

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧