C++课程论文--串口通信编程
课程论文首页
基于VC++的串口通信编程
中文摘要:随着现代信息技术的发展以及计算机网络的广泛应用,计算机通信技术已经日趋成熟,串口通信作为一种灵活、方便、可靠的通信方式,被广泛应用于工业控制中。设计中介绍了串口通信的基本概念及原理,及在VC++6.0平台下,运用MSComm控件实现串口通信的编程。设计结果表明:利用Visual C++6.0开发环境本身已有的控件MSComm进行开发设计,可以减少开发时间,节约开发投资,具有重要的现实意义。
关键词:VC++ 串口通信 MSComm
0 引言
计算机与外界的信息交换称为通信,基本的通信方式有并行通信和串行通信2 种。在远程监控和工业自动化领域系统常见的通信编程多为串口通信。串行通信是指一条信息的各位数据被逐位按顺序传送的通信方式。串行通信的特点是: 数据位传送按位顺序进行,最少只需要一根传输线即可完成,成本低、传送速度慢。串行通信的距离可以从几米到几千米。
目前,计算机的串行通信应用十分广泛,串行接口已成为计算机的必须部件和接口之一。计算机串并口编程在通信软件中有着十分广泛的应用,如电话、传真、视频和控制等。在Windows 应用程序的开发中,常常需要面临与外围数据源设备通信的问题。一般多是利用控件MSComm 设计相应的串口通信程序,完成上位机与下位机之间的数据通信任务。[1]
利用Visual C++编制串行通信程序有3种方法:一是采用Win32应用程序编程接口(API)所提供的串行通信函数,用SDK思路编写;二是用ActiveX通信控件MSComm开发串行通信程序;三是采用C++的MFC思路,将Win32串口通信的API函数封装在一个类中实现串行通信。
在实践中,使用Visual C++串口控件MSComm实现通信的方法比调用API动态链接库的方法更加方便、快捷,而且用较少的代码可以实现相同的功能,从而大大提高了编程效率,也减少了因编程不当而导致的系统不稳定。
采用C++的MFC思路的方法较为繁琐,不仅要了解Win32串行通信的API函数,还要掌握多线程编程,但控制灵活,既涉及到底层编程、纠错能力强,又有C++风格,一般多为专业C++开发人员所采用。
1串口通信基础
1.1串口通信原理
串行端口是CPU和串行设备间的编码转换器。当数据从CPU经过串行端口发出去时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。在Windows环境下,串口是系统资源的一部分。应用程序要使用串行进行通信,必须在使用之前向操作系统提出资源申请请求(打开串口),通信完成后必须释放资源(关闭串口)。
1.2串口通信特点
目前数据通信多采用串口技术。主要原因是串口通信可以在现有的电话网络上进行数据传输,只要通信双方有Modem,就可以再电话网络上进行远程通信。一般地说,串口通信具有如下特点。
●通信成本低
串口通信可以采用现有的信道(例如,电话、电报信道),再配置适当的通信接口,就可以再任意两点间实现通信。
●在一条线路上进行数据传递
数据信号和联系信号在一条数据信号线上按位传递,每一位占据一个固定的时间长度。在远距离传输时,能够降低成本,但是传输速度较慢。
1.3串口通信传输方式
串口通信通常分为单工通信、半双工通信和全双工通信3种方式。
●单工通信
在单工通信中,数据信息智能固定地从发送端A传送到接收端B。在单工通信线路上,一般采用两个信道,一个传送数据,一个传送控制信号。传输形式如图1-1所示。
图1-1 单工通信
●半双工通信
在半双工通信中,允许数据双向传送,但不能同时进行。在半双工通信中,要求通信的两端具有发送装置和接收装置。例如,使用对讲机时,当甲方讲话时,乙方无法讲话,只有等到甲方讲完后,乙方才能讲话。传输形式如图1-2所示。
图1-2 半双工通信
●全双工通信
在全双工通信中,允许通信双方同时在两个方向进行数据传输,它相当于将两个方向相反地单工通信方式组合起来。例如,打电话时,双方可以同时讲话。全双工如图1-3所示。
图1-3 全双工通信
1.4串口通信同步技术
串行传输中,数据是一位一位按照到达的顺序依次传输的,每位数据的发送和接收都需要时钟来控制。发送端通过发送时钟确定数据位的开始和结束,接收端需要在适当的时间间
隔对数据流进行采样来正确地识别数据。接收端和发送端必须保持步调一致,否则就会在数据传输中出现差错。为了解决以上问题,串行传输可采用以下两种方法:异步传输和同步传输。
●异步传输。
在异步传输方式中,字符是数据传输单位。在通信的数据流中,字符间异步,字符内部各位间同步。异步通信方式的“异步”主要体现在字符与字符之间通信没有严格的定时要求。异步传输中,字符可以是连续地、一个个地发送,也可以是不连续地、随机地进行单独发送。在一个字符格式的停止位之后,立即发送下一个字符的起始位,开始一个新的字符的传输,这叫做连续的串行数据发送,即帧与帧之间是连续的。断续的串行数据传送是指在一帧结束之后维持数据线的“空闲”状态,新的起始位可在任何时刻开始。一旦传送开始,组成这个字符的各个数据位将被连续发送,并且每个数据位持续的时间是相等的。接收端根据这个特点与数据发送端保持同步,从而正确地恢复数据。收/发双方则以预先约定的传输速率,在时钟的作用下,传送这个字符中的每一位。
●同步传输。
在同步传输方式中,比特块以稳定的比特流的形式传输,数据被封装成更大的传输单位,称为帧。每个帧中含有多个字符代码,而且字符代码与字符代码之间没有间隙以及起始位和停止位。和异步传输相比,数据传输单位的加长容易引起时钟漂移。为了保证接收端能够正确地区分数据流中的每个数据位,收发双方必须通过某种方法建立起同步的时钟。可以在发送器和接收器之间提供一条独立的时钟线路,由线路的一端(发送器或者接收器)定期地在每个比特时间中向线路发送一个短脉冲信号,另一端则将这些有规律的脉冲作为时钟。这种技术在短距离传输时表现良好,但在长距离传输中,定时脉冲可能会和信息信号一样受到破坏,从而出现定时误差。另一种方法是通过采用嵌有时钟信息的数据编码位向接收端提供同步信息。
2MSComm控件
2.1MSComm控件简介
MSComm控件全称为Microsoft Communications Control,是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它既可以用来提供简单的串行端口通信功能,也可以用来创建功能完备的、事件驱动的高级通信工具。
MSComm控件在串口编程时非常方便,程序员不必花时间去了解较为复杂的API函数,而且在Visual Basic、Visual C++、Delphi等语言中均可使用。
MSComm控件提供了一系列标准通信命令的使用接口,使用它可以建立与串行端口的连接,通过串行端口连接到其他通信设备(例如调制解调器),发出命令,交换数据以及监视和响应串行连接中发生的事件和错误。利用它可以进行诸如拨打电话、监视串行端口的输入
数据乃至创建功能完备的终端程序等。
2.2MSComm使用
在应用程序中插入MSComm控件后就可以较为方便地实现计算机串口收发数据。要使用ActiveX控件MSComm,程序员必须将其添加入工程,其方法如下。
(1)选择主菜单Project中的子菜单Add To project下的Components and Controls选项。(2)在弹出的“Components and Controls Gallery”对话框中选择Registered ActiveX Controls文件夹中的“Microsoft Communications Control,version 6.0”选项,如图2-1所示
图2-1 添加MSComm控件
(3)单击“Insert”按钮,MSComm控件就被添加到工程中了。与此同时,类CMSComm的相关文件mscomm.h和mscomm.cpp也一并被加入Project的Header Files和Source Files 中。当然,程序员可以自己修改文件名,如图2-2所示。
图2-2 修改文件名窗口
(4)单击“OK”按钮,在工具箱面板上就出现了一个形似电话的控件,使用时,将其拖到界面上即可。
2.3MSComm控件常用事件
MSComm控件只提供一个OnComm事件,该事件在串口状态发生改变时触发。例如,用户发送和接收数据时,都将触发OnComm事件。通常在该事件中调用GetCommEvent方法获取串口中发生的事件。根据不同的事件执行相同的动作。在Visual C++中,可以利用类向导来编写OnComm事件处理函数。
(1)打开Class Wizard类向导,如图2-3所示。
图2-3 类向导
(2)选择MessageMaps选项卡,在Object IDs列表中选中MSComm控件ID,在Message列表中将显示OnComm消息,双击OnComm,MFC类向导将自动编写其消息处理函数。
Void CCComDlg::OnOnCommMscomm1()
{
// TODO: Add your control notification handler code here
}
3串口通信程序设计
3.1串口通信设计
硬件方面需要2 个串口来测试程序,这2 个串口可以在同一台机器上,也可以分别在2 台计算机上用串口线将其连接。程序设计方面在利用MSComm 控件来实现发送,接收数
据[5]。串口使用虚拟串口工具实现。图3-1为串口发送程序设计图。
图3-1 串口发送端程序设计
3.2串口发送代码分析与实现
添加编辑框,ID为IDC_EDIT_TXDATA,打开类向导,在IDC_EDIT_TXDATA下添加成员变量m_strTXData类型为control,变量类型为CEdit。添加发送数据按钮,ID为IDC_BUTTON_TX,打开类向导,在IDC_BUTTON_TX下添加BN_CLICKED消息事件,系统自动生成其消息处理函数。
void CMyMSCommDlg::OnButtonTx()
{
CString str; //字符串变量
m_strTXData.GetWindowText(str); //获取编辑框内容存入str
IsSended=FALSE; //发送判断标识
m_ctrlcomm.SetOutput((COleVariant)str);//将str中的内容存入发送缓冲器并发送
IsSended=TRUE;
Sleep(1000);延时1S
}
3.3串口接收代码分析与实现
添加接收编辑框,ID为IDC_EDIT_RXDATA,在类向导中为IDC_EDIT_RXDATA新建成员变量m_strRXData。在IDC_MSCOMM1中添加OnComm消息机制,系统自动生成OnComm消息处理函数。
void
CMyMSCommDlg::OnOnCommMscomm1() {
int resEvent;
resEvent=m_ctrlcomm.GetCommEvent( );//获取串口发生事件,接收事件为2
switch(resEvent) //判断是否为接收事件
{
case 2:
{
IsReceive=TRUE; //接收标识
if(IsReceive)
{
VARIANT data;
data=m_ctrlcomm.GetInput();//从串口接收数据
CString str;
str=data.bstrVal;
IsReceive=FALSE;
m_strRXData.SetWindowText(str);//将接收的数据在编辑框显示
}
}
break;
}
}
3.4串口设置代码分析与实现
添加命令按钮,ID为ID_MSComm_OpenPort,在类向导中为ID_MSComm_OpenPort添加BN_CLICKED消息处理,系统自动生成消息处理函数。
void CMyMSCommDlg::OnMSCommOpenPort() {
switch(Flag) //当前打开或关闭状态标识
{
case TRUE: //若为关闭
{
if(m_ctrlcomm.GetPortOpen()) m_ctrlcomm.SetPortOpen(FALSE);//
若为开启状态则关闭
m_ctrlcomm.SetCommPort(2);//设置串口端号为2
if(!m_ctrlcomm.GetPortOpen())//若为关闭状态{
m_ctrlcomm.SetPortOpen(TRUE);//开启端口
MessageBox("打开成功","Success");//提示开启弹出消息
m_ctrlcomm.SetRThreshold(1);//设置收到多少个字符后触发OnComm事件
m_ctrlButton.SetWindowText("关闭串口");//设置按钮显示为“关闭串口”
}
else
MessageBox("打开失败","Fail");//若串口已被打开,则提示打开失败
Flag=FALSE;//当前按钮状态为打开串口后
}
break;
case FALSE:
{
m_ctrlcomm.SetPortOpen(FALSE);
MessageBox("关闭成功","Success");
m_ctrlButton.SetWindowText("打开串口");
Flag=TRUE; }
break;
} }
4调试运行
(1)将串口设置为端口1和端口2,分别编译链接项目,以下命名为A机和B机,运行调试,则出现程序界面,单机打开串口按钮,如图4-1所示。
图4-1 打开串口
(2)在A机发送数据框中输入数据并发送,则在B机接收窗口收到同样的数据,同样在B 机发送A机也可收到,调试结果如图4-2所示。
图4-2 调试发送与接收
参考文献:
[1] 张立科.Visual C++开发技术大全[M].北京:人民邮电出版社,2007:624-625.
[2] 张少波.Visual C++网络通信编程技术详解[M].北京:机械工业出版社,2011