如何进行精确的定时操作

prefertocb 2000-08-10 10:34:00
我的一个数据采集程序要求精确进行A/D转换,(不可用Timer)
...全文
352 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Winsky 2001-02-20
  • 打赏
  • 举报
回复

我支持死不了的观点,以前写的一个小游戏就是用的TimeGetTime和空闲处理做的,计时精度确实可以达到1ms,如果使用TTimer则只有53ms(18.6Hz)的计时精度。

不知道Raptor(猛禽)是否有好的实现方法或者思路,给大家讲讲好吗?

Un1 2001-02-17
  • 打赏
  • 举报
回复
http://www.banasoft.com/DownLoad/BNTimer.exe
猛禽 2001-02-17
  • 打赏
  • 举报
回复
如果用于工控,用WINDOWS本身的方法精度都不够,建议写一个VXD(95/98)/WDM(NT/2000),直接对8253(4)定时芯片编程才可以.其精度可到:55ms的65536分之一.
NowCan 2000-08-26
  • 打赏
  • 举报
回复
小于1毫秒是不可能的.还是用单片机吧.
shines77 2000-08-21
  • 打赏
  • 举报
回复
收集
springsea 2000-08-20
  • 打赏
  • 举报
回复
windows的定时器取自硬件晶振,不可能精确的很,只能精确到55ms左右吧!
「已注销」 2000-08-12
  • 打赏
  • 举报
回复
虽然Win95下可视化开发工具如VC、Delphi、C++ Builder等都有专用的定时器控件Timer,而且使用很方便,可以实现一定的定时功能,但最小计时精度仅为55ms,且定时器消息在多任务操作系统中的优先级很低,不能得到及时响应,往往不能满足实时控制环境下的应用。不过Microsoft公司在Win32 API函数库中已经为用户提供了一组用于高精度计时的底层函数,如果用户使用得当,计时精度可到1ms。这个计时精度、对于一般的实时系统控制完全可以满足要求。现将由C++ Builder 4.0提供的重新封装后的一组与时间相关的主要接口函数(函数名、参数、功能与Win32 API基本相同)说明如下:
  1.DWORD timeGetTime(void)
  返回从Windows启动开始经过的毫秒数。最大值为232,约49.71天。
  2.MMRESULT timeSetEvent(
  UINT uDelay,
  UINT uResolution,
  LPTIMECALLBACK lpTimeProc,
  DWORD dwUser,
  UINT fuEvent
   )
  该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数,成功后返回事件的标识符代码,否则返回NULL。参数说明如下:
  uDelay:以毫秒指定事件的周期。
  UResolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
  LpTimeProc:指向一个回调函数。
  DwUser:存放用户提供的回调数据。
  FuEvent:指定定时器事件类型:
  TIME_ONESHOT:uDelay毫秒后只产生一次事件
  TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。
  3.MMRESULT timeKillEvent(UINT uTimerID)
  该函数取消一个指定的定时器回调事件。uTimerID标识要取消的事件(由timeSetEvent函数返回的标识符)。如果成功则返回TIMERR_NOERROR,如果定时器时间不存在则返回MMSYSERR_INVALPARAM。
  void CALLBACK TimeProc(
  UINT uID,
  UINT uMsg,
  DWORD dwUser,
  DWORD dw1,
  DWORD dw2
   );
  该函数是一个应用程序定义的回调函数,出现定时器事件时该函数被调用。TimeProc是应用程序定义的函数名的占位符。使用该函数时要注意的是,它只能调用以下有限的几组API函数:PostMessage,timeGetSystemTime, timeGetTime, timeSetEvent,timeKillEvent,midiOutShortMsg, midiOutLongMsg,OutputDebugString。同时也不要使用完成时间很长的API函数,程序尽可能简短。
  使用以上一组函数就可以完成毫秒级精度的计时和控制(在C++ Builder中使用时要将头文件mmsystem.h加到程序中)。由于将定时控制精确到几毫秒,定时器事件将占用大量的CPU时间和系统资源,所以在满足控制要求的前提下,应尽量将参数uResolution的数值增大。而且定时器实时控制功能完成后要尽快释放。
wolfop 2000-08-11
  • 打赏
  • 举报
回复
Timer进行定时的精度是无法保证的, 所谓的1ms往往无法达到.
prefertocb 2000-08-11
  • 打赏
  • 举报
回复
Dinkar:
谢谢您的帖子。我在CB5下用此程序编译出错:
E2206 lllegal character ' '(0xa1a1)
其中定义的变量均有以上错误。而且,奇怪的是回调函数TimerCallProc中的参数您未指定。
请帮忙到底。先行道谢。
「已注销」 2000-08-10
  • 打赏
  • 举报
回复
在工业控制软件中,数据采集和实时控制是经常性的工作。目前,工业控制软件已经从DOS和Windows3.x平台,转到了Windows95上。然而,Windows95并不能直接支持中断,这就意味着在DOS和Windows3.x中的定时器中断不能为我们所用。因此,我们必须寻求新的定时方式。

---- 在C++ Builder和Delphi等典型的编程语言中,都提供了定时器控件,可以方便地实现定时和事件响应。此外,Windows95还提供了SetTimer和KillTimer函数来设置和删除一个定时器,在事件WM_TIMER响应函数中实现处理。然而,遗憾的是,通过这些方式获得的Win95定时器最小只能精确到55毫秒,对于55毫秒以下的时间精度便无能为力。这对于Win95下测控软件的开发是十分不利的。幸运的是,多媒体定时器可以解决这一难题。

---- 以下是一个完整的多媒体定时器设计示例程序,该定时器的精度为1毫秒。该程序的内容十分简单:按下按钮1,启动定时器,在Edit框中显示定时值(计数值),按下按钮2则将关闭定时器。此程序在Windows95环境下,采用C++Builder3.0编程并编译通过,但设计思想同样适用于其它高级语言。按照本程序中的实现方法,读者将可以轻松实现自己的高精度定时器。

---- 程序清单如下:

#include < vcl.h >
#pragma hdrstop

#include "mmsystem.h"  //包含多媒体定时器函数的头文件
#define MilliSecond 1 //定时间隔1毫秒
#define Accuracy   1 //系统允许的分辨率最小值

#define Min(x,y) ((x < y) ? x : y)
#define Max(x,y) ((x > y) ? x : y)

#include "HighTimerU.h"
//------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
UINT TimerID;  //定义定时器句柄
int count;    //定义一个变量以进行计数
int TimerAccuracy;
TForm1 *Form1;
//------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}

void PASCAL TimerCallProc(UINT 
TimerID, UINT msg,DWORD dwUser,
      DWORD dwa,DWORD dwb) 
//定义定时器事件的调用函数
{
  count++;
  Form1- >Edit1->Text=count; 
//在一个编辑框内显示计数值,即定时值
}

//---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TIMECAPS timecaps;
  int TimerResolution;

//从系统获得关于定时器服务能力的信息,
//分辨率不能超出系统许可值(1到16毫秒)
 if (timeGetDevCaps(&timecaps,sizeof(
TIMECAPS))==TIMERR_NOERROR)
   TimerAccuracy=Min(Max(timecaps.wPeriodMin,
Accuracy),timecaps.wPeriodMax);

  timeBeginPeriod(TimerAccuracy); 
//设置定时器分辨率
 
  TimerResolution=1;  //设置定时间隔为1毫秒

  //产生间隔1毫秒,周期执行的定时器事件;启动定时器
  TimerID = timeSetEvent(TimerResolution,
TimerAccuracy,&TimerCallProc,1,TIME_PERIODIC);
}
//-----------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  timeKillEvent(TimerID);    //删除定时器事件
  timeEndPeriod(TimerAccuracy); //清除定时器分辨率
}
 

---- 多媒体定时器对实现高精度定时是很理想的工具,而且其精度是十分可靠的。但是,多媒体定时器也并不是完美的。因为它可靠的精度是建立在对系统资源的消耗之上的。因此,在利用多媒体定时器完成工作的同时,必须注意以下几点:

---- 1. 多媒体定时器的设置分辨率不能超出系统许可范围。

---- 2. 在使用完定时器以后,一定要及时删除定时器及其分辨率,否则系统会越来越慢。

---- 3. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结束之前,注意一定不能再次启动该定时器,不然将迅速造成死机。

13,822

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧