VB环境下基于内存共享技术的串行通讯程序设计

2014-04-29 13:29黄頔刘桦杰李艳宁
智能计算机与应用 2014年5期
关键词:共享内存

黄頔 刘桦杰 李艳宁

摘 要:VB由于具有强大的界面生成能力及灵活的数据库操作功能,是上位软件的主要编程工具之一,在很多场合领域得到了应用。然而,直接采用VB编程的主要问题是可靠性较差,特别是在与其它低层设备,如PLC通讯时。本文提出一种采用内存共享技术的程序之间数据交换方法,将VB的通讯子程序和主程序分离,以解决通讯子程序死锁等故障对主程序的影响。本方法用在汽车安全气囊装配生产线的软件设计中,取得了良好的效果。

关键词:VB;内存映射;共享内存;串行通讯;PLC

中图分类号:TP311 文献标识号:A 文章编号:2095-2163(2014)05-

Serial Communications Design based on Data Sharing Technology under VB Platform

HUANG Di, LIU Huajie, LI Yanning

(School of Precision Instruments and Optoelectronics Engineering, Tianjin University, Tianjin 300072, China)

Abstract: VB (Visual Basic) is widely used in many applications as a program tool for host computers, because of its capacity of interface generation and the flexible operation of databases. However, one of the main problems when programming with VB is its unsatisfactory reliability, especially in the communication between the host computer and the lower CPU. The paper proposes a method of data exchange between programs using shared memory, which separates the communication program with the main program, to reduce the impact of faults, such as deadlock, on the main program. The method has been applied on the design of airbag assembly line for automobiles and has obtained good results.

Keywords: VB; Memory Mapping; Shared-memory Technology; Serial Communications; PLC

0 引 言

汽车安全气囊作为汽车行驶过程的第一很总要安全部件,对其生产过程的可靠性以及质量控制研究即已成为近年来的研讨热点。通常,一条汽车安全气囊装配线多会由若干个装配或检测工位计算机,以及一台数据库服务器工位计算机组合设计而成[1]。其中,每个工位计算机可能和本工位的条码扫描器、PLC、电动螺栓拧紧机和专用电气检测仪表等多种串行设备进行广泛互连,可实现部件品种纠错及工序间顺序控制等功能;进一步地,还可记录操作人员信息、机械或电气等检测参数信息,并存入SQL数据库实现产品追溯功能。但是,如果计算机上的监控软件均采用组态软件时,由于站点数量较多,而使得成本颇高,同时组态软件还存在着对数据库支持功能不足等缺陷。基于此种情况,经过分析可知,应用VB等高级语言设计程序仍然是比较常用的方法之一。但是由于设计者技术等方面的原因,该类应用程序普遍存在可靠性差,后续维护困难等问题,特别是在与其它底层设备,如PLC通讯时,常会由于通讯错误而引发系统死机或操作反映延迟等现象。本文即针对这一状况,提出了一种采用内存共享技术的解决方案[2],并以上位计算机与S7-200 PLC进行串行通讯为例进行了仿真验证,而且取得了良好的应用效果。

1采用内存共享技术的通讯原理

多数情况下,普通用户会将通讯子程序嵌入到主程序中,这样当通讯发生错误,或通讯返回数据需要时间较长时,系统将会发生死锁或停顿现象,严重时还会影响操作界面程序的正常运行。为此,本文采取了一种利用公共数据区交换数据的方法,将通讯程序和主程序分成两个独立的可执行文件,并且通讯程序位于后台工作,而主程序则位于前台。采用这种方法的优点在于通讯程序和人机界面及其它控制程序、也就是主程序是完全分离的,即使通讯程序出现暂时的死锁现象,也不致影响主程序的正常运行,从而提高了软件的可靠性和可操作性。同时,由于Win32是一个基于页式虚拟内存的操作系统,每个进程只能访问自己的虚拟内存页面空间,若要实现这种公共数据区的预设功能,就要利用内存映射文件的概念。

内存映射文件技术是WINDOWS内存管理的一个重要组成部分。当一个应用程序启动时,系统打开该应用程序的.exe文件,确定该应用程序的代码和数据规模,系统也随之保留一个地址空间的区域,并指明与该区域相关联的物理存储器就是.exe文件本身,这一过程可称为内存文件映射,具体来说就是系统装载.exe文件,并将其映射到进程地址空间的过程。如果使两个或多个进程映射同一文件映射对象的视图,那么就将共享磁盘上同一文件或者物理磁盘的同一页面,这样当一个进程将数据写入另一个共享文件映射对象的视图时,其他进程可以立即在其对应视图中查看数据的变化,从而实现了进程间内存级的高速数据传输[3],这一过程如图1所示。

图1 采用内存映射文件的公共数据交换过程示意图

Fig. 1 Data exchange between programs using shared memory

需要指出的是,共享文件可以是一个磁盘文件,也可以是一个物理内存区域,或一个虚拟磁盘区域。为了实现高速交互,一般只使用物理内存或虚拟磁盘文件。另外,对每一个通讯程序,根据数据类型和应用要求,可以设置多个共享文件映射对象。

2 内存映射文件的使用步骤

VB本身不提供内存映射文件操作功能,此时需要调用WINDOWS提供的API函数实现,且将执行下列操作步骤[2-3]:

(1) 创建一个内存映射文件。用函数Create_FileMapping()在主程序中创建一个文件映射内核对象,例如

Long MappingHandle= CreateFileMapping(&HFFFFFFFF,0,PAGE_READWRITE,0,256, “map”)

即表示创建了一个可读写的、256字节、且名字为“map” 的内存映射文件。同时,为了实现快速数据传输,设置第一个参数为&HFFFFFFFF,即表示在物理内存上创建对象。通过调用本函数就可获得文件映射内存对象句柄。

(2) 在创建文件映射对象后,主程序调用MapViewOfFile()函数映射到本程序的地址空间内,例如:

Long MapingAddress = MapViewOfFile(MappingHandle, FILE_MAP_WRITE, 0, 0, 0)

(3) 通讯程序访问共享内存对象时,需要通过内存对象名调用OpenFileMapping()函数,以获取共享内存对象的句柄。例如:

Long MappingHandle = OpenFileMapping(FILE_MAP_WRITE, False, "map")

(4) 如果通讯程序成功获得了共享内存对象的句柄,也需要执行(2)的操作来获取映射对象视图指针。

(5) 主程序或通讯后台程序利用(2)返回的映射对象视图指针MapingAddress,采用CopyMemory()函数实现即可实现对该空间的访问,具体可参见实例代码部分。

当完成对内存映射文件的使用时,需要执行如下步骤将其彻底清除。具体步骤为:

(1) 调用UnmapViewOfFile()从进程地址空间中撤销文件映射内核对象的映像。

(2) 调用CloseHandle()关闭文件映射内核对象。

3 PC与PLC的串行通讯技术

VB中通常采用了MSComm控件以实现工位PC与PLC等底层设备的交互通讯。MSComm控件的实用性强、功能完善,同时更为应用程序提供了通过串行接口收发数据的简便方法[4]。

MSComm控件提供了两种处理通信的方式。一种是事件驱动方式,当有字符到达或发生变化时,MSComm控件都将触发OnComm事件。事件驱动方式的优点就是程序响应及时,但由于接收一个完整信息却需多次中断,如此则不仅降低了程序的执行效率,而且也增加了出错的可能性;另外一种即是查询方式,通过定时或延时查询MSComm控件的某些属性(比如CommEvent和InBufferCount属性)值是否发生变化,以此来选择并确定相应的处理程序。这种方式的优点就在于可以由用户控制通讯过程,尤其当程序空闲较多时多采用这种方式。

本文将每个通讯过程设计成独立的通讯程序,每一通讯程序将采用查询方法来实现和底层设备的通讯过程,再通过各自定义的公共数据区而与主程序实现数据交换。下面即可、以与西门子的S7-200PLC的MODBUS通讯方式为例,介绍通讯程序的设计,PLC侧的MODBUS通讯程序利用西门子公司所提供的库函数[5]。

具体地,通讯程序的一次通讯流程则如图2所示,实际程序中,每次通讯过程均由定时器定时触发。

由图2可知,通讯程序设置定时器定时向通讯对象(如PLC)发出读信息命令,并置循环计数器n=0、再休眠(延时)一定时间间隔后,即进入读取接收信息死循环。程序首先读取缓冲区接收字符长度(InBufferCount)信息,若该值不为零,说明数据已经收到,接收后分解数据,同时根据接收到的功能号或校验结果,判断接收是否正确。若正确,就将该数据更新标志G_ShrPLC.bFlag置为1,且更新数据G_ShrPLC.nDdata,并调用WriteToSharedMemory()存入公共数据区(详情参见程序代码);若不正确则丢弃。若InBufferCount值为零,说明没有接收到数据,空循环,再次读取InBufferCount信息,并使空循环计数器n加1,当n超过设定次数(如10次)时,即预定为接收失败,将跳出接收死循环。

采用如上方法可以人工控制程序流程,避免出现死循环现象,而且需要根据读信息命令的内容,调节延时间隔,即可以实现正确的接收过程。

而对于通信主程序来说,也是由相同定时间隔的定时器触发定时读取公共区的数据,再根据数据更新标志G_ShrPLC.bFlag来判断是否进行更新显示或控制等操作,由此可见数据更新标志在主程序和通讯子程序之间起到一个同步作用,详细流程则如图3所示。此外,对于向PLC下发控制命令,则采取相反的流程。

4 部分程序代码

在此,给出内存映射文件的部分实例代码,具体则如下所示。

Type stShrPLC '定义PLC数据结构

bFalg As Boolean ' PLC数据更新标志

nDdata As Integer ' PLC数据

End Type

Public G_ShrPLC As stShrPLC ' PLC传递数据

Public Const Str_ShrPLC = "H_ShrPLC" '内存映射文件名称

Public hMH_ShrPLC As Long '内存映射句柄

Public hMA_ShrPLC As Long '映射视图指针

Public Sub Form_Load() '窗口加载函数

hMH_ShrPLC =CreateFileMapping(&HFFFFFFFF,0, PAGE_READWRITE,0, Len(G_ShrPLC), Str_ShrPLC)

'创建内存映射文件

If hMH_ShrPLC = 0 Then MsgBox "创建内存映射文件失败", vbQuestion, "错误"

If( Err.LastDllError= 138&) Then '指定内存文件已存在,退出

CloseHandle (hMH_ShrPLC) '关闭映射文件

End

End If

hMA_ShrPLC = MapViewOfFile(hMH_ShrPLC, FILE_MAP_WRITE, 0, 0, 0) '创建映射视图

If hMA_ShrPLC = 0 Then

CloseHandle(hMH_ShrPLC) '退出前关闭

End

End If

End Sub

Public Sub WriteToSharedMemory() '写数据函数

If hMA_ShrPLC <> 0 Then

Call CopyMemory(ByVal hMA_ShrPLC, ByVal G_ShrPLC, Len(G_ShrPLC))

End If

End Sub

Public Sub GetFromSharedMemory() '读数据函数

If hMA_ShrPLC <> 0 Then

Call CopyMemory(ByVal G_ShrPLC, ByVal hMA_ShrPLC, Len(G_ShrPLC))

End If

End Sub

5 结束语

将主程序与PLC等通讯程序分离,同时利用共享内存技术实现程序间数据的快速交换,并且充分利用Windows系统自身的多任务调度机制,得到的监控程序具有通讯可靠、界面操作流畅等优点。应用时由主程序调用SELL()启动其它通讯程序,并设其为后台运行方式。本方法可用于研制的汽车安全气囊装配生产线上,而且通过在企业的实际应用,系统已完全达到了设计目标,获得了良好的应用效果。

参考文献:

[1] 胡荣, 沈俊杰. 基于条形码技术的汽车安全气袋监控系统研制[J]. 机电一体化,2007(2):48-51,54.

[2] 孙文庆, 刘秉权, 肖镜辉.基于内存映射文件的数据共享技术研究与应用[J]. 微计算机应用,2005,26(2):192-194.

[3] 党志斌, 李迎纲, 樊燕京等. 基于内存映射的进程间通信实现跨平台软件互联互通[J]. 现代电子技术, 2012, 29(14):46-47.

[4] 裘智峰,成晓明. 基于PLC 的不定字长的串行通讯的研究及实现[J]. 工业控制计算机,2004,17(2):54-55.

[5] 夏勇. Modbus通讯协议在S7-200通讯中的应用 [J]. 自动化与仪器仪表, ,2009, (1):48-50.

猜你喜欢
共享内存
通过QT实现进程间的通信
基于Linux内核的文件服务器模型的研究与构建
基于PCI总线的多处理器协同机制研究
一种高效RTAI 共享内存管理层的研究与实现*