第八届工业仪表与自动化学术会议
PLC串口通信的MSComm与API实现
The Realization of Series Port Communication for PLC by MSComm and by API
Function
林立春  林琼麒  张功镀
(上海师范大学计算机应用技术研究所,上海  200234)
摘  要:在利用PC(上位机)通过串口通信实现对可编程控制器(PLC)的监控上,本文分别采用了MSComm控件和API函数来实现数据通信,并且在实现时间以及执行效率上进行了比较,用户能够更清楚地了解二者在性能上的差异,因此,在对基于串口通信的PLC监控方式的选择上,用户可以根据实际情况进行合适的选择。 关键词:控制系统 串口通信 PLC MSComm API
Abstract: Using PC to realize the supervisory control to PLC by communication with series port, this article adopt MSComm control and API function respectively, and has carried out comparison on realizing time and carrying out efficiency. So, consumers can understand the difference between their performances clearly. Consequently, on selecting monitoring way in PLC by communicating with series port, consumers can consider the actual conditions to make the best decision.
Keywords: Control System  Series Port Communication  PLC  MSComm  API
0  引言
目前,在上位机(PC)对可编程控制器PLC(Programmable Logic Controller)的通信中一般都采用串口进行通信,这样,串行通信则成为两级计算机控制系统中联系上位机和下位机的桥梁,其通信性能的好坏至关重要,如何实现高性能的串口通信成为了研究的热点。
1  串口通信原理
串口的本质功能是作为串行设备间的编码转换器。当数据从CPU经过串行端口发送出去时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。在Windows环境下,串口是系统资源的一部分。应用程序要使用串口进行通信,必须在使用前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。
目前,串口通信在控制领域的应用中使用是非常多的,其通信方式主要有两种:一是MSCCOM控件;另一种是API函数。其中MSComm控件是微软公司开发的,封装了串口通信的全部API函数,其优点在于使用者不必花费大量时间去了解复杂的API函数。而API函数则由于具有比较强的通信功能,还可编出高质量的通信程序,特别是在CPU处理任务比较繁重、与外围设备有大量的通信数据时,更有实际意义。
2  两种通信方法的实现
2.1  MSC0MM 控件实现通信
1
第八届工业仪表与自动化学术会议
ActiveX是Windows下进行应用程序开发的新技术,它的核心内容是组件对象模型COM (Component Object Mode1)。ActiveX控件包括一系列的属性、方法和事件,合理地使用能够使你的程序简单易懂。因此在使用ActiveX MSComm控件时,只要调用相关的属性、方法和事件就可以了。MSComm控件提供两种处理通信的方式:事件驱动(Event—driven)方式和查询方式。其中事件驱动方式是处理串行端口交互作用的一种非常有效的方法。许多情况下,事件发生时需要得到通知,此时可以利用MSComm控件中的OnComm事件捕捉并处理这些通信事件。而查询方式则是在程序的每个关键功能之后,可以通过检查CommEvent属性的值来轮询(polling)事件和错误,其实质还是事件驱动。所以通常我们选择事件驱动方式。具体步骤如下:
① 建立一个MSComm控件,接着定义一个对象(如m_com);
② 串口初始化。包括打开哪个串口、数据传输速率、检验位、停止位等参数设置;
③ 发送数据。传送数据的时候,利用成员函数SetOutput(VARIANT& newValue),接下来就是等待PLC根据具体指令做相应动作并返回确认;
④ 设置CommEvent事件来监控串口是否收到数据,每当串口收到数据,就会产生一个串口接收数据缓冲区中有字符的事件,然后用GetInput从串口取得数据。关键程序部分如下:
VARIANT readbuffer;
COleSafeArray readsafearray; LONG len,i;
BYTE rxdata[4096];//设置BYTE数组 CString strtemp;
CString strdisp; //用于显示接收数据 if (m_com.GetCommEvent()==2)
{ readbuffer=m_com.GetInput();//读缓冲区
readsafearray=readbuffer;//VARIANT型变量转换为ColeSafeArray型 len= readsafearray.GetOneDimSize();//得到有效数据长度
for(i=0;ifor(i=0;istrdisp+=strtemp;//加入到接收编辑框   strtemp.Empty(); }m_strSend=strdisp; UpdataData(FALSE);
ReportAnalysis();//如果有必要,该函数分析接收的数据帧 }  事件驱动方式的串口通信流程图如图1所示。
2
第八届工业仪表与自动化学术会议
图1  MSComm 控件执行的流程图
在实践应用中,该方法实现起来简单,不用编写大量的代码,也不用了解复杂的硬件串口编程。但是,它不够灵活,很难编出高质量的通信程序,且要间接调用API函数,因此执行效率比API函数要低。
2.2  Windows API函数通信
由于MSComm 控件通信是单线程通信,在很多实际的工业控制系统中,经常通过扩展串口连接多个外设,各外设发送数据的重复频率不同,要求后台实时无差错捕捉、采集、处理、记录各口数据,这就需要在自定义的串行通信类中创建端口监视线程,以便在事件发生时发出响应消息。所以在应用时,可以采用多线程等手段来解决多个外设的问题。特别是在CPU处理任务较繁重和与外围设备有大量通信数据时,API函数就显示了强大的通信功能。
多线程通信类的编写在端口的配置、连接方面与单线程通信相同。端口配置完毕后,最重要的是根据实际情况,建立多线程之间的同步对象。Win32区分两种不同类型的线程:一种是用户
3
第八届工业仪表与自动化学术会议
界面线程UI(User Interface Thread),它包含消息循环或消息泵,用于处理接收到的消息;另一种是工作线程(Work Thread),它没有消息循环,用于执行后台任务,监视串口事件。
主要的设计步骤如下:
① 建立串口的句柄和一个辅助线程的全局变量,并利用CreateFile打开一个串口,同时要注意使用FILE_FLAG_OVERLAPPED结构,主要是为了实现非阻塞通信。
② 启动一个辅助线程,用来对串口事件进行处理。同时还要编写一个全局函数,用来完成数据的接收工作。由于在调用CreateFile()时使用了FILE_FLAG_OVERLAPPED,所以在调用ReadFile()时IpOverlapped参数一定不能为NULL。接着检查函数调用的返回值,并调用GetLastError(),看是否返回ERROR_IO_PENDING,如是,最后再调用GetOverlappedResult()返回重叠操作的结果;调用WriteFile()函数也类似。
③ 在主线程中编写对PLC发送的下行命令。为了不影响在线实时检测的主程序的运行,本文依靠重叠(overlapped)读写操作,让串口读写操作在后台运行。
流程图如图2所示。
图2  WINAPI函数执行的流程图
3  两种方法的对比
通过多次改变实验环境的测试,并且在运行时记录两种方法在相同环境读取相同量数据时的实验数据,得出的比较结果如下:
4
第八届工业仪表与自动化学术会议
① 执行时间
在向PLC发送数据前记录系统时间,然后在取得PLC返回数据之后计算下时间。比较结果见表1。
表1  两种方法执行时间上的对比  执行时间 API函数      (ms) MSComm控件 实验次数1 2 3 4 5 6 16 15 21 20 32 33 13 11 16 15 19 20 ② 数据处理
在处理数据的时候,它们都可采用CString、BYTE、Char类型数组的形式发送,但在接收数据时有区别。用控件时先将数据存在一个VARAINT型变量中,然后从bstrVal中取数据;而API函数接收数据直接存在一个BYTE型数组中。
③ 适用场合
API函数在通信任务较复杂的系统中具有优势,尤其适合多线程编程,并且通信比较稳定。MSComm控件编写代码较简单,适用于通信任务较简单的系统。当将其用于多线程编程时,易发生异常,甚至导致死机,所以并不适合应用于多线程程序中。
4  结束语
综上所述的两种实现方法,用VC++6.0在本文的工程系统里已经得到验证,且两者的对比较明显。因此,要想简单实现串口通信并且对执行效率要求不高的话,就可以使用MSComm控件,同时可以大大地简化编程的难度和缩短时间,使程序结构清晰。当所作的是对多个PLC组成的网络操作的话,最好采用API函数,这可以充分结合多线程技术,编写出具有强大控制能力的串口通信应用程序。
参考文献
1 Karl-Heinz JoHn,Michael TiegelKamp. IEC61131—3工业自动化系统的程序编制. 北京:中国机电一体化技术应用协会秘书处翻译并出版,2002,188-218.
2 李现勇.Visual C++串口通信技术与工程实践[M].北京:人民邮电出版社,2002. 3 高钦和.可编程控制器应用技术与设计实例[M].北京:人民邮电出版社,2004. 4 常斗南.可编程控制原理应用实验【M】.北京:机械工业出版社,2003.
5 求是科技.Visual C++ Visual Basic串并口开发技术工程应用实例导航.北京:人民邮电出版社,2006                          第一作者李立春,男,1974年生,现为上海师范大学数理信息学院在读硕士研究生,讲师;主要研究方向为自动化技术、智能化仪器仪表。
5