注册名:

密码:

个人注册

企业注册

商务申请

商务管理平台

企业管理平台

个人管理平台

我的工控博客

中国工控网www.chinakong.com

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

所在位置:工控博客苑 -- 运动控制系统 -- 四个编程问题,请稍加留意

中国工控网搜索:

钟天玉先生

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

 

发表新论题

 本栏论题: 四个编程问题,请稍加留意  [5008]
    四个编程问题,请稍加留意
   
    No.1 一个由VB编译引起的错误
    在VB编译环境下,常有这样种事情发生,第一次初始化控制卡时,往往正常通过,若中途中断或意外退出,则再次启动程序,则初始化时却找不到控制卡了,有时弄得人很郁闷,一点成熟感都没有,在没有别的招的情况下,搞得程序员一怒之下重启PC才得以好转。然事情却很让人不开心。
    这个问题是由VB编译引起的,由于VB是一种解释语言,其程序运行时被加载的速度不够快,故会把程序调用的动态库等资源暂放置内存,直到VB整个软件结束才会释放。而在调试控制卡软件时,由于中途中断或调试意外退出,没有执行到控制卡关闭函数,则控制卡资源还未被释放,故程序再次运行初始化控制卡资源时,则找不到有效的资源了,因而也找不到控制卡了。
    解决问题很简单,关闭整个VB编译器软件,以释放所有资源,再次进入即可。此过程稍为麻烦,但比上重启PC来讲,还是稍有效率一些。
   
   
    No.2 取位运算
    在使用控制卡编程时,常常碰到取位运算的案例,如下面函数:
    d3000_get_axis_status
    在其《软件手册》上有对其返回值的每一位进行了详细说明,即使这样,有些新手面对具体编程时,一时还转不过弯过来。如:要从返回值内判断原点信号的高低电平状态到底该怎样编程呢,以下列出在C/C++、Basic取位运算的代码片段,其它状态位类同:
    (注:DMC3000控制卡的原点信号在d3000_get_axis_status的返回值第9位,从0位开始数)
   
    1、 C/C++
    DWORD nStatus = d3000_get_axis_status( XCH );//读取X轴的专用输入信号
    //XCH的值为0
   
    if( (nStatus&(1<<9)) != 0 )
    //高电平或低电平
    else
    //低电平或高电平
   
    (用移位方法在《控制卡编程几招》中有介绍)
   
    2、 Basic
   
    Dim nStatus as long
    nStatus = d3000_get_axis_status ( XCH ) ‘读取X轴的专用输入信号
   
    if (nStatus and &H200) <> 0 then
    //高电平或低电平
    else
    //低电平或高电平
    end if
   
    注意:第9位为1时的十六进制数值为0x200
   
   
   
    No.3 关于大数平方和平方根溢出的解决方法
    平方和平方根的计算常常遇到,一般都会用浮点数来表示,当计算大数时,由于电脑内部定义的数据类型字节宽有限,总会有溢的可能,如:
   
    double kx = 1000000.0; //一个double在VC++中为64位,在DOS环境下为32位
    double ky = 1000000.0;
    double len = sqrt( kx * kx + ky * ky );//求两者的平方和之根
   
    想必上面的表达算式大家都见怪不怪了吧,但很容易溢出哦,要是多次系数,就更容易了,那么到底该如何解决这个问题呢?我们改一下表达算法,也可达到同样效果,可将溢出的机率大大降低,请看:
   
    double kx = 1000000.0;
    double ky = 1000000.0;
   
    ky = (ky/kx); //注意变化,实际应用时,要避免kx=0.0
   
    double len = kx * sqrt( 1 + ky * ky );
    //想一想,若kx,ky的数值有效,那么len的值也不会溢出了
   
    No.4 精确定时器的实现(仅用在VC++)
    MFC提供的定时器OnTimer,虽然可以通过SetTimer设定响应时间间隔,但无论怎样都不能超过每少20次的调用频率,在一些需要精确计时的场合当然就不适合了。API提供一个性能较好的函数GetTickCount,这个函数理论上可以跑到毫秒级,但是它的时间积累误差很大,而且不可以得到更精确的计时。
    在《Windows图形编程》一书当中有封装好的一个精确计时类,可以根据CPU的时钟周期来计时,够酷吧,然此书有很多人暂未购得,故由本人做一做义务,公布其主要的核心片段,也足够大家用了,具体大家再根据需要去完善吧。
   
    typedef __int64 I64; //一个64位整数类型的定义
   
    I64 GetQueryCount()
    {//返回当前时钟周期,若不明白以下语法,就不明白,反正能用就行,在NT下也正常
    _asm _emit 0x0F
    _asm _emit 0x31
    }
   
   
    //取得1秒中的周期计数值
    I64 start = GetQueryCount ();
    Sleep(1000);
    I64 stop = GetQueryCount ();
    //转化成1微秒的计数值,可根据需要进行,我在一个软件当中使用1微秒就够了
    //单位关系:1秒=1000毫秒=1000000微秒
    long double fUnit = (long double)(stop-start)*0.000001;//取得1微秒的时种周期值
   
    若你想要达到100微秒中断一次,则可以写出下面程序:
   
    I64 nTimers = I64( fUnit * 100 );//将100再转化周期值
    I64 nStart = GetQueryCount();
    I64 nEnd = nStart;
   
    While( 你的有效循环条件 )
    {
    nEnd = GetQueryCount();
    if( labs(nEnd – nStart) >= nTimers )
    {
    …做你想做的事情,记得你要作的事情不要太复杂,以致于运行的周期超过自己定义的中断间隔周期。
   
    nEnd = nStart;
    }
    else
    ::DoEvents();//此函数在我的相关文章有详解,故不赘述
    }
   
   
 

以下是关于《四个编程问题,请稍加留意》论题的回复(共1篇)

回复人:zkp345

 回复时间:2012-5-4 9:34:00

    好

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

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

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

注册名:

密  码:

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

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

 ©2021-2022 中国工控网(www.chinakong.com) 版权所有 豫ICP备17046657号

管理员信箱:chinakong98@163.com  服务热线:13525974529

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

中国    洛阳