蔡文斋
(中国电子科技集团公司第三十九研究所 陕西 西安 710065)
实时监控程序的实验室快速调试开发
蔡文斋
(中国电子科技集团公司第三十九研究所 陕西 西安 710065)
提出了航天测控工程中实时监控类应用软件开发中的仿真调试几种方法,该文主要展示了一种内嵌在监控程序本身的窗口调试法,该方法使用一个独立的十六进制编辑窗口发消息方式代替某接入计算机的硬件传感器,在实验室内可完全仿真出硬件通讯时的环境,可灵活地按协议给出硬件传感器发送给计算机的定长信息,从而可无硬件环境下调通整个监控系统,一旦硬件配件接通,协议级的通讯亦随即完成。
复杂控制系统 仿真调试 测控工程 线程 事件
航空、航天和电子等领域内实时监控系统通常由若干计算机,一大堆相关板卡构成一个硬件环境,通常在Win32环境下编制相关的监控软件,假定已知了相关的硬件需求和相应的软件通讯协议后,可否在实验室内无硬件设备时完全开发出全套监控系统软件,文章提供的方法即为此目的而设计[1]。承研单位的监控软件在Windows xp环境下使用C++或者Delphi开发。通常的做法是,开发人员等到买到各种相关板卡后再逐个调试各端口,当设备全联在一起时统一联调,通常联调时很费时费力,要求各设备或者分机配合一块调。文中提出的方法是:在实验室内,无需连接各板卡,同样可以仿真出这些硬件设备开发出整个监控软件,等到各种板卡到位后,再添加这些板卡的设备初始化及I/O函数。这样,在实验室内,整套监控软件在无硬件环境下可以提前编制完成。作者在组织项目中监控软件开发时,工程中使用的板卡因为种种原因未能够及时到位,但工程任务时间要求紧,如果等到各板卡到位再编制监控软件时,那么整个进度将无法保障。作者使用监控程序内加调试支持方法巧妙解决了这类问题。
假定不考虑接入计算机的某板卡接口形式,不考虑具体的某硬件传感器的特性,仅从抽象的角度考虑,那么可以将接入的任一硬件传感器都视为一流设备,这些硬件设备通过相关板卡与计算机联在一起,计算机与这些板卡的通信就是一串十六进制码字的交换,任一硬件的读入形式经抽象化后都是一样的。比如如下的某航天测控类应用项目:该项目是一雷达测控站,控制计算机要外接的硬件具体设备,如图1所示,计算机经接口板卡与硬件设备的连接示意图如图2所示。
图1 工程硬件结构图
图2 数字计算机接口图
任一接入控制计算机的硬件设备与计算机通讯本质上是一定长的十六进制字符码字的双向信息交流,在程序中即为读写函数Read与Writ函数[2],无论硬件接口形式是什么,最终抽象的读写参数是一样的:设备号、读写缓冲区数据内容、读写长度、实际读入或者写出的长度及回送的状态码字。例:
Ret=ReadAny(HardNum:integer;设备号
Const Buffer;缓冲器
ReadLength);欲读入的长度
Ret为实际读入的长度,也表示回送的状态码字,写出函数同理。姑且不论某一硬件传感器是怎样初始化及怎样使用的,一般相关板卡均带有驱动程序,在Win32环境下通常是通过驱动程序提供的API函数访问硬件,虽然各硬件的访问形式有所差异,但计算机访问的机制却是相同的。
该法的要点为:在监控程序端加入用户读硬件消息机制,加消息调试机制;再使用某方法设计一个十六进制编辑器作为仿真器使用,发出这些消息,并且将这个十六进制编辑器的内容复制为你的欲调试的某硬件读缓冲区内容,这样使用该仿真器即代替了某具体硬件设备。
监控软件一端加接收消息机制,首先定义用户消息,这些消息为:某硬件传感器读到数据的消息,例如你的系统共有6路接口的硬件设备,定义6个读用户消息,消息函数功能为:将读到的硬件数据缓冲区解码,抽象化这样传感器将其视为一组缓冲区,监控软件本身就是对某硬件传感器缓冲区的加工处理,假定这个缓冲区内容已经具备,相当于你已经读到了硬件内容,仿真的方法就是构造这个你欲想得到的缓冲区内容。监控软件一端加调试支持机制,在某个用户读消息中(调试接口,例如上例中6个消息之1),加如下代码:如果调试A硬件,则复制由仿真器传来的缓冲区内容到A读入缓冲区,再发送A硬件读完成消息给你的监控程序窗口。
如果调试B硬件,则复制由仿真器传来的缓冲区内容到B读入缓冲区,再发送B硬件读完成消息给监控程序窗口等。仿真器构造这个缓冲区内容ComBuffer,并且发特定的消息给监控程序窗口,这样无需要硬件传感器本身接入,只要知道通信协议即可开发出全套监控软件。
仿真器可以使用多种方法构造:①使用串行口调试器作为仿真器[3];于使用网络调试器作为仿真器[4];③使用进程通信方法作为仿真器[5];④单进程方法[6],在监控程序中,内嵌一个单独的窗口,在该窗口内编写一个十六进制编辑器作为仿真器[7]。
第①和于方法就是开发出一套仿真硬件调试器,比如串口调试器和网络调试器等,这样在实验室内可快速调试出整套监控系统。这些调试器网络上已经有下载的程序了,或者自己写这些调试器,无论怎样,在监控程序中要写接收代码。
第③种方法为:设计一款基于进程通讯技术的综合调试器,该调试器实际是一款十六进制输入编辑器。代表一串硬件信息流,比如com2口读入的信息,再使用进程通讯技术使该调试器将这一串信息传给监控软件。在监控软件一端,程序同样要使用进程通讯技术接收由调试器发来的信息,达到仿真某硬件传感器读入信息的目的。进程通讯方法有多种形式,作者使用多种技术手段曾写出了这款综合调试器,使用多种进程通讯技术传出数据,亦使用多种内核技术通知数据的变化,效果颇佳。该法的优点是你可以深入到WINDOWS内核级编程,学习到高深的进程间通信方法[4],缺点是这一大堆内核对象技术及进程之间的通讯方法对初学者有一定难度。
第④种方法为:直接在监控软件本身内置一个仿真器,同样可以达到无硬件环境调试出全套软件的目的。
其中任一款调试器都可以作为通用调试器使用,关键部分在改造监控程序本身部分,你的监控软件需要具备调试支持功能,在任一硬件的设备读完成语句后加读完成消息机制。
首先将监控软件本身稍作改造,使其具备调试支持功能。无论具体硬件传感器是什么形式,比如是一款GPS导航设备通过串行口往计算机送出位置信息,形式化的硬件访问函数一般为几句:①设备打开;于设备读;③设备写;④设备刷新;5设备关。这些函数一般由商用板卡厂家依DLL形式提供,但串行口和网络通讯用的函数却由Windows API提供。该文重点在于调试方法,在监控程序内,设计一种通知机制,当每种硬件传感器读语句执行完成,发一用户定制的消息给主窗口,告知该主窗口由线程或者回调函数业已完成硬件信息读。在对应的消息处理函数中,完成信息解码,表示该设备读完成并且在该消息函数中加工数据。有了这样一种机制在后台工作后,假定需要调试COM12串行口,只要从什么地方能够发出COM12对应的消息就相当于COM12读到了数据。如果将调试器的输入内容作为比如com12口的读入内容,而由该调试器发这一用户消息给主窗口,主窗口分不出到底是由具体的com12口硬件设备发出或者由调试器发出,这样就达到了以假乱真的效果。
无论监控程序使用什么语言编写,无论读入时序怎样安排,为了达到仿真调试目的,将监控程序改造如下:设计若干读入完成消息,在每个硬件传感器读入函数完成后,发一用户特定的消息给前台窗口,告知该设备读已完成;读入完成消息处理为:对读入缓冲区解码,将缓冲区某某位置的十六进制码字按照通讯协议变换为监控程序使用的变量,提供给监控程序使用。设监控程序为A窗口,仿真硬件程序为B窗口。
A窗口要接收B窗口数据,并且B窗口数据变化时应立即通知给A窗口,那么问题变为:通知和复制变化数据。A窗口的调试方法:假定要调试串行口12,首先假定已经编写了com口读写线程(注意此时无硬件,com12打不开,无法跟踪[6]),假定你的监控程序已经具备了调试支持功能(用户消息),当每个硬件传感器读完成后都会发一对应的读完成信息的。那么只要在什么地方发出该消息,就相当于已经读入了该硬件数据。试设想一下,如果读入缓冲区的每一位都可控制输入,那么在实验室内就仿真了所有实际的通讯情况,将节约大量时间在设备联调阶段,因为在联调时,只有对方开机运行他或者她的程序时你才能调程序。
假定开发者设计的监控程序需要调试16个串行口,2个网络设备,4个A/D设备,48路I/O设备等等,此时假定需要的多串行口卡,A/D卡等等还没有买到,那么使用一款网络调试器来调试整个监控程序:注意只有一个输入,网络读,监控程序首先要完成网络读部分,下面介绍怎样调试串行口12,在网络读函数完成后,将网络读入的缓冲区内容复制到串行口12的读缓冲区中,网络读中再加一句代码,发送串行口12读完成消息给主窗口,这样就骗过了串行口12的读完成语句;此时,串行口12可能还不能够使用(设备未到位),但开发进度并不受影响,串行口需要的数据来自于网络调试器,通知来自于网络读消息,在网络读函数中,改造上2句代码成其他设备,将顺次调试完你所有连入系统的硬件设备。假定监控程序已经具备了上文中的调试支持功能,那么可以在实验室无硬件环境下完全调试处整套监控软件。形式化的伪代码为:
MemoryCopy(ComBuffer12,NetBuffer,Ret);//将网络缓冲区内容复制到串行口12的读缓冲区;PostMessage(窗口句柄,WM_COM12_READ,0,0);//发送串行口12读完成消息给前台窗口;},到此为止,相当于网络读到的数据已经复制给串行口12的缓冲区,发送消息表示串行口12读到了数据,将内存复制与发送消息语句改为其他缓冲区和其他消息则可以调试其他任一设备。}
硬件缓冲产生器的设计方法为:在开发控制程序时,设计一款内置的小型调试器,该调试器实际就是一个小型的十六进制编辑器,在加发送特定消息的功能。使用软件开发一个十六进制编辑器代替硬件,在这个编辑器界面上使用消息通知机制告知监控程序硬件读数据已经准备好。
下面使用Delphi展示这个调试器设计[7]。在监控软件工程文件中,设计一Form,该Form内设计两部分输入:一部分允许十六进制输入,一部分允许浮点数输入,十六进制输入使用Stringdrid组件,浮点数输入使用Edit组件即可,下面主要介绍十六进制编辑器及调试方法具体实现。
设计一StringGrid,两行256列(0~255),调整格子大小及相应组件属性:重载该StringGrid的CellEdit消息,该消息用于检查是否为十六进制输入,这样就编写了一款十六进制输入的简易编辑器,
设计一按钮组件,该按钮方法为:(界面中需要加一组RadioButton组件用于控制发送什么消息,例如COM1,COM2,…,A/D,…),依据控制开关发送不同的消息。
将十六进制的字符串格子内容Copy到某具体预调试的读入缓冲区内,发用户定制的某具体硬件传感器读已完成消息。这样监控程序就误以为读到了某具体硬件传感器数据了,而且每一位都可以编辑,按通讯协议就可以很快调试出监控程序到底编写正确与否,调试方法示意图如图3所示。
上述各仿真器给出的方法特别适合于调试通信中每一位的变化这种情况(假定从缓冲区第2子节到第12字节每一位表示不同的物理硬件设备状态,设想一下,你的程序将有80种判断要处理,10 Bytes,每字节8位),实际工程中另一种情况为浮点数的表示,浮点数常使用以下几种表示法(通信时都是一串十六进制的数据):
A:通信双方自己规定表示方式
B:直接使用计算机本身规定的方式放置数据
对A表示法,需要通信双方写置码,解码函数;对B方法,通信双方将这几个字节使用内存对齐技术引用即可,delphi语言中使用Absulute技术[8],C++语言中使用联合Unite技术[9];这样不用编写转换函数;注意Windows系统与UNIX系统放置数据通常是倒置的,高低字节调整即可;
在实际工程中,通讯中经常碰到这样一种情况,读入某些字段是一组动态数据(比如弹道曲线x、y和z),带驱动的监控软件希望由一组动态数据支持程序运行,以便测试程序整个控制过程正常否,下面介绍这样一种情形的仿真调试:假定弹道由基地中心的网络传送,网络传送字节长度为64,从第12字节开始,每4 Bytes代表一弹道数据,分别为x、y和z,低位在前,高位在后。
在仿真Form中,设计另一按钮,按钮消息为:
图3 调试方法示意图
打开某文本文件(该文件代表弹道数据,设计为文本优点在于文本文件可以灵活改变数据,便于置入异常数据测试,测试监控软件是否具备异常处理功能),读入文件后将文本中的字符串转换为浮点数分别存贮在3个数组中XA、YA和ZA中,在仿真界面上,设计一个Timer组件,间隔为100 ms,再设计一cheekbox组件,使用cheekbox设置时钟组件Timer的开或者关,重载Timer消息:当Timer开时,从数组中取一组值,数据序号设计为全局控制量integer型,每次序号加1,这样下一个Timer消息到来时正好达到数据下一组数据,当这一浮点数按通讯协议再转换为DWORD放置在发送网络设备缓冲区的第12字节开始处(这样就代表了动态x、y、z),Timer消息最后一句为PostMessage()[10];向主窗口发送网络读完成消息,这样主窗口就相当于接收到了一组动态网络数据。监控程序运行时只要在仿真界面Form中打开Timer组件开关,就完全仿真了动态数据读入过程,其他设备调试方法同理。
航空、航天和电子类实时控制软件因其特殊性,经常由几个研究单位共同开发各自的监控系统再进一步传给上一级的监控系统,这种系统可能有多级,控制系统联调是个很繁杂的工作,既费时间又要求其他分系统人员互相配合,该文提供的方法使得开发者在实验室内,使用很短时间开发出全套监控软件,为后续联试节约大量时间,因为按协议的通讯全提前解决了。如果将该类问题扩展之,任一个业务逻辑都会碰到该类调试问题,开发者使用上文的机制改造应用软件,再设计自己的调试器在应用软件内,虽然在初期写了多余的调试代码,但在后期联合调试时将节约大量的时间。
[1](美)温伯格.完美软件—对软件测试的各种幻想[M].北京:电子工业出版社,2009:56-63.
[2]RICHTER J.Window高级编程指南[M].王书洪,刘光明,译.北京:清华大学出版社,1999:236-243.
[3]赵兰涛,苏彦华.DELPHI串口通信技术与工程实践[M]. 2004:80-87.
[4]王艳平.Windows网络与通信程序设计[M].北京:人民邮电出版社,2009:153-160.
[5]JEFFREY J,CHRISTOPHE N.Windows核心编程[M].葛子昂,周靖,廖敏,译.北京:清华大学出版社,2008:270-276
[6]吴天准.Delphi 7程序设计技巧与实例[M].北京:中国铁道出版社,2003:77-82.
[7]刘山,赵辉.Delphi系统开发实例精粹[M].北京:人民邮电出版社,2005:172-175.
[8]梁冰,李钟尉,吕双.Delphi技术方案宝典[M].北京:人民邮电出版社,2008:260-264.
[9]谭浩强.C程序设计[M].北京:清华大学出版社,2005: 153-160.
[10]范文庆,周彬彬,安靖.精通Windows API--函数接口编程实例[M].北京:人民邮电出版社,2009:223-250.
Rapid Debugging and Development of Real-time Monitoring Program in Lab
CAI Wen-zhai
(The 39th Research Institute of CETC,Xi’an Shaanxi 710065,China)
This paper proposes the several simulation and debugging methods of real-time monitoring application software development in Telemetry,Track and command(TT&C)project,and mainly introduces a window debugging method embedded in the monitoring program.This method uses an independent hexadecimal edit window message mode to replace a hardware sensor accessed to the computer,completely simulates the hardware communication environment in the lab,and flexibly gives the fixed length information send by the hardware sensor to the computer according to protocols,in order to debug the whole monitoring system without hardware. Once the hardware components are connected,the communication at the protocol level is immediately completed.
complex control system;simulation debugging;TT&C project;threading;event
TP39
A
1008-1739(2015)02-58-5
定稿日期:2014-12-26