|  |  | 
| 
|  | 发表人:zhong2010 | 发表时间:2010/5/9 21:13:00 |   |  发表新论题
 |  
| 过程控制编程之简要探讨 
 抽像一点讲,过程控制渗透在生活的各个角落。特别是在数控行业,尤为明显。早期在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函数版本,以上实现最为简单,但有一些较特殊。比如:在程序启动时
 |  |  
| 以下是关于《过程控制编程之简要探讨》论题的回复(共2篇) |  
| 
|  | 回复人:delphia |  回复时间:2010/5/27 20:13:00 |  |  |  |  
| 
|  | 回复人:ma5062 |  回复时间:2010/6/29 22:07:00 |  |  |  |  
| 
|  相关博客新闻: |  |  
| 
|  相关技术论坛: |  |  
| 
|  相关技术论文: |  |  |