vc 串口通讯
visual c++串口通信与工程应用实践
visual c++串口通信与工程应用实践Visual C++是一款强大的集成开发环境,可以用于开发串口通信和工程应用。
它提供了一套丰富的工具和函数库,可以方便地进行串口通信和工程应用的开发。
需要掌握相关的编程技巧和串口通信协议知识,才能更好地实践和应用。
下面是一些实践的步骤:1. 配置串口:在Visual C++中,可以使用WinAPI函数SetCommState和GetCommState来配置串口的波特率、数据位、停止位等参数。
需要定义一个DCB结构体来保存串口的配置信息,然后使用GetCommState获取当前串口的配置信息,修改对应的参数,最后使用SetCommState来设置新的配置。
2. 打开串口:使用WinAPI函数CreateFile来打开串口。
需要提供串口的名称(如"COM1")、访问权限和共享模式等参数。
打开成功后,会返回一个句柄,可以用于后续的读写操作。
3. 读取串口数据:使用ReadFile函数从串口中读取数据。
可以设置一个缓冲区来保存读取的数据,并指定读取的字节数。
ReadFile函数会阻塞,直到有足够的数据可供读取。
4. 写入串口数据:使用WriteFile函数将数据写入串口。
可以将要发送的数据保存到一个缓冲区,然后指定要发送的字节数。
WriteFile函数会阻塞,直到所有数据都被发送。
5. 关闭串口:使用CloseHandle函数关闭串口句柄。
以上是串口通信的基本步骤,可以根据具体的应用需求和功能进行扩展。
在工程应用中,可以根据串口通信的需求来设计和开发相应的功能模块,例如数据采集、控制命令发送等。
可以使用Visual C++的其他功能,如图形界面设计和多线程编程,来增强应用的用户体验和性能。
基于VC++串口通信
图 1
图 2
1 S 2 2的标 准 .R 一 3 2
R 一 3C标准 的全称是 E A R 一 3 C标 S 22 I— S 22 单击它 , 它通过 R 一 3 串口 S 22 线传人无线电 号 准, 它是在 16 年 由 国电子工业协会、 99 美 贝尔系 信端 口 ; 设 备 十 六 进 制 控 制 信 号 0 H ( 进 制 形 式 4 二 统和调制解调器厂家及计算机终端生产厂家共同 注意 :必须在打开端 口之前设置 C mm ot 0 0 0 0)而后无线电设备通过发射器向电机发 o Pr o o 10, 制定的用于串 行通信的标准。 它的全名是“ 数据终 属性 送启动和关闭控制信号, 它的作用是启动和关闭 2 2 Stns 2 eig 属性是功能设置并 返回波特 电机。电机的接收 t 端设备( T ) D E 和数据通信设备∞c ) E 之间串行二进 奇偶校验、 数据位 、 停止位参数 ; 制数据交换接口技术标准”应用 9 O 芯的 R 一 3C 率、 S22 信号,控制电机转动和转速从而使模拟人质靶移 近距离传送。 芯的 R - 3 C 9 S 2 2 的特性如下: 2 3 I u属性是功能从接收缓冲区内读取 动 , 2 Pt 2 n 来使模拟 ^ 质靶充当模拟绑匪的挡箭牌的逼 1 .主要信号线定义 21 数据 ; 真画面。再通过摄像头采集人物状态及中 的位 枪 2 . O tu屙 l是功能向发送缓冲区写数 置 , 2 u t 生 4 P 引脚 1数据载波检测 D D  ̄ 脚 2发送数 : C ;I : 然后通过视频采集卡传人计算机进行算法比 或返回 发送缓冲区当前的数据 ; 据 R D 引脚 3接收数据 T D 引脚 4 数据终端 据 , X ; : X ; : 较, 得出测试结果女1 2 1 。 图 就绪 D R  ̄脚 5信号地 S ; I 6数据设备就 T ;I : G  ̄脚 : 2 _ P r p n属性是功能用于打开或关闭 . ot e 2 5 O 参考文献 绪 D R  ̄脚 7请求发送 R s引脚 8清除发送 串口 , S ;I : T; : 的 或返回串口 的开 、 关状态 。 『 张 自强. 1 1 基于 VC MS cmm控件 的串行通信 H_ C o C S  ̄脚 9振铃指示 R 。 T ;I : I 3 串口 通信应用 [ 河南科技大学学报 , 0 ( 1 J 1 . 2 40 ) 0 . 串口 通信应用——射击训练系统 1 2电气特性 . 2 [秋育 2 1 桥基 于 M C m S o m的 P 机与单片机串行通 c E A R 一 3C对电器特性 、 I — S 22 逻辑电平和各 射击洲练系统的原理示意图如图 1 。 信程序设计 科技信息,0 9 20. 种信号线功能都有规定。 通过射击 练系统的 V 界面图上的运动档 『 志 ̄.S o m控件在 V + 6 训 C 斟岳 M Cm c + D串口 通信 中的 & T D和 R D上 : 在 x x 逻辑 1MA K= 3 位的 A ,D四个按钮控制电机转动及转速 , 中 应用 长春工程学院学报, 0 (1. ( R )一 V~ ,C B, 其 2 9 ) 0 0 按钮 C的代码如下 : 1V , 5 逻辑 0 P C )+ ~+1V; ( A E= 3 S 5 【崔艳华模 拟射击训练 系统的设计与实 4 1 现 微机 l R sc ' D R D R和 D D等控制线 T 、r 、S 、T 在 I s C vi S o n etl.n utn 0 o C C r T s  ̄O B t C d m D ' o 发 展 ,0 30 ) 20 (4 . 上: 信号有效 ( 接通 ,N状态 , O 正电压 ) 3 =+ V~ { 阁 徐进RS4 2 8 _2/ 5串行通信在控制 系统 中的应 4 / /TODo Ad o rc nrln t — 用 山东 d y u o t oi o i f + 5 ,信号无效 ( IV 断开 ,F 状态 ,负电压 ) OF 建筑工程学院学报 , O () 2 l 0 4
VC6.0MFC串口通信编写全过程
其于MFC的串口调试助手编辑过程一、新建打开VC6.0 文件新建工程MFC AppWiard(exe) 位置(选择保存工程位置)工程名称(输入工程名XXXX)确定选择基本对话框下一步下一步下一步选择(CXXXXDlg)完成确定在生成的基本对话框内将不需要按钮及提示框(自动生成的“确定”“取消”及提示框)删除或修改使用,至此基本框架完成如下图:二、往生成的基本框架中添加控件1、因为控件列表框内没有串口通信用到的通信控件,所以要先添加到控件列表框内再将控件添加到基本框内使用,步骤如下:菜单栏工程添加到工程Components and controls…Registered ActiveX Controls 选择“Microsoft Communications Control, version 6.0”Insert 确定OK 关闭此子窗口完成添加操作标志如上图所示。
2、将刚才添加添加到控件列表框内的串口控件添加到基本框架内点击控件列表框内的串口控件,此时光标变为“十”形,在基本框架内随意划取一矩形区域,即可以添加串口控件,不需要修改此控件的大小及位置,因为程编译运行后此控件是看不到的,步骤结果如下图:此控件(标志)是下面步骤添加进来的串口控件基本框架3、继续往基本框架内添加用于编辑发送数据的输入编辑框及输出编辑框,同理选择控件列表框内的“编辑框控件”,以相同的操作即可添加两个编辑窗口及一个按纽控件如下图所示:选择其中任意一个作为输入编辑框及输出编辑框这两个窗口需要修改大小及位置,因为程序运行后将会显示而串口通信控件则不显示,上图是运行后的效果。
4、对以上四个控件编程步骤如下:a、右击串口通信控件建立类向导Member variables Control IDS中选择IDC_MSCOMM1 add variable…Member variable name中输入控件变量名m_ctrlComm(变量名可以随意选取,但程序中应与所取变量名一致)OK 确定b、右击编辑框、属性、常规、ID:中输入ID号,此编辑框用于接收显示数据的其ID 号为IDC_EDIT_RXDATA(可以随意选取,但程序中应与所取ID号一致),再在此窗口的样式中勾选”多行”,同时将“自动水平滚动(T)”勾选去掉,再勾选“垂直滚动(V)”,此勾选操作是用于垂直多行显示的,按回车后即可输入;同理右击另一编辑框输入ID号为IDC_EDIT_TXDATA此编辑框用于编辑发送数据的,同样也选上用于垂直多行显示,发送框可以不用垂直多行显示;再为按钮控件添加ID号,为IDC_BUTTON_MANUALSEND,并将标题中的“Button1”改为“发送”,功能是按一次就把发送编辑框中的内容发送一次。
VC++串口通信编程
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信。
串口通信方便易行,应用广泛。
一般情况下,工控机和各智能仪表通过RS485总线进行通信。
RS485的通信方式是半双工的,只能由作为主节点的工控PC机依次轮询网络上的各智能控制单元子节点。
每次通信都是由PC机通过串口向智能控制单元发布命令,智能控制单元在接收到正确的命令后作出应答。
在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但欠灵活。
其二是调用Windows的API函数,这种方法可以清楚地掌握串口通信的机制,并且自由灵活。
本文我们只介绍API串口通信部分。
串口的操作可以有两种操作方式:同步操作方式和重叠操作方式(又称为异步操作方式)。
同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而重叠操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。
无论那种操作方式,一般都通过四个步骤来完成:(1)打开串口(2)配置串口(3)读写串口(4)关闭串口(1)打开串口Win32系统把文件的概念进行了扩展。
无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台,都是用API函数CreateFile来打开或创建的。
该函数的原型为:HANDLE CreateFile( LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDistribution,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);•lpFileName:将要打开的串口逻辑名,如“COM1”;•dwDesiredAccess:指定串口访问的类型,可以是读取、写入或二者并列;•dwShareMode:指定共享属性,由于串口不能共享,该参数必须置为0;•lpSecurityAttributes:引用安全性属性结构,缺省值为NULL;•dwCreationDistribution:创建标志,对串口操作该参数必须置为OPEN_EXISTING;•dwFlagsAndAttributes:属性描述,用于指定该串口是否进行异步操作,该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作;•hTemplateFile:对串口而言该参数必须置为NULL;同步I/O方式打开串口的示例代码:HANDLE hCom; //全局变量,串口句柄hCom=CreateFile("COM1",//COM1口GENERIC_READ|GENERIC_WRITE, //允许读和写0, //独占方式NULL,OPEN_EXISTING, //打开而不是创建0, //同步方式NULL);if(hCom==(HANDLE)-1){AfxMessageBox("打开COM失败!");return FALSE;}return TRUE;重叠I/O打开串口的示例代码:HANDLE hCom; //全局变量,串口句柄hCom =CreateFile("COM1", //COM1口GENERIC_READ|GENERIC_WRITE, //允许读和写0, //独占方式NULL,OPEN_EXISTING, //打开而不是创建FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式NULL);if(hCom ==INVALID_HANDLE_VALUE){AfxMessageBox("打开COM失败!");return FALSE;}return TRUE;(2)、配置串口在打开通讯设备句柄后,常常需要对串口进行一些初始化配置工作。
基于VC++6.0实现的串口通讯
基于VC++6.0实现的串口通讯摘要:串口通讯作为一种灵活、方便、可靠的通讯方式,广泛应用于计算机与其它设备之间的通讯以及工业控制系统中,是计算机与外部设备进行数据通讯时经常使用的方式之一。
本文介绍了VC++6.0环境下利用MSComm控件实现计算机与外部设备之间的串口通讯。
关键词:串口通讯VC++6.0MSComm一、引言串口作为计算机标准配置中的对外接口,由于其简便、易行及数据传输可靠等优点,使其成为计算机与外部设备之间通讯的主要手段之一,广泛应用于工业控制系统中。
VC++6.0作为面向对象的可视化开发工具,具有良好的界面设计能力,利用具有良好运行效率和稳定性的MSComm控件,可以简单方便的实现串口通讯功能。
二、MSComm控件介绍VC++6.0是基于Windows操作系统的主流编程可视化语言。
应用VC++6.0开发串行通讯通常有如下几种方法:1.利用Windows API通讯函数。
2.利用VC的标准通讯函数_inp,_inpw,_inpd,_outp,_outpw,_outpd等直接对串口进行操作。
3.使用Microsoft Visual C++的通讯控件(MSComm)。
以上几种方法中,前两种由于使用时需要的专业程度比较高,需要了解内部接口及标准通讯函数的定义,因此比较困难;第三种方法较简单,对使用者要求不高,只需对串口进行简单配置即可。
Microsoft Communications Control(以下简称MSComm)是Microsoft公司基于组件对象模型(COM)开发的简化Windows下串口通讯编程的ActiveX控件,它为应用程序提供了通过串口接口收发数据的简便方法。
该控件屏蔽了通讯过程中的底层操作,用户只需通过设置并监视其属性和事件,即可完成串口编程,实现与被控制对象的串行通讯、数据交换,并监视或响应在通讯过程中可能发生的各种错误和事件。
具体有两种处理方法:一是事件驱动(Event-Driven)。
如何实现VC应用程序与PLC的数据交换
如何实现VC应用程序与PLC的数据交换当今,随着工业自动化的广泛应用,越来越多的工业企业开始采用可编程逻辑控制器(PLC)来控制和管理生产过程。
而随着信息技术的不断发展,将计算机技术与工业控制相结合,实现VC应用程序与PLC的数据交换,已经成为很多企业提高生产效率、提升产品质量的一种重要手段。
本文将从硬件和软件两个角度来介绍如何实现VC应用程序与PLC的数据交换。
硬件层面:在实现VC应用程序与PLC的数据交换之前,首先需要确保计算机和PLC之间能够进行可靠的通信。
一般而言,可以通过以下几种方式来实现计算机和PLC之间的连接和通信。
1.串口通信:串口通信是最常见的一种方式,通过串口线将计算机的串口与PLC的COM口相连接。
在VC应用程序中,通过编程方式来读写串口数据,从而实现与PLC的数据交互。
2.以太网通信:在以太网通信方式下,计算机和PLC通过以太网进行连接。
可以使用TCP/IP协议来实现数据的传输。
在VC应用程序中,可以使用套接字编程来实现与PLC的通信。
B通信:有些PLC具备USB接口,可以通过USB线将计算机和PLC进行连接。
在VC应用程序中,可以通过USB编程来与PLC进行数据交互。
软件层面:在硬件连接完成之后,下一步就是通过软件来实现VC应用程序与PLC的数据交换。
以下是一些常用的软件开发工具和编程语言,可以帮助我们实现这个目标。
1.Visual Studio:Visual Studio是一个功能强大的集成开发环境,可以用于开发各种类型的应用程序,包括VC应用程序。
在VC应用程序中,可以通过编写相应的代码来与PLC进行数据交换。
2.C#编程语言:C#是一种简单、现代化的编程语言,广泛应用于Windows平台的应用程序开发。
在VC应用程序中,可以使用C#编写代码来实现与PLC的数据交互。
3.编程库:PLC通常配备有相关的编程库,包括DLL、API等,可以用于编写与PLC通信的代码。
在VC应用程序中,可以引用这些编程库,从而实现与PLC的数据交换。
VC++中串行通信程序设计
O 引言
在很多情况下 , 远程监控和 自动化领域系统常见的通信
控件 的 C mmE et o vn 属性 以检查执行结果或者检查某 一事件 是否发 生。如果应用 程序较 小 , 并且 是 自成 一体 , 这种 方法
可 能是 更 可取 的 。
编程多为 串口通信 编程 。计算 机 串口编程在通信 软件 中有
C mmP r o ot
设 置 / 取控 件 对 应 的 串 行 口 获
S ti s et g n Pr e ot n Op Ipt nu
Oup t tu
设置/ 取波特率、 获 校验方式 、 数据位 、 停止位 打开/ 关闭通信 口 读取 数 据
发 送种 是利 用 Mioot 司提供 c sf 公 r 的 AcvX控 件 Mi ootC mmu i t n o t l te i c sf o r nc i sC nr 。本 文将 ao o 主要介绍第二种方法 。
话框的 MF C应用程序项 目, 命名为 my O 记住在设置 项 C m,
目选 项 时 必 须 选 上 Aci X C nrl 其 他 的 按 照 缺 省 设 置 。 t e ot s v o,
它的核心 内容是组 件对象 模型 C OM( m o e tO j t o C p nn be c Moa 。A t e d ) ci X控件包 括一 系列 的属性 、 法和事件 , 用 1 v 方 使
问串口, 一种是 利 用 Mioot 司提供 的 A t e c sf公 r ci X控件 Mi oot o v c sf C mmu i tn nrl r nc i s a o C t 编写 串行通 信程序 的方 o o
法, 并给 出了例 程 , 具有一定 的实用意义 。
VC 串口编程基础之如何用 VC 打开串口和关闭串口
VC 串口编程基础之如何用VC 打开串口和关闭串口在对串口进行操作之前都需要先打开串口,VC 串口编程方法分为利用VC 串口控件(或VC 串口类)和直接调用Windows底层API函数(我称之为VC API 串口编程)两种方法,不管哪种方法,其实质都是利用底层API函数对串口进行操作,这里我们来看怎么利用API函数来用VC 打开串口。
在Windows 32位以上操作系统(Win98以上)中,将串口(包括其它通信设备)作为文件来处理,所以串口的打开、读写和关闭所用API函数与文件操作函数一样。
所以打开串口用CreateFile,读串口用ReadFile,写串口用WriteFile,关闭串口用CloseHandle。
一、用VC 打开串口、关闭串口的API函数1、打开串口用CreateFile,其声明如下:1HANDLE CreateFile(2LPCTSTR lpFileName, // file name3DWORD dwDesiredAccess, // access mode4DWORD dwShareMode, // sha re mode5LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD6DWORD dwCreationDisposition, // how to create7DWORD dwFlagsAndAttributes, // file attributes8HANDLE hTemplateFile // handle to template file9);部分参数解释如下:●lpFileNam e:指定要打开的串口逻辑名,用字符串表示,如“COM1”和“COM2”分别表示串口1和串口2,若要知道您的电脑有哪此串口,可以打开设备管理器查看,如下图所示,或用丁丁串口调试助手,这个工具启动后会枚举系统当前存在的串口。
●dwDesiredAccess:访问类型,有读(dwDesiredAccess=GENERIC_READ)、写(dwDesiredAccess=GENERIC_WRITE)或两者兼有((dwDesiredAccess=GENERIC_READ | GENERIC_WRITE)。
VC串口通讯实例
在VC++中有两种方法可以进行串口通讯。
一种是利用Microsoft公司提供的ActiveX 控件Microsoft Communications Control。
另一种是直接用VC++访问串口。
下面将简述这两种方法。
一、Microsoft Communications ControlMicrosoft公司在WINDOWS中提供了一个串口通讯控件,用它,我们可以很简单的利用串口进行通讯。
在使用它之前,应将控件加在应用程序的对话框上。
然后再用ClassWizard 生成相应的对象。
现在我们可以使用它了。
该控件有很多自己的属性,你可以通过它的属性窗口来设置,也可以用程序设置。
我推荐用程序设置,这样更灵活。
SetCommPort:指定使用的串口。
GetCommPort:得到当前使用的串口。
SetSettings:指定串口的参数。
一般设为默认参数"9600,N,8,1"。
这样方便与其他串口进行通讯。
GetSettings:取得串口参数。
SetPortOpen:打开或关闭串口,当一个程序打开串口时,另外的程序将无法使用该串口。
GetPortOpen:取得串口状态。
GetInBufferCount:输入缓冲区中接受到的字符数。
SetInPutLen:一次读取输入缓冲区的字符数。
设置为0时,程序将读取缓冲区的全部字符。
GetInPut:读取输入缓冲区。
GetOutBufferCount:输出缓冲区中待发送的字符数。
SetOutPut:写入输出缓冲区。
一般而言,使用上述函数和属性就可以进行串口通讯了。
以下是一个范例。
#define MESSAGELENGTH 100class CMyDialog : public CDialog{protected:VARIANT InBuffer;VARIANT OutBuffer;CMSComm m_Com;public:......}BOOL CMyDiaLog::OnInitDialog(){CDialog::OnInitDialog();m_Com.SetCommPort(1);if (!m_Com.GetPortOpen()) {m_Com.SetSettings("57600,N,8,1");m_Com.SetPortOpen(true);m_Com.SetInBufferCount(0);SetTimer(1,10,NULL);InBuffer.bstrVal=new unsigned short[MESSAGELENGTH]; OutBuffer.bstrVal=new unsigned short[MESSAGELENGTH]; OutBuffer.vt=VT_BSTR;}return true;}void CMyDiaLog::OnTimer(UINT nIDEvent){if (m_Com.GetInBufferCount()>=MESSAGELENGTH) { InBuffer=m_Com.GetInput();// handle the InBuffer.// Fill the OutBuffer.m_Com.SetOutput(OutBuffer);}CDialog::OnTimer(nIDEvent);}用该控件传输的数据是UNICODE格式。
vc++_串口上位机编程实例 附vc串口通信(接收)
VC++串口上位机简单例程(源码及详细步骤)VC++编写简单串口上位机程序串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享一下,体验一下单片机和PC通信的乐趣。
编译环境:VC++6.0操作系统:VMWare虚拟出来的Windows XP程序实现功能:1、PC初始化COM1口,使用n81方式,波特率57600与单片机通信。
PC的COM口编号可以通过如下方式修改:当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。
COM1口可用的话,会提示串口初始化完毕。
否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。
2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC 转换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。
(见文章末尾图)3、为防止串口被一只占用,点击关闭串口可以关闭COM1,供其它程序使用,点击后按钮变为打开串口,点击可重新打开COM1。
程序的编写:1、打开VC++6.0建立基于对话框的MFC应用程序Test,2、在项目中插入MSComm控件:工程->增加到工程->Components and Controls->双击Registered ActiveX Controls->选择Microsoft Communications Control, version 6.0->Insert,按默认值添加,你会发现多了个电话图标,这是增加后串口通信控件。
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_READ GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL FILE_FLAG_OVERLAPPED, //重叠I/ONULL);将提示错误,这样就OK:_com_handle = CreateFile(“\\\\.\\COM10“,//对应的就是\\.\COM10GENERIC_READ GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL FILE_FLAG_OVERLAPPED, //重叠I/ONULL);线程中循环的低效率问题使用SetCommMask(pcom->_com_handle, EV_RXCHAR EV_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_ERRClearCommError(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<typename T>_asyn_com& operator << (T x){strstream s;s << x ;write(s.str(), s.pcount());return *this;}就可以这样使用_sync_com com1;com1.open(1, 9600);com1 << “ then random() 's return value is “<< rand() << “ .\n“ ;com1.close();本串口类库的主要接口class _base_com{bool open(int port);bool open(int port, int baud_rate);bool open(int port, char * set_str); // set_str : “9600, 8, n, 1“bool set_state(int BaudRate, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT)//设置内置结构串口参数:波特率,停止位bool set_state(char *set_str)bool is_open();HANDLE get_handle();virtual bool open_port()=0; //继承用的重要函数virtual close();}class _sync_com :public _base_com //同步{int read(char *buf, int buf_size); //自动补上'\0',将用去一个字符的缓冲区int write(char *buf, int len);int write(char *buf);}class _asyn_com :public _base_com //异步{int read(char *buf, int buf_size); //自动补上'\0',将用去一个字符的缓冲区int write(char *buf, int len);int write(char *buf);}class _thread_com :public _asyn_com //线程{virtual void on_receive() //供线程接受到字符时调用,可继承替换之{if(_notify_hwnd)PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0));else{if(_func)_func(_port);}}void set_hwnd(HWND hwnd); //设置窗口句柄,发送ON_COM_RECEIVE WM_USER + 618void set_func(void (*f)(int)); //设置调用函数,窗口句柄优先void set_notify_num(int num); //设定发送通知, 接受字符最小值}一些应用范例当然首先#include "_com.h"一、打开串口1同步写char str[] = "com_class test";_sync_com com1; //同步com1.open(1); // 相当于com1.open(1, 9600); com1.open(1, "9600,8,n,1");for(int i=0; i<100; i++){Sleep(500);com1.write(str); //也可以com1.write(str, strlen(str));}com1.close();二、打开串口2异步读char str[100];_asyn_com com2; //异步com2.open(2); // 相当于com2.open(2, 9600); com2.open(2, "9600,8,n,1");if(!com2.is_open())cout << "COM2 not open , error : " << GetLastError() << endl;也可以如下用法if(!com2.open(2))cout << "COM2 not open , error : " << GetLastError() << endl; */for(int i=0; i<100; i++){Sleep(500);if(com2.read(str, 100) > 0) //异步读,返回读取字符数cout << str;}com2.close();三、扩展应用具有监视线程的串口类class _com_ex : public thread_com{public:virtual on_receive(){char str[100];if(read(str, 100) > 0) //异步读,返回读取字符数cout << str;}int main(int argc, char *argv[]){try{char str[100];_com_ex com2; //异步扩展com2.open(2);Sleep(10000);com2.close();}catch(exception &e){cout << e.what() << endl;}return 0;}四、桌面应用可发送消息到指定窗口(在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_MAPON_MESSAGE(ON_COM_RECEIVE, On_Receive)END_MESSAGE_MAP()打开串口,传递窗口句柄_thread_com com2;com2.open(2);com2.set_hwnd(ComDlg->m_hWnd);处理消息LRESULT ComDlg::On_Receive(WPARAM wp, LPARAM lp) {char str[100];com2.read(str, 100);char com_str[10];strcpy(com_str, "COM");ltoa((long)wp, com_str + 3, 10); // WPARAM 保存端口号MessageBox(str, com_str, MB_OK);return 0;}C++ Builderclass TForm1 : public TForm{__published: // IDE-managed Componentsvoid __fastcall FormClose(TObject *Sender, TCloseAction &Action); void __fastcall FormCreate(TObject *Sender);private: // User declarationspublic: // User declarationsvoid On_Receive(TMessage& Message);__fastcall TForm1(TComponent* Owner);_thread_com com2;BEGIN_MESSAGE_MAPMESSAGE_HANDLER(ON_COM_RECEIVE, TMessage, On_Receive) END_MESSAGE_MAP(TForm)};void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action){com2.close();}//---------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender){com2.open(2);com2.set_hwnd(Handle);}//---------------------------------------------------------------------------void TForm1::On_Receive(TMessage& Message){char xx[20];int port = Message.WParam;if(com2.read(xx, 20) > 0)ShowMessage(xx);}错误和缺陷在所难免,欢迎来信批评指正;wushaojian@ 附完整源代码_com.h/*串口基础类库(WIN32)ver 0.1编译器:BC++ 5; C++ BUILDER 4, 5, 6, X; VC++ 5, 6; ; 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.8 llbird wushaojian@*//*Example :*/#ifndef _COM_H_#define _COM_H_#pragma warning(disable: 4530)#pragma warning(disable: 4786)#pragma warning(disable: 4800)#include <cassert>#include <strstream>#include <algorithm>#include <exception>#include <iomanip>using namespace std;#include <windows.h>class _base_com //虚基类基本串口接口{protected:volatile int _port; //串口号volatile HANDLE _com_handle;//串口句柄char _com_str[20];DCB _dcb; //波特率,停止位,等COMMTIMEOUTS _co; // 超时时间virtual bool open_port() = 0;void init() //初始化{memset(_com_str, 0, 20);memset(&_co, 0, sizeof(_co));memset(&_dcb, 0, sizeof(_dcb));_dcb.DCBlength = sizeof(_dcb);_com_handle = INVALID_HANDLE_VALUE; }virtual bool setup_port(){if(!is_open())return false;if(!SetupComm(_com_handle, 8192, 8192))return false; //设置推荐缓冲区if(!GetCommTimeouts(_com_handle, &_co))return false;_co.ReadIntervalTimeout = 0xFFFFFFFF;_co.ReadTotalTimeoutMultiplier = 0;_co.ReadTotalTimeoutConstant = 0;_co.WriteTotalTimeoutMultiplier = 0;_co.WriteTotalTimeoutConstant = 2000;if(!SetCommTimeouts(_com_handle, &_co))return false; //设置超时时间if(!PurgeComm(_com_handle, PURGE_TXABORT PURGE_RXABORT PURGE_TXCLEAR PURGE_RXCLEAR ))return false; //清空串口缓冲区return true;}inline void set_com_port(int port){char p[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"bool set_state(char *set_str){if(is_open()){if(!GetCommState(_com_handle, &_dcb))return false;if(!BuildCommDCB(set_str, &_dcb))return false;return SetCommState(_com_handle, &_dcb) == TRUE;}return false;}//设置内置结构串口参数:波特率,停止位bool set_state(int BaudRate, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT){if(is_open()){if(!GetCommState(_com_handle, &_dcb))return false;_dcb.BaudRate = BaudRate;_dcb.ByteSize = ByteSize;_dcb.Parity = Parity;_dcb.StopBits = StopBits;return SetCommState(_com_handle, &_dcb) == TRUE;}return false;}//打开串口缺省9600, 8, n, 1inline bool open(int port){return open(port, 9600);}//打开串口缺省baud_rate, 8, n, 1 inline bool open(int port, int baud_rate) {if(port < 1 port > 1024)return false;set_com_port(port);if(!open_port())return false;if(!setup_port())return false;return set_state(baud_rate);}//打开串口inline bool open(int port, char *set_str) {if(port < 1 port > 1024)return false;set_com_port(port);if(!open_port())return false;if(!setup_port())return false;return set_state(set_str);}inline bool set_buf(int in, int out){return is_open() ? SetupComm(_com_handle, in, out) : false; }//关闭串口inline virtual void close(){if(is_open()){CloseHandle(_com_handle);_com_handle = INVALID_HANDLE_VALUE;}}//判断串口是或打开inline bool is_open(){return _com_handle != INVALID_HANDLE_VALUE; }//获得串口句炳HANDLE get_handle(){return _com_handle;}operator HANDLE(){return _com_handle;}};class _sync_com : public _base_com{protected://打开串口virtual bool open_port(){if(is_open())close();_com_handle = CreateFile(_com_str,GENERIC_READ GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL ,NULL);assert(is_open());return is_open();//检测串口是否成功打开}public:_sync_com(){}//同步读int read(char *buf, int buf_len){if(!is_open())return 0;buf[0] = '\0';COMSTAT stat;DWORD error;if(ClearCommError(_com_handle, &error, &stat) && error > 0) //清除错误{PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除输入缓冲区*/return 0;}unsigned long r_len = 0;buf_len = min(buf_len - 1, (int)stat.cbInQue);if(!ReadFile(_com_handle, buf, buf_len, &r_len, NULL))r_len = 0;buf[r_len] = '\0';return r_len;}//同步写int write(char *buf, int buf_len){if(!is_open() !buf)return 0;DWORD error;if(ClearCommError(_com_handle, &error, NULL) && error > 0) //清除错误PurgeComm(_com_handle, PURGE_TXABORT PURGE_TXCLEAR); unsigned long w_len = 0;if(!WriteFile(_com_handle, buf, buf_len, &w_len, NULL))w_len = 0;return w_len;}//同步写inline int write(char *buf){assert(buf);return write(buf, strlen(buf));}//同步写, 支持部分类型的流输出template<typename T>_sync_com& operator << (T x){strstream s;s << x;write(s.str(), s.pcount());return *this;}};class _asyn_com : public _base_com{protected:OVERLAPPED _ro, _wo; // 重叠I/Ovirtual bool open_port(){if(is_open())close();_com_handle = CreateFile(_com_str,GENERIC_READ GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL FILE_FLAG_OVERLAPPED, //重叠I/O NULL);assert(is_open());return is_open();//检测串口是否成功打开}public:_asyn_com(){memset(&_ro, 0, sizeof(_ro));memset(&_wo, 0, sizeof(_wo));_ro.hEvent = CreateEvent(NULL, true, false, NULL); assert(_ro.hEvent != INVALID_HANDLE_VALUE);_wo.hEvent = CreateEvent(NULL, true, false, NULL); assert(_wo.hEvent != INVALID_HANDLE_VALUE); }virtual ~_asyn_com(){close();if(_ro.hEvent != INVALID_HANDLE_VALUE)CloseHandle(_ro.hEvent);if(_wo.hEvent != INVALID_HANDLE_VALUE)CloseHandle(_wo.hEvent);}//异步读int read(char *buf, int buf_len, int time_wait = 20) {if(!is_open())return 0;buf[0] = '\0';COMSTAT stat;DWORD error;if(ClearCommError(_com_handle, &error, &stat) && error > 0) //清除错误{PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除输入缓冲区*/return 0;}if(!stat.cbInQue)// 缓冲区无数据return 0;unsigned long r_len = 0;buf_len = min((int)(buf_len - 1), (int)stat.cbInQue);if(!ReadFile(_com_handle, buf, buf_len, &r_len, &_ro)) //2000 下ReadFile 始终返回True{if(GetLastError() == ERROR_IO_PENDING) // 结束异步I/O{//WaitForSingleObject(_ro.hEvent, time_wait); //等待20msif(!GetOverlappedResult(_com_handle, &_ro, &r_len, false)){if(GetLastError() != ERROR_IO_INCOMPLETE)//其他错误r_len = 0;}}elser_len = 0;}buf[r_len] = '\0';return r_len;}//异步写int write(char *buf, int buf_len){if(!is_open())return 0;DWORD error;if(ClearCommError(_com_handle, &error, NULL) && error > 0) //清除错误PurgeComm(_com_handle, PURGE_TXABORT PURGE_TXCLEAR); unsigned long w_len = 0, o_len = 0;if(!WriteFile(_com_handle, buf, buf_len, &w_len, &_wo))if(GetLastError() != ERROR_IO_PENDING)w_len = 0;return w_len;}//异步写inline int write(char *buf){assert(buf);return write(buf, strlen(buf));}//异步写, 支持部分类型的流输出template<typename T>_asyn_com& operator << (T x){strstream s;s << x ;write(s.str(), s.pcount());return *this;}};//当接受到数据送到窗口的消息#define ON_COM_RECEIVE WM_USER + 618 // WPARAM 端口号class _thread_com : public _asyn_com{protected:volatile HANDLE _thread_handle; //辅助线程volatile HWND _notify_hwnd; // 通知窗口volatile long _notify_num;//接受多少字节(>_notify_num)发送通知消息volatile bool _run_flag; //线程运行循环标志void (*_func)(int port);OVERLAPPED _wait_o; //WaitCommEvent use//线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含窗口编号virtual void on_receive(){if(_notify_hwnd)PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0));else{if(_func)_func(_port);}}//打开串口,同时打开监视线程virtual bool open_port(){if(_asyn_com::open_port()){_run_flag = true;DWORD id;_thread_handle = CreateThread(NULL, 0, com_thread, this, 0, &id); //辅助线程assert(_thread_handle);if(!_thread_handle){CloseHandle(_com_handle);_com_handle = INVALID_HANDLE_VALUE;}elsereturn true;}return false;}public:_thread_com(){_notify_num = 0;_notify_hwnd = NULL;_thread_handle = NULL;_func = NULL;memset(&_wait_o, 0, sizeof(_wait_o));_wait_o.hEvent = CreateEvent(NULL, true, false, NULL); assert(_wait_o.hEvent != INVALID_HANDLE_VALUE); }~_thread_com(){close();if(_wait_o.hEvent != INVALID_HANDLE_VALUE) CloseHandle(_wait_o.hEvent);}//设定发送通知, 接受字符最小值void set_notify_num(int num){_notify_num = num;}int get_notify_num(){return _notify_num;}//送消息的窗口句柄inline void set_hwnd(HWND hWnd) {_notify_hwnd = hWnd;}inline HWND get_hwnd(){return _notify_hwnd;}inline void set_func(void (*f)(int)) {_func = f;}//关闭线程及串口virtual void close(){if(is_open()){_run_flag = false;SetCommMask(_com_handle, 0);SetEvent(_wait_o.hEvent);if(WaitForSingleObject(_thread_handle, 100) != WAIT_OBJECT_0)TerminateThread(_thread_handle, 0);CloseHandle(_com_handle);CloseHandle(_thread_handle);_thread_handle = NULL;_com_handle = INVALID_HANDLE_VALUE;ResetEvent(_wait_o.hEvent);}}/*辅助线程控制*///获得线程句柄HANDLE get_thread(){return _thread_handle;}//暂停监视线程bool suspend(){return _thread_handle != NULL ? SuspendThread(_thread_handle) != 0xFFFFFFFF : false;}//恢复监视线程bool resume(){return _thread_handle != NULL ? ResumeThread(_thread_handle) != 0xFFFFFFFF : false;}//重建监视线程bool restart(){if(_thread_handle) /*只有已有存在线程时*/{_run_flag = false;SetCommMask(_com_handle, 0);SetEvent(_wait_o.hEvent);if(WaitForSingleObject(_thread_handle, 100) != WAIT_OBJECT_0)TerminateThread(_thread_handle, 0);CloseHandle(_thread_handle);_run_flag = true;_thread_handle = NULL;DWORD id;_thread_handle = CreateThread(NULL, 0, com_thread, this, 0, &id);return (_thread_handle != NULL); //辅助线程}return false;}private://监视线程static DWORD WINAPI com_thread(LPVOID para){_thread_com *pcom = (_thread_com *)para;if(!SetCommMask(pcom->_com_handle, EV_RXCHAR EV_ERR)) return 0;COMSTAT stat;DWORD error;for(DWORD length, mask = 0; pcom->_run_flag && pcom->is_open(); mask = 0){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_ERRClearCommError(pcom->_com_handle, &error, &stat);if(mask & EV_RXCHAR) // == EV_RXCHAR{ClearCommError(pcom->_com_handle, &error, &stat);if(stat.cbInQue > pcom->_notify_num)pcom->on_receive();}}return 0;}};typedef _thread_com _com; //名称简化#endif //_COM_H_。
vc串口通讯控件MSComm编程详解
vc串口通讯控件MSComm编程详解在mfc中进行串口通讯最简单的方法莫过于在对话框中使用MSCOMM控件了,MSComm通信控件提供了一系列标准通信命令的接口,它允许建立串口连接,可以连接到其他通信设备(如Modem).还可以发送命令、进行数据交换以及监视和响应在通信过程中可能发生的各种错误和事件,从而可以用它创建全双工、事件驱动的、高效实用的通信程序。
一、用MSComm控件通信1.串口通信基础知识一般悦来,计算机都有一个或多个串行端口,它们依次为com1、Com2、…,这些串口还提供了外部设备与pC进行数据传输和皿信的通道。
这些串口在CPU和外设之间充当解释器的角色。
当字符数据从CPU 发送给外设时,这些字符数据将被转换成串行比特流数据;当接收数据时,比特流数据被转换为字符数据传递给CPU,再进一步说,在操作系统方面,Windows用通信驱动程序(COMM.DRV)调用API函数发送和接收数据,当用通信控件或声明调用API函数时,它门由COMM. DRV解释并传递给设备驱动程序,作为一个vB程序员,要编写通信程序.只需知道通信控件提供给Windows通信AP1函数的接口即可.换句话说,只需设定和监视通信控件的属性和事件即可。
2.使用Mscomm控件在开始使用MSComm控件之前。
需要先了解其属性、事件或错误属性描述CommPort 设置或返回通信端口号Settings 以字符串的形式设置或返回波特率、奇偶校验、数据位和停止位PortOpen 设置或返回通信端口的状态。
也可以打开和关闭端口Input 返回和删除接收缓冲区中的字符Output 将字符串写入发送缓冲区CommEvent属性为通信事件或错误返回下列值之一。
在该控件的对象库中也可以找到这些常量。
常量值描述ComEventBreak 1001 收到了断开信号ComEventCTSTO 1002 Clear To Send Timeout。
VC实现串口通信项目源码
VC实现串口通信项目源码以下是一个简单的串口通信项目的VC实现源码,包括了串口初始化、发送数据、接收数据等基本功能。
```#include <Windows.h>#include <stdio.h>#define BUFFER_SIZE 1024HANDLE hSerial;//初始化串口参数BOOL InitSerialPort//打开串口hSerial = CreateFile("\\\\.\\COM1", GENERIC_READ ,GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hSerial == INVALID_HANDLE_VALUE)printf("Failed to open serial port\n");return FALSE;}//配置串口参数DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams); printf("Failed to get serial port state\n"); CloseHandle(hSerial);return FALSE;}dcbSerialParams.BaudRate = CBR_9600; // 波特率为9600 dcbSerialParams.ByteSize = 8; // 8位数据位dcbSerialParams.Parity = NOPARITY; // 无奇偶校验dcbSerialParams.StopBits = ONESTOPBIT;// 1位停止位printf("Failed to set serial port state\n"); CloseHandle(hSerial);return FALSE;}//设置超时操作CloseHandle(hSerial);return FALSE;}return TRUE;//发送数据BOOL SendData(const char* data)DWORD bytesWritten;if (!WriteFile(hSerial, data, strlen(data), &bytesWritten, NULL))printf("Failed to send data\n");CloseHandle(hSerial);return FALSE;}return TRUE;//接收数据BOOL ReceiveData(char* buffer, DWORD size)DWORD bytesRead;if (!ReadFile(hSerial, buffer, size, &bytesRead, NULL))printf("Failed to receive data\n");CloseHandle(hSerial);return FALSE;}return TRUE;if (!InitSerialPort()return 1;}char sendBuffer[BUFFER_SIZE];char receiveBuffer[BUFFER_SIZE];//发送数据printf("Enter data to send: ");gets_s(sendBuffer, BUFFER_SIZE);if (!SendData(sendBuffer))return 1;}//接收数据printf("Receiving data...\n");if (!ReceiveData(receiveBuffer, BUFFER_SIZE)) return 1;}printf("Received data: %s\n", receiveBuffer); CloseHandle(hSerial);```这个项目使用了Windows的串口通信API函数来实现串口的初始化、发送数据和接收数据操作。
VC++MSComm串口发送与接收上位机制做总结
VC++MSComm串口发送与接收上位机本设计用VC编写的一个简单的上位机软件,实现功能为:简单的串口数据发送与接收。
具体步骤如下:一.建立应用程序工程“串口通信_韩季方01”1.打开VC++6.0-》建立对话框MFC应用程序:串口通信_韩季方01—》添加基本控件如图1。
0.图1。
02.添加MSComm控件:Add To Project—》Components and Controls…打开如图1.1,双击“Registered ActiveX Contronls”项—》出现如图1.2—》选择“Microsoft Communications Control,version 6。
0"控件—》点击“Insert”—》提示“…”确认即可-》弹出图1.3—》点击“OK”—》再点击“Close”。
下一步,将对话框资源控件中的电话状控件托到对话框中即可,如图1.4。
图1。
1 图1。
2图1.3图1.4 3。
编辑控件及其属性设置:如表1。
0控件控件ID Caption 需要添加的变量及变量类型静态文本IDC_STATIC 接收显示静态文本IDC_STATIC 发送输入编辑框IDC_EDIT_RXDATA m_strEditRXDataValue CString编辑框IDC_EDIT_TXDATA m_strEditTXDataValue CString 按键IDC_BUTTON_MANUALSEND 发送IDC_MSCOMM1 m_ctrlcomm control MSComm控件表1.04。
添加变量及其类型方法如图1.5图1.5二.初始化串口:设置MSComm控件属性打开Class Wizard—》Member Variables-》选IDC_MSCOMM1-》点击“Add Varialbe…"—》添加变量m_ctrlComm。
如图1。
5。
之后,在工作空间打开文件如图2。
0—》在函数OnInitDialog中添加代码如图2.1.图2.0图2。
基于VC++的串口通信服务的开发论文
基于VC++的串口通信服务的开发摘要随着计算机技术的发展和推广,利用串口进行数据通讯在通讯领域中占有着重要的地位。
为了方便和快速的通过Internet网络访问串口服务器的串口,本课题把串口通信集成到Windows服务,由Windows服务完成串口通信的基本操作。
文中详细描述了串口通信服务的原理和工作流程,还列举出了相关的核心代码。
用流程图的方式来描述了各个模块的逻辑实现。
串口通信服务中采用安全队列的机制来控制多线程访问多串口。
在开发中按照软件工程的流程,从需求分析到概要设计,从详细设计到编码,以及最后的测试,利用软件工程的工具管理开发代码和文档。
此外,还开发出了客户端来测试该服务工作是否正常。
经过测试服务工作正常,能通过网络连接到服务器完成串口的通信。
最后总结了开发和设计的不足之处,程序还有待进一步完善。
关键词:串口通信;Windows服务;安全队列;多线程The Development of Serial Communication ServiceBased on VC++AbstractWith the development and spread of computer technology, serial communication is an important part in the field of computer network communication. In order to access server's serial port more convenient and faster through the Internet, this topic put serial communication services integrated into Windows service, which completed the basic operation of serial communication services. The serial communications services and the workflow are in detail described. The core code of the services is also given. Flow chart is used to describe the handling process of the serial communications services. The services using safe queue mechanism to control multithreading visit serials. During the entire development, according to the software engineering flow, from requirements analysis to summary design, from detail design to coding, and the final test, uses the software engineering tools to management the code and documentation. In addition, I developed a client to test the service.Test results of the experiment indicate the services can work normally. In the end, summarizes the disadvantages of the design and development, and further perfection of studies is surely in need.Key words:Serial Communication; Windows Service; Safe Queue; Multithread目录论文总页数:22页1 引言 (1)1.1 课题背景 (1)1.2 研究现状 (1)1.3 研究的意义 (1)2 相关理论基础 (1)2.1 W INDOWS NT服务 (1)2.2 串口通信 (2)2.3 多线程及线程间通信 (3)2.4 安全队列 (4)2.5 W INDOWS套接字规范 (4)2.6 客户机服务器系统 (5)3 需求分析及设计方案 (6)3.1 功能需求 (6)3.2 设计方案 (7)4 具体设计流程与实现 (8)4.1 安全队列 (8)4.2 服务应用程序 (10)4.3 串口通信 (16)4.4 客户端 (18)4.5 类图 (19)5 调试与分析 (19)结论 (20)参考文献 (20)致谢 (21)声明 (22)1引言1.1课题背景计算机与外界的信息交换称为通信。
基于VC++ 6.0的串口通信实验报告
网络与通信实验报告题目:串口通行实验班级:0309103学号:*********姓名:***指导老师:付大丰日期:2012-10-21一、实验要求把两台计算机的串口通过串口线连在一起,通过串口实现两台计算机通讯。
可以利用高级语言、C语言编程实现,要求程序界面友好,有发送和接收功能,其接收和发送内容可在屏幕上显示。
二、实验原理串口通讯把数据的字节分解成单个的二进制比特流依次传输,其结构简单,连接线少,应用非常广泛。
实现串口通信的方法很多。
如:利用标准通信函数实现串口通信、利用API实现串口通信和利用ActiveX控件实现。
本文主要采用ActiveX控件Microsoft CommunicationsControl(MSComm)编程,Windows平台先进的ActiveX技术使得对串口编程不再需要处理烦琐的细节。
利用已有的AxtiveX控件,只需要编写少量的代码,就可以轻松高效地完成任务。
以下对ActiveX控件属性进行简单介绍,在ClassWizard中为新创建的通信控件定义成员对象(CMSComm m_comm),通过该对象便可以对串口属性进行设置,MSComm控件共有27个属性,这里只介绍其中几个常用属性:CommPort:设置并回通讯端口号,缺省为COMl。
Settings:以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen:设置并返回通讯端口的状态,也可以打开和关闭端口。
Input:从接收缓冲区返回和删除字符。
Output:向发送缓冲区写一个字符串。
InputLen:设置每次Input读入的字符个数,缺省值为0,表明读取接收缓冲区中的全部内容。
InBufferCount:返回接收缓冲区中已接收到的字符数,将其置0可以清除接收缓冲区。
InputMode:定义Input属性获取数据的方式(为0:文本方式;为1:二进制方式)。
RThreshold和SThreshold:表示在OnComm事件发生之前,接收缓冲区或发送缓冲区中可以接收的字符数。
VC++串口通信详解
VC++串口通信详解串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。
本文以VC++为平台进行串口通信编程串口通讯在VC++下实现方式有很多,控件自然是最简单话的方式了,但由于控件只支持对话框程序,有些场合又不需要对话框,所以用Windows API实现是比较好的方式串行通信的操作方式1.同步方式同步方式中,读串口的函数试图在串口的接收缓冲区中读取规定数目的数据,直到规定数目的数据全部被读出或设定的超时时间已到时才返回MTIMEOUTS timeOver;//COMMTIMEOUTS结构用于设置读写函数的等待时间。
2.memset(&&timeOver,0,sizeof(timeOver));3.DWORD timeMultiplier,timeConstant;4.timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;5.timeOver.ReadTotalTimeoutConstant=timeConstant;6.SetCommTimeouts(hComport,&&timeOver);7.……8.ReadFile(hComport,//串口句柄9. inBuffer,//缓冲10. nWantRead,//每次调用ReadFile时,函数试图读出的字节数11. &&nRealRead,//实际读出的字节数12. NULL);//代表ReadFile将采用同步文件读写的方式如果所规定的待读取数据的数目nWantRead较大且设定的超时时间也较长,而接收缓冲区中数据较少,则可能引起线程阻塞。
解决这一问题的方法是检查COMSTAT结构的cbInQue 成员,该成员的大小即为接收缓冲区中处于等待状态的数据的实际个数。
如果令nWantRead 的值等于COMSTAT.cbInQue,就能较好地防止线程阻塞。
VC串口通信资料汇集整理(PDF)
用MFC实现串口编程龚建伟评论:本文既写了在Windows中怎样用VC控件MSComm,又说明了API 技术编程方法,在写用MSComm控件时,数据类型的转换说得不是太明白,初次涉猎串口编程的朋友恐怕看了还是编不出来;直接从底层编写的部分值得一读,说得较为详细,但你得先从VC教本上看一看什么是线程。
一.串行通信的基本原理二.串口信号线的接法三.16位串口应用程序的简单回顾四.在MFC下的32位串口应用程序㈠使用ActiveX控件㈡使用32位的API通信函数本文详细介绍了串行通信的基本原理,以及在Windows NT、Win98环境下用MFC实现串口(COM)通信的方法:使用ActiveX控件或Win API.并给出用Visual C++6.0编写的相应MFC32位应用程序。
关键词:串行通信、VC++6.0、ActiveX控件、Win API、MFC32位应用程序、事件驱动、非阻塞通信、多线程.在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。
计算机和单片机(如MCS-51)都具有串行通信口,可以设计相应的串口通信程序,完成二者之间的数据通信任务。
实际工作中利用串口完成通信任务的时候非常之多。
已有一些文章介绍串口编程的文章在计算机杂志上发表。
但总的感觉说来不太全面,特别是介绍32位下编程的更少,且很不详细。
笔者在实际工作中积累了较多经验,结合硬件、软件,重点提及比较新的技术,及需要注意的要点作一番探讨。
希望对各位需要编写串口通信程序的朋友有一些帮助。
一.串行通信的基本原理串行端口的本质功能是作为CPU和串行设备间的编码转换器。
当数据从CPU 经过串行端口发送出去时,字节数据转换为串行的位。
在接收数据时,串行的位被转换为字节数据。
在Windows环境(Windows NT、Win98、Windows2000)下,串口是系统资源的一部分。
应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
m_ctrlComm.SetInputMode(1); // 以二进制方式检取数据 m_ctrlComm.SetRThreshold(1); //参数 1 表示每当串口接收缓冲区中有多于或等于 1 个字符时将引发一个接收数 据的 OnComm 事件 m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为 0 m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据
运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一 端的串口调试助手(或别的调试工具)接收框里出现了什么。
如果你真是初次涉猎串口编程,又一次成功,那该说声谢谢我了,因为我第一次 做串口程序时可费劲了,那时网上的资料也不好找。开开玩笑,谢谢你的支持, 有什么好东西别忘了给我寄一份。
void CSCommTestDlg::OnComm()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置 BYTE 数组 An 8-bit integerthat is not signed.
在众多网友的支持下,串口调试助手从 2001 年 5 月 21 日发布至今,短短一个月, 在全国各地累计下载量近 5000 人次,在近 200 多个电子邮件中,20 多人提供了 使用测试意见,更有 50 多位朋友提出要串口调试助手的源代码,为了答谢谢朋 友们的支持,公开推出我最初用 VC 控件 MSComm 编写串口通信程序的源代码,并 写出详细的编程过程,姑且叫串口调试助手源程序 V1.0 或 VC 串口通讯源程序吧, 我相信,如果你用 VC 编程,那么有了这个代码,就可以轻而易举地完成串口编 程任务了。(也许本文过于详细,高手就不用看)
5.添加串口事件消息处理函数 OnComm() 打开 ClassWizard->Message Maps,选 择类 CSCommTestDlg,选择 IDC_MSCOMM1,双击消息 OnComm,将弹出的对话框中 将函数名改为 OnComm,(好记而已)OK。
这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个 串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们 在 OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数 中加入如下代码:
开始吧:
1.建立项目:打开 VC++6.0,建立一个基于对话框的 MFC 应用程序 SCommTest (与我源代码一致,等会你会方便一点);
2.在项目中插入 MSComm 控件 选择 Project 菜单下 Add To Project 子菜单中 的 Components and Controls…选项,在弹出的对话框中双击 Registered ActiveX Controls 项(稍等一会,这个过程较慢),则所有注册过的 ActiveX 控件出现在列表框中。 选择 Microsoft Communications Control, version 6.0,,单击 Insert 按钮将它插入到我们的 Project 中来,接受缺省的选项。(如 果你在控件列表中看不到 Microsoft Communications Control, version 6.0, 那可能是你在安装 VC6 时没有把 ActiveX 一项选上,重新安装 VC6,选上 ActiveX 就可以了),
这时在 ClassView 视窗中就可以看到 CMSComm 类了,(注意:此类在 ClassWizard 中看不到,重构 clw 文件也一样),并且在控件工具栏 Controls 中出现了电话 图标(如图 1 所示),现在要做的是用鼠标将此图标拖到对话框中,程序运行后, 这个图标是看不到的。
3.利用 ClassWizard 定义 CMSComm 类控制对象 打开 ClassWizard->Member Viariables 选项卡,选择 CSCommTestDlg 类,为 IDC_MSCOMM1 添加控制变量: m_ctrlComm,这时你可以看一看,在对话框头文件中自动加入了 //{{AFX_INCLUDES() #include "mscomm.h" //}}AFX_INCLUDES (这时运行程 序,如果有错,那就再从头开始)。
最后说明一下,由于用到 VC 控件,在没有安装 VC 的计算机上运行时要从 VC 中 把 mscomm32.ocx、msvcrt.dll、mfc42.dll 拷到 Windows 目录下的 System 子目 录中(win2000 为 System32)
8.发送十六进制字符 在主对话框中加入一个复选接钮,ID 为 IDC_CHECK_HEXSEND Caption: 十六进制发送,再利用
再打开 ClassWizard->Member Viariables 选项卡,选择 CSCommTestDlg 类, 为 IDC_EDIT_RXDATA 添加 CString 变量 m_strRXData, 为 IDC_EDIT_TXDATA 添加 CString 变量 m_strTXData。说明: m_strRXData 和 m_strTXData 分别用来放入 接收和发送的字符数据。
void CSCommTestDlg::OnButtonManualsend() { // TODO: Add your control notification handler code here UpdateData(TRUE); //读取编辑框内容 m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送数据 }
4.在对话框中添加控件 向主对话框中添加两个编辑框,一个用于接收显示数据 ID 为 IDC_EDIT_RXDATA,另一个用于输入发送数据,ID 为 IDC_EDIT_TXDATA,再 添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其 ID 设为 IDC_BUTTON_MANUALSEND。别忘记了将接收编辑框的 Properties->Styles 中把 Miltiline 和 Vertical Scroll 属性选上,发送编辑框若你想输入多行文字,也 可选上 Mi#39;) { i++; continue; } i++; if(i>=len) break; lstr=str[i]; hexdata=ConvertHexChar(hstr); lowhexdata=ConvertHexChar(lstr); if((hexdata==16)||(lowhexdata==16)) break; else hexdata=hexdata*16+lowhexdata; i++; senddata[hexdatalen]=(char)hexdata; hexdatalen++; } senddata.SetSize(hexdatalen); return hexdatalen; }
ClassWizard 为其添加控制变量:m_ctrlHexSend; 在 ClassView 中为 SCommTestDlg 类添加以下两个 PUBLIC 成员函数,并输入相应代码;
//由于这个转换函数的格式限制,在发送框中的十六制字符应该每两个字符之间插入一个空隔 //如:A1 23 45 0B 00 29 //CByteArray 是一个动态字节数组,可参看 MSDN 帮助 int CSCommTestDlg::String2Hex(CString str, CByteArray &senddata) { int hexdata,lowhexdata; int hexdatalen=0; int len=str.GetLength(); senddata.SetSize(len/2); for(int i=0;i<len;) { char lstr,hstr=str[i];
BYTE bt=*(char*)(rxdata+k); //字符型 strtemp.Format("%c",bt); //将字符送入临时变量 strtemp 存放 m_strRXData+=strtemp; //加入接收编辑框对应字符串 } } UpdateData(FALSE); //更新编辑框内容 }
到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行 程序不应该有任何错误,不然,你肯定哪儿没看仔细,因为我是打开 VC6 对照着 做一步写一行的,运行试试。没错吧?那么做下一步:
6.打开串口和设置串口参数 你可以在你需要的时候打开串口,例如在程序中做 一个开始按钮,在该按钮的处理函数中打开串口。现在我们在主对话框的 CSCommTestDlg::OnInitDialog()打开串口,加入如下代码:
// TODO: Add extra initialization here if(m_ctrlComm.GetPortOpen()) m_ctrlComm.SetPortOpen(FALSE);
m_ctrlComm.SetCommPort(1); //选择 com1 if( !m_ctrlComm.GetPortOpen()) m_ctrlComm.SetPortOpen(TRUE);//打开串口 else AfxMessageBox("cannot open serial port");
现在你可以试试程序了,将串口线接好后(不会接?去看看我写的串口接线基本 方法),打开串口调试助手,并将串口设在com2,选上自动发送,也可以等会手 动发送。再执行你编写的程序,接收框里应该有数据显示了。