|
|
抽像一点讲,过程控制渗透在生活的各个角落。特别是在数控行业,尤为明显。早期在PLC时代,几乎是一统天下。当大小不一的控制卡公司如雨后春笋般成长起来时,控制卡在过程控制逐步体现出强劲优势。 其编程手段往往邦定非常成熟的编程工具,如:CB,VC,Dephi,CB。故其推广非常迅速. 很快拥有大量客户群。 但是,作为编程者,碰到同一程序需要控制多个同样设备时(动作不一定同步),往往在Window多任务系统的影响下,很快想到多线程技术,其实多线程编程对系统依赖性较强,不同级别的处理,将导致程序的维护成本增加,并且还需要考虑线程之间的通讯,使编程起来较为麻烦。事实上,依靠过程编程的思想,会使程序获得更简单的做法。 纯粹从编程角度来看,过程控制编程应包含几个要素,下面以C++伪码方式来表示一个类,较易说明问题:
/************************** 一个动作封装类,包含一个 设备的所有执行动作 **************************/ class CAction { public: CAction():m_nWorkStep(-1000){} ~CAction(){} public: enum{ None, Inital, Start, Stop, Pause, Continue };//部分控制标记
public: int Control( int nStatus, void *pParam ); //要素2: 一定可以接受外部控制 int Run( void *pParam ); //要素3: 绝对有一个不断推动的执行过程(这是整个过程编程的心脏所在)
public: int m_nWorkStep; //要素1: 必须有一个工作执行步 private: void * m_pMemberData; //要素4: 可选,邦定被操作的数据 // ..其它辅助变量 };
要素5:可选,为了能与外界用户进行沟通,Control函数与Run函数,须选择一个参数,满足用户的输入输出。但由于用户可选项太多,故古人告诉我们,万事皆空即是成功,对于C++而言,没有比void *类型更有前途了(若想体会,需搭配类型转换更有潜力)。早在一年前,本人写过一个过程控制器编程,并有成功实例,但今次版本,更有精装之特点。
住下再参见一下Control函数,及Run函数的一个小样例,这将是程序员发挥强劲功能的场地所在。如下:
int CAction::Control( int nStatus, void *pParam ) {//此处的设计需要一点技巧,当然完全取决程序员的经验,和对控制的理解 switch( nStatus ){ case Inital: m_pMemberData = pParam;//初始化邦定的用户数据 break; case Start: m_nWorkStep = 0; //一般令第0步作为开始较易理解 break; case Stop: m_nWorkStep = -1000;//停止 break; case …//其它略去 default: break; } return m_nWorkStep;//返回值可自定 }
int CAction::Run( void *pParam ) {//以下为一个动作不断返回,直至接受到停止指令 switch( m_nWorkStep ){ case 0: if( IsMove() ) break; //正在忙,不执行 Move(1600); //正向移动1600单位 m_nWorkStep++; //跳至下一步 break; case 1: if( IsMove() ) break; //正在忙,不执行 Move(-1600); //反向移动1600单位 m_nWorkStep=0; //再回至第0步 break; case –1000: break;//停止 default: break;//此句最好有,以便于理解 } return m_nWorkStep; //返回值可自定 } 对于Run函数须谨记一点:不要有长时间的循环操作,更不要有死循环,否则另外设备无法正确动作,因为另外的设备Run函数无法被激活执行,心脏无法跳动,只好等死吧! 当然,还须担心一点:多个设备同时执行时,其实时性会下降一点,若没有特别高的要求,在现今CPU狂奔的时代,以上程序框架足已满足90%的需求,还是有学习和理解的必要吧!
以上的框架出来了,那么如何操作使设备驱动起来呢,不管在DOS亦或在Window系统环境里,以下的思路都一样,参见伪代码如下:
const int nSize=10; //定义10台设备对象 CAction exeArray[nSize]; BOOL bRunning=FALSE;//控制整个驱动的标志
Void OnRunAction()//启动函数 { //初始化一下 for( int i(0); i〈nSize; i++) exeArray[i].Control( CAction::Inital, ( void *)userData );//userData由用户选择
bRunning = true;//外部控制变量 for( i=0; bRunning; i=(i+1)%nSize)//给予运行时间,即是驱动了 { exeArray[i].Run(( void *)userData); //不断驱动Action设备(即激活心脏) DoEvents();//做其它事情,如系统消息检测,以防止死机 } }
DoEvents函数功能的详解可参见本人的〈〈DMC1000控制卡不能响应系统消息〉〉,上面有不同编程工具下的实现源代码。
void OnControlAction() { for( int i(0); i〈 nSize; i++) exeArray[i].Control( Caction::(/*用户想要的动作*/), ( void *)userData); }
void OnOver() { bRunning = FALSE;//结束驱动 }
注意:有很多程序员在不同编译器下,需要不同的OnRunAction函数版本,以上实现最为简单,但有一些较特殊。比如:在程序启动时,就驱动所有设备,这点本人在VC6.0环境有过经验,可以分享一下,其它环境下,还需同胞们一起去努力发现。
还有一点声明,多线程技术也不是一无是处,在花费时间较频繁的通讯编程方面,它的优势,还是有相当的诱惑力。
|
|
状 态:
离线
公司简介
产品目录
|
|
公司名称:
|
深圳市雷赛智能控制股份有限公司
|
联 系 人: |
梁邦敏
|
电 话: |
755-26401178
|
传 真: |
|
地 址: |
深圳市南山区登良路天安南油工业区2栋3楼 |
邮 编: |
518000 |
主 页: |
|
|
|
|
|