• <option id="gtlqy"></option>
    <code id="gtlqy"></code>
    <ins id="gtlqy"><mark id="gtlqy"></mark></ins>
    1. <div id="gtlqy"><tt id="gtlqy"><span id="gtlqy"></span></tt></div>
    2. <xmp id="gtlqy"><ruby id="gtlqy"></ruby>
    3.  注册名:

      密码:

      个人注册

      企业注册

      商务申请

      商务管理平台

      企业管理平台

      个人管理平台

      我的工控博客

      中国工控网www.www.qqigying.com

      首页 | 新闻中心 | 工控论坛 | 经验视点 | 工控商务 | 电气手册 | 工控博客 | 招聘求职 | 网上调查 | 企业中心 | 供求信息 | 资料中心 | 工控书店

      所在位置:工控博客苑 -- 运动控制系统 -- 多类型运动控制卡编程方法探讨

      中国工控网搜索:

      钟天玉先生

           学历:大学本科
           职称:工程师
           年龄:35岁
             新闻信息(7/2)
             工作图片(0)
             技术论文(2/7)
             交流论坛(19/19)
             留言信箱(4)
             浏览人次:7966
             给我发消息
       我的新闻推荐 更多..
      发表人:zhong2010 发表时间:2010-5-9 21:10:00

       

      发表新论题

       本栏论题: 多类型运动控制卡编程方法探讨  [4331]
          多类型运动控制卡编程方法探讨
         
         
          运动控制卡发展越来越讯速,不同类型的控制卡亦多种多样,使软件项目经理具备越来越灵活的方案选择。而对于软件开人员,对不同的类型卡的性能测试工作无疑也越来越麻烦,通常各类型的控制卡其驱动库函数各不一样,都需要用户自己进行整理封装。本文的目的就是通过C++方式编程,探讨一下实现多类型卡编程方式,以供开发人员参考。
         
          一、利用C++虚拟函数机制
          除了手动去单个修改替换以前卡的驱动函数之外,此方法最易被C++程序员所想起,其方法是,首先需要建立一个通用的基类(父),然后不同卡封装的类通过重写基类的虚拟函数来实现,代码看上去大致如下:
          class CDviece//用户根据自己的设置建立的基类
          {
          public:
          virtual int InitBoard(); //在此仅以初始化函数为例
          … (略)
          };
         
          class CDmc1000Card: public CDviece // 设该卡为雷赛的DMC1000卡
          {
          public:
          virtual int InitBoard()
          {
          return dmc1000_init_board();
          }//改进基类的InitBoard函数
          …(其它改写略去)
          }
         
          class COMS: public CDviece //设该卡为美国的OMS卡
          {
          public:
          virtual int InitBoard()
          {
         
          }
          …(其它改写略去)
          }
         
          在程序中,若想设备使用DMC1000控制卡,可定义如下:
          CDviece *pMineDviece = new CDmc1000Card;
          改为OMS控制卡则一样:
          CDviece *pMineDviece = new COMS;
          而其它代码调用InitBoard函数可以不去改动,照常使用:
          if( pMineDviece->InitBoard() )
          {
          …(Do s.th)
          }
         
          使用此方法,需要根据当前设备配置情况,完整的写好CDviece的所有函数,同样,从CDviece派生的控制卡类,也需要将父类虚拟函数全部改写完毕,对函数返回值,参数都需要进行规范,同时,修改完成之后,将整个软件工程全部编译一次。
          利用虚拟函数方法,会带来虚拟函数表的成本开销,随着CDivece需要的函数增加,其成本会相应的增加,事实上,MFC的消息机制就是以代码的方法实现了虚拟函数的机制,只不过虚拟函数的处理是通过C++编译器来完成的。
          并且,CDviece的需求发生变化时,其派生类的函数相应的也要发生变化,这一点是程序员需要注意的。
         
          二、利用DLL动态库实现
          从COM组件编程过来的人,很容易想到DLL的实现方案。看重这一点是的只要主程序框架写得正确,改变DLL即可实现主程序不编译,即可获得不同类型卡的选择。
          事实上,这是一种美好的愿望,要实现起来并不容易,而且很需要程序员有熬夜的精神。大致伪代码实现如下:
         
          class CDviece
          {
          private:
          HANDLE dllHandle;
          public:
          typedef int( *P_InitBoard)(void );
          P_InitBoard InitBoard;
          …(其它所有定义及声明略去)
         
          int InitFunction( char *dllFileName )//调用DLL文件
          {
          dllHandle = LoadLibaray( dllFileName );
          InitBoard = (P_InitBoard)FindFunction(dllHandle, “Init_Board”);
          … (其它略去)
          }
          }
          由于不同卡的函数名都不一样,故需要程序员按照CDviece所需函数进行另一DLL的编写,若需要DMC1000控制卡时,则需要生成一个MDMC1000.dll如下:
         
          int InitBoard()
          {
          return dmc1000_board_init();
          }
          …(其它略去)
         
          生成OMS控制卡的MOMS.dll如法炮制:
          int InitBoard()
          {
          }
          …(其它略去)
         
          在代码中调用DMC1000控制卡,使用如下:
          CDviece mineDviece;
          mineDviece.LoadLibaray(“Mdmc1000.dll”);
          if( mineDviece.InitBoard() )
          {
          …(Do s.th)
          }
          使用OMS控制卡如下:
          mineDviece.LoadLibaray(“Moms.dll”);
          …(其它略去)
         
          看似简单,实质上略去的部分将是程序员的一场恶梦,想一想那一大堆的定义和声明,一碰到CDviece的变动,哪怕是最小的函数返回值或参数变动,则其它相应的所有DLL都需跟全部编译。这无疑给软件项目的整个维护带来极大的难度。
         
          三、利用模板类实现
          探讨到现在,本人比较推荐的就是使用此方法,它较虚拟函数相比无额外成本的开销,更不有因为虚拟函数带来的效率问题。
          与DLL方法相比,定义声明,及变动性都非常良好,整个维护的成本也较低。
          其编程特点即是,通过模板定义一个空壳类,然后根据需要可以邦定不同类型的控制卡。其伪代码实现方法如下:
         
          //定义一个空壳类
          template
          class CDviece: public CARD
          {
          public:
          CDviece(){}
          ~CDviece(){}
          }//简单吧,了无秘密可言
         
          以下定义DMC1000封装类:
          class CDmc1000Card //无需继承
          {
          public:
          int InitBoard( void )
          {
          return dmc1000_board_init();
          }
          …(其它略去)
          }
         
          以下定义OMS封装类:
          class COMS
          {
          public:
          int InitBoard( void )
          {
          }
          }
         
          在程序中应用时,调用DMC1000控制卡如下:
         
          typedef CDviece DEVIECE;
          DEVIECE mineDviece;
          if( mineDviece.InitBoard() )
          {
          …(Do s.th)
          }
          当然,DEVIECE的定义也可以如下形式:
          class DEVIECE: public CDviece
          {
          public:
          DEVIECE(){}
          ~DEVIECE(){}
          }
          调用OMS控制卡如下:
          typedef CDvieceDEVIECE;
          …(其它同上)
         
          可以看到,此方法还是让人感到兴奋的。即使参数或声明发生变化或忘记定义,那就让编译器来查错吧!
          顺带提一下,由于控制卡封装时,总有一些数据结构是通用的,对此解决方法也很简单,实现如下:
          struct tag_CARD
          {
          …(定义通用数据,如每转脉冲数,最大速度值,行程范围等等之类)
          }
          再改变一下CDmc1000Card如下形式:
          class CDmc1000Card: public tag_CARD //其它不变,OMS的定义同理
         
          四、设立一个卡类型变量
          此方法最为简单,缺点是需要同时链接全部的控制卡驱动库函数,且在程序安装时,还需要考虑各种控制卡的驱动程序或其相应的动态库是否存在。其伪代码形式下如:
          enum{ NOCARD=0,DMC1000=1, OMS=2 …};
          class CCtrlCard
          {
          public:
          int m_nCardType;//记录控制卡类型变量
         
          CCtrlCard():NOCARD(0){}
          ~CCtrlCard(){}
         
          int InitBoard( int nCardType )
          {
          m_nCardType = nCardType;
          switch( nCardType ){
          case DMC1000:
          if( d1000_board_init() <= 0 )
          m_nCardType = NOCARD;//初始化失败
          else{
          }
          break;
          case OMS:
          …
          break;
          default:
          m_nCardType = NOCARD;
          }
          return m_nCardType;
          }
          //其它省略
          };
         
          调用时伪代码形式如下:
          CCtrlCard card;
          if( card.InitBoard( DMC1000 ) != DMC1000 )
          //初始化失败
          else
          //找到控制卡
         
         
       

      以下是关于《多类型运动控制卡编程方法探讨》论题的回复(共1篇)

      回复人:chenwuhan

       回复时间:2013-5-8 22:47:00

          顶得住

      如果要回复本栏论题,请首先登陆网站

      ·如果你已经是中国工控网www.www.qqigying.com成员,请直接登录。

      ·如果你还不是中国工控网www.www.qqigying.com成员,请首先注册,注册为免费!

      注册名:

      密  码:

                 注册中国工控网www.www.qqigying.com
                 忘记密码
       
           相关技术论文:

      关于我们     免责声明     服务项目     广告联系     友情链接     联系方式     意见反馈     设为首页     加入收藏

       ©2016-2018 中国工控网(www.www.qqigying.com) 版权所有 豫ICP备17046657号

      管理员信箱:chinakong98@163.com  服务热线:13525974529  办公电话:0379-65185929  传真:0379-65185928

      洛阳博德工控自动化技术有限公司

      中国    洛阳

      亚博提现流水 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>