VC串口通讯DLL.docx

上传人:b****5 文档编号:6658865 上传时间:2023-01-08 格式:DOCX 页数:25 大小:21.96KB
下载 相关 举报
VC串口通讯DLL.docx_第1页
第1页 / 共25页
VC串口通讯DLL.docx_第2页
第2页 / 共25页
VC串口通讯DLL.docx_第3页
第3页 / 共25页
VC串口通讯DLL.docx_第4页
第4页 / 共25页
VC串口通讯DLL.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

VC串口通讯DLL.docx

《VC串口通讯DLL.docx》由会员分享,可在线阅读,更多相关《VC串口通讯DLL.docx(25页珍藏版)》请在冰豆网上搜索。

VC串口通讯DLL.docx

VC串口通讯DLL

VC串口通讯DLL

串口在工业应用是极为普遍的,我用API封装了同步和异步的串口类,以及一个具有监视线程的异步串口类;使用简单高效,具有工业强度,我在BC,BCB,VC,BCBX,GCC下编译通过,相信足够应付大多数情况,而且还可以继承扩展,下面简单介绍使用方法

库的层次结构:

_base_com:

虚基类,基本接口,可自行扩展自己的串口类

_sync_com:

_base_com的子类,同步应用,适合简单应用

_asyn_com:

_base_com的子类,异步应用(重叠I/O),适合较高效应用,NT平台

_thread_com:

_asyn_com的子类,异步应用,监视线程,适合较复杂应用,窗口通知消息和继承扩展的使用方式;几个问题:

结束线程

如何从WaitCommEvent(pcom->_com_handle,&mask,&pcom->_wait_o)这个API退出以便顺利结束线程:

方案1:

SetCommMask(_com_handle,0);这个方法在MSDN有载,当在一些情况下并不完全有效,原因未知;

方案2:

SetEvent(_wait_o.hEvent);直接激活重叠IO结构中的事件句柄,绝对有效;这份代码我两种都用;

打开10以上的COM端口

在NT/2000下打开编号10以上端口用

_com_handle=CreateFile(

“COM10“,

GENERIC_READGENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMALFILE_FLAG_OVERLAPPED,//重叠I/O

NULL

);

将提示错误,这样就OK:

_com_handle=CreateFile(

“\\\\.\\COM10“,//对应的就是\\.\COM10

GENERIC_READGENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMALFILE_FLAG_OVERLAPPED,//重叠I/O

NULL

);

线程中循环的低效率问题

使用SetCommMask(pcom->_com_handle,EV_RXCHAREV_ERR)监视接受字符和错误消息;一旦有个字符来就会激活WaitCommEvent通常作以下接受操作:

if(!

WaitCommEvent(pcom->_com_handle,&mask,&pcom->_wait_o))

{

if(GetLastError()==ERROR_IO_PENDING)

{

GetOverlappedResult(pcom->_com_handle,&pcom->_wait_o,&length,true);

}

}

if(mask&EV_ERR)//==EV_ERR

ClearCommError(pcom->_com_handle,&error,&stat);

if(mask&EV_RXCHAR)//==EV_RXCHAR

{

pcom->on_receive();//接收到字符

//或发送到窗口消息

}

这样频繁的函数调用或接受发送消息,效率低下,我添加扫描缓冲区的代码,当字符数超过设定的字符数才作接受字符的操作;

if(mask&EV_RXCHAR)//==EV_RXCHAR

{

ClearCommError(pcom->_com_handle,&error,&stat);

if(stat.cbInQue>pcom->_notify_num)//_notify_num是设定得字符数

pcom->on_receive();

}

类似于流的输出方式

我编了一个简单的写串口的方式,可以类似于流将简单的数据类型输出

template

_asyn_com&operator<<(Tx)

{

strstreams;

s<

write(s.str(),s.pcount());

return*this;

}

就可以这样使用

_sync_comcom1;

com1.open(1,9600);

com1<<“thenrandom()'sreturnvalueis“<

com1.close();

本串口类库的主要接口

class_base_com

{

boolopen(intport);

boolopen(intport,intbaud_rate);

boolopen(intport,char*set_str);//set_str:

“9600,8,n,1“

boolset_state(intBaudRate,intByteSize=8,intParity=NOPARITY,intStopBits=ONESTOPBIT)

//设置内置结构串口参数:

波特率,停止位

boolset_state(char*set_str)

boolis_open();

HANDLEget_handle();

virtualboolopen_port()=0;//继承用的重要函数

virtualclose();

}

class_sync_com:

public_base_com//同步

{

intread(char*buf,intbuf_size);//自动补上'\0',将用去一个字符的缓冲区

intwrite(char*buf,intlen);

intwrite(char*buf);

}

class_asyn_com:

public_base_com//异步

{

intread(char*buf,intbuf_size);//自动补上'\0',将用去一个字符的缓冲区

intwrite(char*buf,intlen);

intwrite(char*buf);

}

class_thread_com:

public_asyn_com//线程

{

virtualvoidon_receive()//供线程接受到字符时调用,可继承替换之

{

if(_notify_hwnd)

PostMessage(_notify_hwnd,ON_COM_RECEIVE,WPARAM(_port),LPARAM(0));

else

{

if(_func)

_func(_port);

}

}

voidset_hwnd(HWNDhwnd);//设置窗口句柄,发送ON_COM_RECEIVEWM_USER+618

voidset_func(void(*f)(int));//设置调用函数,窗口句柄优先

voidset_notify_num(intnum);//设定发送通知,接受字符最小值

}

一些应用范例

当然首先#include"_com.h"

一、打开串口1同步写

charstr[]="com_classtest";

_sync_comcom1;//同步

com1.open

(1);//相当于com1.open(1,9600);com1.open(1,"9600,8,n,1");

for(inti=0;i<100;i++)

{

Sleep(500);

com1.write(str);//也可以com1.write(str,strlen(str));

}

com1.close();

二、打开串口2异步读

charstr[100];

_asyn_comcom2;//异步

com2.open

(2);//相当于com2.open(2,9600);com2.open(2,"9600,8,n,1");

if(!

com2.is_open())

cout<<"COM2notopen,error:

"<

/*

也可以如下用法

if(!

com2.open

(2))

cout<<"COM2notopen,error:

"<

*/

for(inti=0;i<100;i++)

{

Sleep(500);

if(com2.read(str,100)>0)//异步读,返回读取字符数

cout<

}

com2.close();

三、扩展应用具有监视线程的串口类

class_com_ex:

publicthread_com

{

public:

virtualon_receive()

{

charstr[100];

if(read(str,100)>0)//异步读,返回读取字符数

cout<

}

};

intmain(intargc,char*argv[])

{

try

{

charstr[100];

_com_excom2;//异步扩展

com2.open

(2);

Sleep(10000);

com2.close();

}

catch(exception&e)

{

cout<

}

return0;

}

四、桌面应用可发送消息到指定窗口(在C++Builder和VC++测试通过)

VC++

接受消息

BEGIN_MESSAGE_MAP(ComDlg,CDialog)

//{{AFX_MSG_MAP(ComDlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_WM_DESTROY()

//}}AFX_MSG_MAP

ON_MESSAGE(ON_COM_RECEIVE,On_Receive)

END_MESSAGE_MAP()

打开串口,传递窗口句柄

_thread_comcom2;

com2.open

(2);

com2.set_hwnd(ComDlg->m_hWnd);

处理消息

LRESULTComDlg:

:

On_Receive(WPARAMwp,LPARAMlp)

{

charstr[100];

com2.read(str,100);

charcom_str[10];

strcpy(com_str,"COM");

ltoa((long)wp,com_str+3,10);//WPARAM保存端口号

MessageBox(str,com_str,MB_OK);

return0;

}

C++Builder

classTForm1:

publicTForm

{

__published:

//IDE-managedComponents

void__fastcallFormClose(TObject*Sender,TCloseAction&Action);

void__fastcallFormCreate(TObject*Sender);

private:

//Userdeclarations

public:

//Userdeclarations

voidOn_Receive(TMessage&Message);

__fastcallTForm1(TComponent*Owner);

_thread_comcom2;

BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(ON_COM_RECEIVE,TMessage,On_Receive)

END_MESSAGE_MAP(TForm)

};

void__fastcallTForm1:

:

FormClose(TObject*Sender,TCloseAction&Action)

{

com2.close();

}

//---------------------------------------------------------------------------

void__fastcallTForm1:

:

FormCreate(TObject*Sender)

{

com2.open

(2);

com2.set_hwnd(Handle);

}

//---------------------------------------------------------------------------

voidTForm1:

:

On_Receive(TMessage&Message)

{

charxx[20];

intport=Message.WParam;

if(com2.read(xx,20)>0)

ShowMessage(xx);

}

错误和缺陷在所难免,欢迎来信批评指正;wushaojian@

附完整源代码_com.h

/*

串口基础类库(WIN32)ver0.1

编译器:

BC++5;C++BUILDER4,5,6,X;VC++5,6;VC.NET;GCC;

class_base_com:

虚基类基本串口接口;

class_sync_com:

同步I/O串口类;

class_asyn_com:

异步I/O串口类;

class_thread_com:

异步I/O辅助读监视线程可转发窗口消息串口类(可继承虚函数on_receive用于读操作);

class_com:

_thread_com同名

copyright(c)2004.8llbirdwushaojian@

*/

/*

Example:

*/

#ifndef_COM_H_

#define_COM_H_

#pragmawarning(disable:

4530)

#pragmawarning(disable:

4786)

#pragmawarning(disable:

4800)

#include

#include

#include

#include

#include

usingnamespacestd;

#include

class_base_com//虚基类基本串口接口

{

protected:

volatileint_port;//串口号

volatileHANDLE_com_handle;//串口句柄

char_com_str[20];

DCB_dcb;//波特率,停止位,等

COMMTIMEOUTS_co;//超时时间

virtualboolopen_port()=0;

voidinit()//初始化

{

memset(_com_str,0,20);

memset(&_co,0,sizeof(_co));

memset(&_dcb,0,sizeof(_dcb));

_dcb.DCBlength=sizeof(_dcb);

_com_handle=INVALID_HANDLE_VALUE;

}

virtualboolsetup_port()

{

if(!

is_open())

returnfalse;

if(!

SetupComm(_com_handle,8192,8192))

returnfalse;//设置推荐缓冲区

if(!

GetCommTimeouts(_com_handle,&_co))

returnfalse;

_co.ReadIntervalTimeout=0xFFFFFFFF;

_co.ReadTotalTimeoutMultiplier=0;

_co.ReadTotalTimeoutConstant=0;

_co.WriteTotalTimeoutMultiplier=0;

_co.WriteTotalTimeoutConstant=2000;

if(!

SetCommTimeouts(_com_handle,&_co))

returnfalse;//设置超时时间

if(!

PurgeComm(_com_handle,PURGE_TXABORTPURGE_RXABORTPURGE_TXCLEARPURGE_RXCLEAR))

returnfalse;//清空串口缓冲区

returntrue;

}

inlinevoidset_com_port(intport)

{

charp[12];

_port=port;

strcpy(_com_str,"\\\\.\\COM");

ltoa(_port,p,10);

strcat(_com_str,p);

}

public:

_base_com()

{

init();

}

virtual~_base_com()

{

close();

}

//设置串口参数:

波特率,停止位,等支持设置字符串"9600,8,n,1"

boolset_state(char*set_str)

{

if(is_open())

{

if(!

GetCommState(_com_handle,&_dcb))

returnfalse;

if(!

BuildCommDCB(set_str,&_dcb))

returnfalse;

returnSetCommState(_com_handle,&_dcb)==TRUE;

}

returnfalse;

}

//设置内置结构串口参数:

波特率,停止位

boolset_state(intBaudRate,intByteSize=8,intParity=NOPARITY,intStopBits=ONESTOPBIT)

{

if(is_open())

{

if(!

GetCommState(_com_handle,&_dcb))

returnfalse;

_dcb.BaudRate=BaudRate;

_dcb.ByteSize=ByteSize;

_dcb.Parity=Parity;

_dcb.StopBits=StopBits;

returnSetCommState(_com_handle,&_dcb)==TRUE;

}

returnfalse;

}

//打开串口缺省9600,8,n,1

inlineboolopen(intport)

{

returnopen(port,9600);

}

//打开串口缺省baud_rate,8,n,1

inlineboolopen(intport,intbaud_rate)

{

if(port<1port>1024)

returnfalse;

set_com_port(port);

if(!

open_port())

returnfalse;

if(!

setup_port())

returnfalse;

returnset_state(baud_rate);

}

//打开串口

inlineboolopen(intport,char*set_str)

{

if(port<1port>1024)

returnfalse;

set_com_port(port);

if(!

open_port())

returnfalse;

if(!

setup_port())

returnfalse;

returnset_state(set_str);

}

inlineboolset_buf(intin,intout)

{

returnis_open()?

SetupComm(_com_handle,in,out):

false;

}

//关闭串口

inlinevirtualvoidclose()

{

if(is_open())

{

CloseHandle(_com_handle);

_com_handle=INVALID_HANDLE_VALUE;

}

}

//判断串口是或打开

inlineboolis_open()

{

return_com_handle!

=INVALID_HANDLE_VALUE;

}

//获得串口句炳

HANDLEget_handle()

{

return_com_handle;

}

operatorHANDLE()

{

return_com_handle;

}

};

class_sync_com:

public_base_com

{

protected:

//打开串口

virtualboolopen_port()

{

if(is_open())

close();

_com_handle=CreateFile(

_com_str,

GENERIC_READGENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL,

NULL

);

assert(is_open());

returnis_open();//检测串口是否成功打开

}

public:

_sync_com()

{

}

//同步读

intread(char*buf,intbuf_len)

{

if(!

is_open())

return0;

buf[0]='\0';

COMSTATstat;

DWORDerror;

if(ClearCommError(_com_handle,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 电大

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1