| DMC1000控制卡不能响应系统消息 
 一、问题现象及分析
 问题经常通过以下编程表现出来:
 
 //X发出脉冲后,等待脉冲发完后再做其它事情
 d1000_start_t_move( 0, 6400, 3200, 6400, 0.1 );
 while( d1000_check_done(0) == 0 );
 
 老版本的库函数如下:
 
 d1000_start_tr_move( 0, 6400, 3200, 6400, 0.1 );
 while( d1000_check_done(0) == 0 );
 
 或者:
 d1000_wait_done( 0 );
 此函数内部实际上包含类似于while( d1000_check_done(0) == 0 );的语句
 
 以上可以看出,在检测脉冲是否发完时,此段代码的执行完全独占了CPU分配给当前进程的所有时间,
 因而也排挤了其它消息的响应,当然也就不能响应定时器读取位置,或其它停止操作等.
 
 二、解决方法
 解决此问题关键是让while循环时能检测系统消息,以下分别介绍在VB,VC,CB下的解决措施:
 
 注:以下编程全以DMC1000最新的驱动库函为参考
 
 1.VB编程
 d1000_start_t_move 0, 6400, 3200, 6400, 0.1
 DO
 DoEvents
 LOOP WHILE (d1000_check_done(0) = 0)
 
 2.VC编程
 在VC下编程关键是要解决类似于VB的DoEvnets函数
 
 void DoEvents()
 {
 static MSG msg;
 if( ::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) ){
 ::TranslateMessage( &msg );
 ::DispatchMessage( &msg );
 }
 }
 
 然后编程如下:
 
 d1000_start_t_move( 0, 6400, 3200, 6400, 0.1 );
 while( d1000_check_done(0) == 0 )
 ::DoEvents();
 
 3.CB编程
 同样也需要完成一个DoEvents函数的定义:
 void DoEvents()
 {
 Application->ProcessMessages();//VCL给程序带来极大简化
 }
 编程如下:
 d1000_start_t_move( 0, 6400, 3200, 6400, 0.1 );
 while( d1000_check_done(0) == 0 )
 ::DoEvents();
 
 三、技巧提升
 有了自产的DoEvents函数,是否就可以一切OK了呢。试想一个问题,实际加工时,
 通常会有大量的小线段(即短脉冲距离)出现,若频繁的调用DoEvents势必带来新的麻烦,因为加工
 需要连续的进行,设备的运动之间停顿时间过长,会形成设备的多次启停,进而易产生振动,造成
 设备的加速磨损,并且速度也快不起来。因此添加一小小技巧(实用又省钱),判断脉冲距离是否过小
 若过小则不执行DoEvents函数,过小量可以根据自己的需求也定义一个参考量。当然程序的执行顺序也
 可以优化一下,以上面程序为例:
 if( d1000_check_done(0) != 0 ) return;
 d1000_start_t_move( 0, 6400, 3200, 6400, 0.1);
 咋一看没有什么特别的,但是请看下加工程序的部分简化代码,也许会有新的启示:
 
 for( int i(0); i
 {
 
 if( d1000_check_done(0) == 0 )
 {
 if( Len > 2.0 )DoEvents();
 //小于2单位(可以指为毫米,或其它单位)则不执行DoEvents函数
 continue;
 }
 Len = dist[i].Len;
 d1000_start_t_move( 0, dist[i], speed );
 i ++;
 }
 当然,世界上做事情的方法多的是,有高手则愿意动用复杂的多任务编程方法来完成操作,
 最后经过努力,事情也可以解决,若有兴趣,可参见另一篇《控制卡的多任务编程》,然后自行做
 编程测试。不过本人的理论是,解决事情的方法越简单越好,据本人了解,大师之所以为大师,通常
 不是把问题搞得高深莫测,而是通俗易懂。
 
 四、其它应用
 此方法对所有DMC系列的控制卡的编程都可以运用,还可用在自定义的Arc(圆弧运动)函数
 上,参见下面伪代码(Arc的直线拟合算法参见DMC2000的ARC算法):
 
 for( int i(0); i
 {
 while( IsRunning(X) || IsRunning(Y) )
 {
 if( i%16 == 0 ) DoEvents();//每16再运行一次
 }
 start_line2( newx, newy );
 }
 
 
 |