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个,如下所示:
  1. //com.h
  2. #ifndef _COM_DLL_H
  3. #define _COM_DLL_H
  4. #ifdef MyComDll
  5. #else
  6. #define MyComDll extern "C" __declspec(dllimport)
  7. #endif
  8. MyComDll int FAR PASCAL ComOpen(int port);
  9. MyComDll int FAR PASCAL ComClose();
  10. MyComDll int FAR PASCAL SetCallback(void (CALLBACK* fun)(int port));
  11. MyComDll int FAR PASCAL GetComData(LPBYTE buf);
  12. MyComDll BOOL FAR PASCAL SendDataToCom(LPBYTE Cmd,int CmdLen);
  13. #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++源代码模块中,首先应包含如下头文件,及定义相关变量:
  1. #include <windows.h>
  2. #define MyComDll extern "C" __declspec(dllexport)
  3. #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在特定的时刻(本程序是当串行端口接收到有效数据时)通过内部的指针函数,调用外部的应用
程序,从而实现“回调”功能。
  1. //com.cpp
  2. void (CALLBACK* infunc) (int port);
  3. int FAR PASCAL SetCallBack(int controlport, void (CALLBACK*
  4. outfunc)(int controlport))
  5. {
  6. if(outfunc!=NULL)
  7. infunc=outfunc;
  8. return 1;
  9. }
  4、往工程中添加模块定义文件  模块定义文件(module-definition)文件是以.def为扩展名的文本文件,为了能被其他开发工具如Visual Basic、Delphi等使用,创建的DLL文件必须要有模块定义文件,否则在应用程序调用ComOpen时会出现“Can’t find DLL entry point ComOpen in Comdll.dll”错误提示。Exports节和extern "C"的作用一样,告诉编译器不要改变输出的函数名。
  1. LIBRARY COMDLL
  2. DESCRIPTION ’COM Communication Demo’
  3. EXPORTS
  4. ComOpen @ 1
  5. ComClose @ 2
  6. SendDataToCom @ 3
  7. SetCallBack @ 4
  8. GetComData @ 5
  四、动态链接库函数的VB 调用示范  1、VB测试程序  以下程序示范了在VB中如何调用由VC++编写的动态链接库中的函数。因为动态链接库中使用了回调函数,在VB代码中必须将回调函数放到标准的.BAS模块中,不可放在窗体模块中,也不能将其附加到类模块中。CALLBACK函数只是触发同一工程中一个窗体上的定时器控件,对串口数据进行采集,其定义如下:
  1. Sub CallBackFunc(ByVal port As Long) Form1.Timer1.Interval = 1
  2. Form1.Timer1.Enabled = True
  3. End Sub
  在标准的.BAS模块中,还需定义该DLL函数的调用方式,具体如下:
  1. Option Explicit
  2. Public Declare Function ComOpen Lib "Comdll.dll" (ByVal
  3. port As Long) As Long
  4. Public Declare Function ComClose Lib "Comdll.dll" () As
  5. Long
  6. Public Declare Function SendDataToCom Lib "Comdll.dll"
  7. (ByRef Cmd As Byte, ByVal CmdLen As Long) As Long
  8. Public Declare Function SetCallBack Lib "Comdll.dll" (ByVal
  9. port As Long, ByVal func As Long) As Long
  10. Public Declare Function GetComData Lib "Comdll.dll" (ByRef
  11. buf As Byte) As Long
  在窗体程序中,当打开串口时,调用DLL的SetCallBack函数设置回调函数,调用方式如下:
  1. SetCallBack (comport, AddressOf CallBackFunc);
  关键字AddressOf是将CallBackFunc的函数地址传递给DLL中的指针函数void (CALLBACK* infunc) (int port)。  2、调试方法  串行通讯的调试相对来说是比较麻烦,在实践中,可以在同一台具有两个串行通讯口的机器上进行调试,只需要将两个串口的RXD和TXD交叉连接,并将5脚对等连接,就可以进行调试了;当然,也可用一个串口进行调试,只需将同一串口的2、3连接。  在调试过程中,需提醒读者注意的一点是:动态链接库与执行文件应在同一目录下,否则出现找不到动态链接库的问题;由于Windows操作系统本身的原因,在对动态链接库的第一次使用时,须将其拷贝至系统安装目录的system32子目录中才能避免上述问题。

用VC开发串口通信dll控件相关推荐

  1. 基于VC++开发串口通信的方法

    串行通信中的关键是串行通信设备的初始化.数据的发送和接收及其实现方式. 在Dos环境下,用户可以直接对通信设备编程,可以通过查询中断的方式使用通信设备.但是Windows不提倡应用程序直接控制硬件,而 ...

  2. VC++利用微软mstscax.dll控件集成远程桌面

    利用微软mstscax.dll控件集成远程桌面 1. 新建基于MFC的对话框程序,在对话框资源上右键,选择[Insert ActiveX Control...]菜单,然后在弹出的界面中选择" ...

  3. VC++开发学习三(对话框控件的绑定)

    对话框的控件绑定不难,操作几遍就能掌握 对话框控件不同类型成员变量的绑定: 一个控件只能绑定控件类型和非控件类型,同时使用控件类型绑定时可以通过SetDlgItem进行设置控件的信息,GetDlgIt ...

  4. VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程

    VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程 开篇语:最近在弄ocx控件发布到asp.net网站上使用,就是用户在使用过程中,自动下载安装ocx控件.(此文章也是 ...

  5. 串口通讯mscomm控件下载

    串口通讯mscomm控件下载 大家知道,当我们安装VC++6.0/VB6.0时,如果选择了ACtiveX控件项(自定义安装),MSComm控件就会自动安装在计算机上了,并在系统文件夹下多了3个文件:M ...

  6. vc mscomm串口通信使用了CButtonST按钮类软件分析

    使用了mscomm串口控件, 使用了CButtonST按钮类, 使用CDigitalClock类设置时间. 使用静态文本框实现了系统时间的显示控件,引入按钮文件BtnST.cpp,BtnST中使用了  ...

  7. SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题...

    转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...

  8. C#开发学习——web服务器端控件

    Asp.net在客户端开发和web开发所用到的控件还是有很大的差别的,而且Web开发的界面是在浏览器中显示的,所以控件的设计都和前边学习HTML设计有联系,没有客户端开发那么简单,不过我们可以通过专门 ...

  9. iOS开发UI篇—UITableview控件基本使用

    iOS开发UI篇-UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) 1 #import <Foundation/Foundation.h&g ...

最新文章

  1. 打字游戏--飞机大战
  2. react native 中下拉列表FlatList组件的讲解以及实例demo
  3. JQuery获取下拉列表框选中项
  4. WPF快速指导5:验证
  5. 中海达ihand30手簿使用说明_如何使用RTK手簿求坐标转换参数(四参数/七参数)...
  6. 核心期刊 CA JST CSCD 含金量_期刊评介|《仪表技术与传感器》科技期刊的阿玛尼,只管投就对了!...
  7. java面试总结之一
  8. WC2019 自闭记
  9. UWP-HttpClient
  10. 操作系统(3) 多处理器编程:从入门到放弃
  11. MyBatis中一对多和多对一处理
  12. 国内的商业与开源 CMS
  13. 《剑指offer》66道算法题合集(java实现)
  14. 2018年计划Review,2019年计划Kick off | 掘金年度征文
  15. 腾讯 纸牌游戏 (排序)
  16. 高通平台开发系列讲解(外设篇)高通Camera用户层移植
  17. 算法 - 两数互质问题
  18. 计算机组成原理mips与arm,计算机组成原理之MIPS指令系统和MIPS体系结构
  19. 基于查表法的永磁同步电机MTPA-MTPV控制仿真模型,查表法,最大电流弱磁控制
  20. 【转】VMware 11.0 简体中文版|附永久密钥

热门文章

  1. yum mysql 启动失败_Linux下MySQL数据库yum升级后无法启动解决办法 | 系统运维
  2. mysql主键创建非聚集索引_什么是聚集索引,非聚集索引,索引覆盖,回表,索引下推...
  3. Requires: libstdc++.so.6(GLIBCXX_3.4.15)
  4. 面试题整理 1:将一个字符串转换为整数
  5. 神经网络-全连接层(1)
  6. Visio中插入mathtype公式,解决直线交叉弯曲的问题
  7. 跟我一起写 Makefile(三)
  8. eclipse导出jar包
  9. 【Machine Learning】OpenCV中的K-means聚类
  10. 校招面试必读 Tips