求教关于visual C++ V6.0 中串行口的编程方法

longman 2000-02-03 03:15:00
...全文
225 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
yb 2000-02-07
  • 打赏
  • 举报
回复
同意lov的意见。
lov 2000-02-03
  • 打赏
  • 举报
回复
我曾经开发过交换机计费的项目,当时的串口通信我是用winapi函数做的,太复杂.我发
现用微软的Microsoft Communications Control控件很简单,详细的函数说明MSDN有,我相信它能解决你问题!
Firing_Sky 2000-02-03
  • 打赏
  • 举报
回复
串行口是作为文件方式打开的,用CreateFile打开串口,并得到串口句柄
然后设定一个DCB结构指定端口的特性
读写串口文件
关闭串口文件
  • 打赏
  • 举报
回复
最近我用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);
}
}
关门开门 2000-02-03
  • 打赏
  • 举报
回复
use createfile("\\\\.\\COM1",.....);
then use readfile and writefile.
at last closehandle

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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