用VC开发串口通信dll控件
VC串口通信技术网《VC串口上位机编程方法简介》介绍了串口编程的常见方法,其中就有使用串口dll控件的方法,dll是一种动态链接库,使用起来非常方便。 本文利用VC编程工具,对Windows提供的API函数进行封装,实现了一个串行通信动态链接库dll的完整实例,实例既给出了DLL函数的编写方法,又包括一份用其它编程工具(VB)对此DLL进行声明及调用的范例。为了使大家能看得懂,本例作了简化。希望对需要进行串行通信编程的网友及需要学习编写DLL的编程爱好者提供一点帮助。 一、有关dll的常识 1、什么是dll DLL是动态链接库Dynamic Link Library 的简称, DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。DLL 是一个包含可由多个程序同时使用的代码和数据的库。Windows API中的所有函数就是包含在DLL中,它有众多优点,如:简化软件项目管理以便分工合作,有助于节省内存,便于资源共享并且可以用多种语言来编写。 用VC++ 编写动态链接有以下四种类型:Win32 DLL、MFC常规DLL(动态链接MFC)、MFC常规DLL(静态链接MFC)、MFC扩展DLL等,关于它们之间的区别,在此不一一介绍,可参阅相关文档。本程序的编写为Win32 DLL。 如何没有dll编写基础,请查阅相关文档,进一步学习dll开发。 2、串口通信一般步骤 在Windows系统,用CreateFile函数来打开串口设备,在打开之前,应该对串口相关参数进行配置,系统通过一个叫DCB(Device Control Block)的结构对串行口进行配置,通过Windows API GetCommState函数可以得到串行通讯口的状态信息,使用SetCommState函数可以对串行通讯口进行设置,配置好后即可打工串口,打开串口后可以通过ReadFile和WriteFile读写串口。实现串行通信一般需按以下四步进行: (1) 打开串口。由于串口是独占性资源,因此应用程序打开串口后,别的应用程序就不能再打开此串口了,所以在使用CreateFile打开串口时相关参数要注意,应使用独点方式。 (2)配置串口。利用GetCommState函数获取串口当前配置,根据需要更改DCB 结构中的参数,然后用SetCommState函数设置串口通讯参数。 (3)数据传送。在串口上进行数据发送接收,并根据需要进行校验,触发一些事件等等。这个串口通讯DLL的目的就是收发数据。 (4)关闭串口。不需要此串口时,关闭串口,供其它的应用程序使用。 3、有关CALLBACK函数 在编写dll时,CALLBACK函数是必不可少的。在微软的官方手册中是这样定义CALLBACK函数的:“CALLBACK函数是由应用程序定义而由操作系统调用的函数”。在我们编写DLL时,就是由应用程序定义,而调用是由我们编写的DLL来执行,这一机制在被调用者(DLL)和调用者(应用程序)之间进行信息传递是非常有用的。这一特性,让初学者较难理解,但是它却是编写串行通信程序者的福音,正是由于使用这一特性,才可很方便地在动态链接库中实现像MSComm控件中的OnComm 事件,并且可根据需要进行灵活控制。 二、串口通信动态链接库dll的编写 下面演示了如何用VC缩写串口通信dll过程。 1、从VC++ 6.0的File菜单中选择New命令,并在列表框中选择Win32 Dynamic-Link Library项,创建一个工程,如下图所示:
2、往工程中添加头文件 在新建一个com.h文件,里加入对外提供的函数接口,如要有5个,如下所示:
- //com.h
- #ifndef _COM_DLL_H
- #define _COM_DLL_H
- #ifdef MyComDll
- #else
- #define MyComDll extern "C" __declspec(dllimport)
- #endif
- MyComDll int FAR PASCAL ComOpen(int port);
- MyComDll int FAR PASCAL ComClose();
- MyComDll int FAR PASCAL SetCallback(void (CALLBACK* fun)(int port));
- MyComDll int FAR PASCAL GetComData(LPBYTE buf);
- MyComDll BOOL FAR PASCAL SendDataToCom(LPBYTE Cmd,int CmdLen);
- #endif
DLL的源代码模块需要包含该头文件,而且用户应用程序在使用此串口dll时也要包含com.h。另外,你会发现,MyComDll中包含了extern "C"链接指示符,这是因为在用C++编写动态链接库时,通常在经C++编译器编译后,其函数名称会改变,如ComOpen编译后,展现给调用者的名字是:_ComOpen@8这种形式,这样应用程序在调用时,链接程序就会提示找不到指定的函数。加上extern“C”后的作用就告诉编译器不要改变变量名或函数名。__declspec(dllimport)是告诉编译器,应用程序将从这个DLL 模块引入这些函数,__declspec(dllexport) 是告诉编译器这些函数是从产生的DLL模块输出给别的应用程序调用。 3、往工程中添加C/C++源代码文件 在C++源代码模块中,首先应包含如下头文件,及定义相关变量:
- #include <windows.h>
- #define MyComDll extern "C" __declspec(dllexport)
- #include "com.h"
然后实现本动态链接库的五个输出函数: (1)ComOpen(int port) 此函数接口功能是用来打开指定的串行通讯端口,参数port即为通讯口号(不用在前面加com了)。打开端口后,通过API函数GetCommState得到该端口的配置;根据需要更改其波特率、数据位、停止位等,以及设置触发信号事件的字符(即设置BCB的EvtChar字段);然后通过调用SetCommState设置端口。 串口打开成功后,将创建一个ComThreader线程,在ComThreader中,循环监控串行口是否收到有效数据,若收到则触发回调函数。 (2)GetComData (LPBYTE buf) 此函数是将串口接收缓冲区中的数据放到接收缓冲区buf中。 (3)SendDataToCom(LPBYTE Cmd,int CmdLen) 此函数是将指定长度的数据发送到串行口中。其长度由于变量CmdLen指定,发送的数据即为变量Cmd中的内容。发送数据时,需要将线程ComThreader暂时挂起,以避免与接收数据的线程冲突,产生紊乱。 (4)ComClose() 此函数用来关闭已打开的串口,无参数。通过事件触发以及WaitForSingleObject 、WaitForMultipleObjects函数,中断线程,关闭创建的各种事件、文件,释放相应资源,因为采用了多线程技术,因此需要特别注意主线程和子线程的相互同步。 (5)SetCallBack(int controlport,void (CALLBACK *outfunc)(int controlport)) 此函数的功能是设置回调函数,controlport为指定的端口,outfunc是外部应用程序传过来的函数指针,其主要目的是将应用程序的函数指针传给DLL中的一个指针函数,DLL在特定的时刻(本程序是当串行端口接收到有效数据时)通过内部的指针函数,调用外部的应用 程序,从而实现“回调”功能。
- //com.cpp
- void (CALLBACK* infunc) (int port);
- int FAR PASCAL SetCallBack(int controlport, void (CALLBACK*
- outfunc)(int controlport))
- {
- if(outfunc!=NULL)
- infunc=outfunc;
- return 1;
- }
4、往工程中添加模块定义文件 模块定义文件(module-definition)文件是以.def为扩展名的文本文件,为了能被其他开发工具如Visual Basic、Delphi等使用,创建的DLL文件必须要有模块定义文件,否则在应用程序调用ComOpen时会出现“Can’t find DLL entry point ComOpen in Comdll.dll”错误提示。Exports节和extern "C"的作用一样,告诉编译器不要改变输出的函数名。
- LIBRARY COMDLL
- DESCRIPTION ’COM Communication Demo’
- EXPORTS
- ComOpen @ 1
- ComClose @ 2
- SendDataToCom @ 3
- SetCallBack @ 4
- GetComData @ 5
四、动态链接库函数的VB 调用示范 1、VB测试程序 以下程序示范了在VB中如何调用由VC++编写的动态链接库中的函数。因为动态链接库中使用了回调函数,在VB代码中必须将回调函数放到标准的.BAS模块中,不可放在窗体模块中,也不能将其附加到类模块中。CALLBACK函数只是触发同一工程中一个窗体上的定时器控件,对串口数据进行采集,其定义如下:
- Sub CallBackFunc(ByVal port As Long) Form1.Timer1.Interval = 1
- Form1.Timer1.Enabled = True
- End Sub
在标准的.BAS模块中,还需定义该DLL函数的调用方式,具体如下:
- Option Explicit
- Public Declare Function ComOpen Lib "Comdll.dll" (ByVal
- port As Long) As Long
- Public Declare Function ComClose Lib "Comdll.dll" () As
- Long
- Public Declare Function SendDataToCom Lib "Comdll.dll"
- (ByRef Cmd As Byte, ByVal CmdLen As Long) As Long
- Public Declare Function SetCallBack Lib "Comdll.dll" (ByVal
- port As Long, ByVal func As Long) As Long
- Public Declare Function GetComData Lib "Comdll.dll" (ByRef
- buf As Byte) As Long
在窗体程序中,当打开串口时,调用DLL的SetCallBack函数设置回调函数,调用方式如下:
- SetCallBack (comport, AddressOf CallBackFunc);
关键字AddressOf是将CallBackFunc的函数地址传递给DLL中的指针函数void (CALLBACK* infunc) (int port)。 2、调试方法 串行通讯的调试相对来说是比较麻烦,在实践中,可以在同一台具有两个串行通讯口的机器上进行调试,只需要将两个串口的RXD和TXD交叉连接,并将5脚对等连接,就可以进行调试了;当然,也可用一个串口进行调试,只需将同一串口的2、3连接。 在调试过程中,需提醒读者注意的一点是:动态链接库与执行文件应在同一目录下,否则出现找不到动态链接库的问题;由于Windows操作系统本身的原因,在对动态链接库的第一次使用时,须将其拷贝至系统安装目录的system32子目录中才能避免上述问题。
用VC开发串口通信dll控件相关推荐
- 基于VC++开发串口通信的方法
串行通信中的关键是串行通信设备的初始化.数据的发送和接收及其实现方式. 在Dos环境下,用户可以直接对通信设备编程,可以通过查询中断的方式使用通信设备.但是Windows不提倡应用程序直接控制硬件,而 ...
- VC++利用微软mstscax.dll控件集成远程桌面
利用微软mstscax.dll控件集成远程桌面 1. 新建基于MFC的对话框程序,在对话框资源上右键,选择[Insert ActiveX Control...]菜单,然后在弹出的界面中选择" ...
- VC++开发学习三(对话框控件的绑定)
对话框的控件绑定不难,操作几遍就能掌握 对话框控件不同类型成员变量的绑定: 一个控件只能绑定控件类型和非控件类型,同时使用控件类型绑定时可以通过SetDlgItem进行设置控件的信息,GetDlgIt ...
- VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程
VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程 开篇语:最近在弄ocx控件发布到asp.net网站上使用,就是用户在使用过程中,自动下载安装ocx控件.(此文章也是 ...
- 串口通讯mscomm控件下载
串口通讯mscomm控件下载 大家知道,当我们安装VC++6.0/VB6.0时,如果选择了ACtiveX控件项(自定义安装),MSComm控件就会自动安装在计算机上了,并在系统文件夹下多了3个文件:M ...
- vc mscomm串口通信使用了CButtonST按钮类软件分析
使用了mscomm串口控件, 使用了CButtonST按钮类, 使用CDigitalClock类设置时间. 使用静态文本框实现了系统时间的显示控件,引入按钮文件BtnST.cpp,BtnST中使用了 ...
- SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题...
转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...
- C#开发学习——web服务器端控件
Asp.net在客户端开发和web开发所用到的控件还是有很大的差别的,而且Web开发的界面是在浏览器中显示的,所以控件的设计都和前边学习HTML设计有联系,没有客户端开发那么简单,不过我们可以通过专门 ...
- iOS开发UI篇—UITableview控件基本使用
iOS开发UI篇-UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) 1 #import <Foundation/Foundation.h&g ...
最新文章
- 打字游戏--飞机大战
- react native 中下拉列表FlatList组件的讲解以及实例demo
- JQuery获取下拉列表框选中项
- WPF快速指导5:验证
- 中海达ihand30手簿使用说明_如何使用RTK手簿求坐标转换参数(四参数/七参数)...
- 核心期刊 CA JST CSCD 含金量_期刊评介|《仪表技术与传感器》科技期刊的阿玛尼,只管投就对了!...
- java面试总结之一
- WC2019 自闭记
- UWP-HttpClient
- 操作系统(3) 多处理器编程:从入门到放弃
- MyBatis中一对多和多对一处理
- 国内的商业与开源 CMS
- 《剑指offer》66道算法题合集(java实现)
- 2018年计划Review,2019年计划Kick off | 掘金年度征文
- 腾讯 纸牌游戏 (排序)
- 高通平台开发系列讲解(外设篇)高通Camera用户层移植
- 算法 - 两数互质问题
- 计算机组成原理mips与arm,计算机组成原理之MIPS指令系统和MIPS体系结构
- 基于查表法的永磁同步电机MTPA-MTPV控制仿真模型,查表法,最大电流弱磁控制
- 【转】VMware 11.0 简体中文版|附永久密钥
热门文章
- yum mysql 启动失败_Linux下MySQL数据库yum升级后无法启动解决办法 | 系统运维
- mysql主键创建非聚集索引_什么是聚集索引,非聚集索引,索引覆盖,回表,索引下推...
- Requires: libstdc++.so.6(GLIBCXX_3.4.15)
- 面试题整理 1:将一个字符串转换为整数
- 神经网络-全连接层(1)
- Visio中插入mathtype公式,解决直线交叉弯曲的问题
- 跟我一起写 Makefile(三)
- eclipse导出jar包
- 【Machine Learning】OpenCV中的K-means聚类
- 校招面试必读 Tips