vb中的定时器精度有多高???

时间:2021-10-29 20:24:03
我的激光测量系统100毫秒取一次数据,太慢,如何提高速度定时一定要准确

38 个解决方案

#1


该回复于2009-06-08 14:09:31被版主删除

#2


十八分之一秒

#3


摘自MSDN的解释:
使用 Timer 控件
Timer 控件响应时间的流逝。它们独立于用户,编程后可用来在一定的时间间隔执行操作。此控件的一个一般用处是检查系统时钟,判断是否该执行某项任务。对于其它后台处理, Timer 控件也非常有用。
每个 Timer 控件都有 Interval 属性,指定定时器事件之间的毫秒数。除非禁止此属性,否则定时器在大致相等的时间间隔不断接受事件(称作定时器事件会更贴切)。
在为 Timer 控件编程时应考虑对 Interval 属性的几条限制: 
如果应用程序或其它应用程序正在进行对系统要求很高的操作─ 例如长循环、高强度的计算或者正在访问驱动器、网络或端口─ 则应用程序定时器事件的间隔可能比 Interval 属性指定的间隔长。
间隔的取值可在 0 到 64,767 之间(包括这两个数值),这意味着即使是最长的间隔也不比一分钟长多少(大约 64.8 秒)。
间隔并不一定十分准确。要保证间隔准确,应在需要时才让定时器检查系统时钟,而不在内部追踪积聚的时间。
系统每秒生成 18 个时钟信号─ 所以即使用毫秒衡量 Interval 属性,间隔实际的精确度不会超过 18 分之一秒。
 

#4


以下文字来自MSDN Programmer's Guide:

The system generates 18 clock ticks per second — so even though the Interval property is measured in milliseconds, the true precision of an interval is no more than one-eighteenth of a second. 

#5


补充一点,Timer 控件的实际间隔时间是Timer 控件Interval 属性设置的时间 + 在Timer 事件中代码执行的时间(它与系统和机器的硬件环境有很大关系. 所以要保证间隔准确,应在需要时才让定时器检查系统时钟,而不在内部追踪积聚的时间。

#6


问题在于你的timer里的代码能在1000/18秒内完成吗?

#7


学习下

#8


你可以用多媒体时钟,那个能精确到1ms

#9



不要用定时器了,可以用 API 实现高精度时钟:

Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long


Public Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

第一个函数是测量系统时钟的。以便计算延时所需的时钟周期数。

第二个用来返回系统运行的时钟数。可以用来延时。

这两个函数都涉及到大整数。

#10


Timer 的分辨率是 1ms。但是精度就很难说了,它受到多任务时间分配的影响。一般来说,精度好于 10 ms。

#11


引用 9 楼 of123 的回复:
不要用定时器了,可以用 API 实现高精度时钟:

Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long


Public Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

第一个函数是测量系统时钟的。以便计算延时所需的时钟周期数。

第二个用来返回系统运行的时钟数。可以用来延时。

这两个函数都涉及到大整数。


同意!具体用法我这儿有:  http://blog.csdn.net/chenjl1031/archive/2008/01/09/2032579.aspx
  

#12


Timer 的分辨率是 1ms。但是精度就很难说了,它受到多任务时间分配的影响。一般来说,精度好于 10 ms


一般要api了
Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long 

#13


楼主可以考虑写一个循环过程来监视具体如下:
Public Declare Function GetTickCount Lib "kernel32" () As Long
dim bolExit as boolean
dim lngStart as long 
bolExit=false    '请将其定义为模块级变量
lngStart=gettickcount
do
  DoEvents   '这个是必须的,不然响应其他操作会很慢
  if gettickcount-lngstart>99 then   '之所以要去99,是因为每次判断不会完全精确,需要你手动的
      '执行你的处理过程
       lngStart=gettickcount    '更新新的起点坐标
  endif
loop until bolExit

这个循环在bolExit为False时,不过会退出循环,你可在外部设置bolExit为True,即可退出。

#14


你可测试一下你的程序执行一次数据采集需要多少毫秒,当你的时间间隔很小时可能以上程序需要修改一下,比如:你要间隔10ms采集一次,而每次你的采集过程执行时间是3ms你最好是这样写:
Public Declare Function GetTickCount Lib "kernel32" () As Long 
dim bolExit as boolean 
dim lngStart as long 
bolExit=false    '请将其定义为模块级变量 
lngStart=gettickcount 
do 
  DoEvents  '这个是必须的,不然响应其他操作会很慢 
  if gettickcount-lngstart>9 then  '之所以要去9,是因为每次判断不会完全精确,需要你手动的 
      lngStart=gettickcount    '更新新的起点坐标 
      '执行你的处理过程 
  endif 
loop until bolExit 

#15


好帖,顶!

#16


Timer要经过消息循环的,所以有可能会被堵塞,自己实现一个吧也不难

#17


cpu始终是18ms的

timer精度最高是18ms

#18


再次学习,多谢了!

#19


17楼正确.在最好的情况下,精度也不会超过18ms,何况程序还会自我阻塞.用单片机吧!

#20


vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

#21


引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

#22


引用 21 楼 veron_04 的回复:
引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

这不是精度误差造成的,而是Timer是靠消息队列产生的。如果超时,一些Timer会被抛弃。比如程序做运算的时候,会跳过刚好到来的Timer事件。

#23


2米99!!

#24


20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

#25


引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。

#26


引用 22 楼 caozhy 的回复:
引用 21 楼 veron_04 的回复:
引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

这不是精度误差造成的,而是Timer是靠消息队列产生的。如果超时,一些Timer会被抛弃。比如程序做运算的时候,会跳过刚好到来的Timer事件。


你自己做个测试吧,VB6环境,什么都不做,每隔一个小时输出一次时间。你就可以发现VB6误差大到难以相信。

#27


好贴。。。

#28


引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


你是使用和系统时间比较吧,如果那样你将Timer 的间隔设置成100ms,一月后也能保持在100ms内

#29


路过...........

#30


引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


我就觉得VC的onTimer函数和VB的Timer控件是一样的!
因为两个都是处理窗口的WM_TIMER消息!

你所说的 onTimer 函数,只在MFC上面有,其实就是当系统接收到 WM_TIMER 消息时,把计时器的ID发送到 onTimer 函数中,在该函数里按照计时器的ID号不同而区分不同的计时器

而VB的Timer函数也一样,只不过它封装成一个控件,你在窗口上放一个 Timer 控件,设置好一些属性,那么这个控件就会用某些方法(例如SetTimer函数)使得窗体产生一个WM_TIMER消息,而控件就拦截到这个消息,然后判断计时器的ID是否属于Timer控件所拥有的(这个属性估计是隐藏的,VB可能是根据Timer控件的名称生成一个长整数类型来记录ID),如果是它所拥有的,则调用用户所写的函数。


至于你所说的差异,估计是编译器所造成的,VB是经过封装,中间所需处理很多细节,所以导致一些时间上的差异。

#31


好帖,顶一顶!

#32


才发现,1分帖...

#33


学习啦~~

#34


激光一般都是测量距离、位置和时间有关系吗?
lz:能够说的清楚点吗?

 ”激光测量系统100毫秒取一次数据“
是不是激光100ms输出数据
或者是100ms激光读取一个时基。再如何、如何呢?

对你的帖子内容感兴趣,说详细点!

#35


我在这里顶一下 思楼 格雷斯,书看得细。有权威的味道!

#36


引用 28 楼 huyongsc 的回复:
引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


你是使用和系统时间比较吧,如果那样你将Timer 的间隔设置成100ms,一月后也能保持在100ms内


别想当然,我VC中用一个函数计算当前时间到整点的秒数,做一个这个秒的定时,等这个定时到了,关闭这个定时启动一个定时,比方,定时一小时,则VC的定时是这样设置的,SetTiemr(99,1000*24*60,NULL),就是定时一个小时,然后程序就每个定点时间输出了,很容易观察的 。设置天也可以,不过VB Timer是太烂了,它不能设置>32535数,如果你想超过这个数的话,你要在定时函数中自己判断了,这当然要大大影响精度了。

#37


定时一小时VC是这样的:
SetTiemr(99,1000*60*60,NULL),
定时一天则这样:
SetTiemr(99,1000*60*60*24,NULL)

VB中的定时时间非常短,因为Timer的interval属性是integer型,不能大于65535/2=32768,也就是说如果不特殊处理,定时时长不超过33秒。

#38


我记得有个控件计算的时间很准的,在网上找找

#1


该回复于2009-06-08 14:09:31被版主删除

#2


十八分之一秒

#3


摘自MSDN的解释:
使用 Timer 控件
Timer 控件响应时间的流逝。它们独立于用户,编程后可用来在一定的时间间隔执行操作。此控件的一个一般用处是检查系统时钟,判断是否该执行某项任务。对于其它后台处理, Timer 控件也非常有用。
每个 Timer 控件都有 Interval 属性,指定定时器事件之间的毫秒数。除非禁止此属性,否则定时器在大致相等的时间间隔不断接受事件(称作定时器事件会更贴切)。
在为 Timer 控件编程时应考虑对 Interval 属性的几条限制: 
如果应用程序或其它应用程序正在进行对系统要求很高的操作─ 例如长循环、高强度的计算或者正在访问驱动器、网络或端口─ 则应用程序定时器事件的间隔可能比 Interval 属性指定的间隔长。
间隔的取值可在 0 到 64,767 之间(包括这两个数值),这意味着即使是最长的间隔也不比一分钟长多少(大约 64.8 秒)。
间隔并不一定十分准确。要保证间隔准确,应在需要时才让定时器检查系统时钟,而不在内部追踪积聚的时间。
系统每秒生成 18 个时钟信号─ 所以即使用毫秒衡量 Interval 属性,间隔实际的精确度不会超过 18 分之一秒。
 

#4


以下文字来自MSDN Programmer's Guide:

The system generates 18 clock ticks per second — so even though the Interval property is measured in milliseconds, the true precision of an interval is no more than one-eighteenth of a second. 

#5


补充一点,Timer 控件的实际间隔时间是Timer 控件Interval 属性设置的时间 + 在Timer 事件中代码执行的时间(它与系统和机器的硬件环境有很大关系. 所以要保证间隔准确,应在需要时才让定时器检查系统时钟,而不在内部追踪积聚的时间。

#6


问题在于你的timer里的代码能在1000/18秒内完成吗?

#7


学习下

#8


你可以用多媒体时钟,那个能精确到1ms

#9



不要用定时器了,可以用 API 实现高精度时钟:

Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long


Public Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

第一个函数是测量系统时钟的。以便计算延时所需的时钟周期数。

第二个用来返回系统运行的时钟数。可以用来延时。

这两个函数都涉及到大整数。

#10


Timer 的分辨率是 1ms。但是精度就很难说了,它受到多任务时间分配的影响。一般来说,精度好于 10 ms。

#11


引用 9 楼 of123 的回复:
不要用定时器了,可以用 API 实现高精度时钟:

Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long


Public Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

第一个函数是测量系统时钟的。以便计算延时所需的时钟周期数。

第二个用来返回系统运行的时钟数。可以用来延时。

这两个函数都涉及到大整数。


同意!具体用法我这儿有:  http://blog.csdn.net/chenjl1031/archive/2008/01/09/2032579.aspx
  

#12


Timer 的分辨率是 1ms。但是精度就很难说了,它受到多任务时间分配的影响。一般来说,精度好于 10 ms


一般要api了
Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long 

#13


楼主可以考虑写一个循环过程来监视具体如下:
Public Declare Function GetTickCount Lib "kernel32" () As Long
dim bolExit as boolean
dim lngStart as long 
bolExit=false    '请将其定义为模块级变量
lngStart=gettickcount
do
  DoEvents   '这个是必须的,不然响应其他操作会很慢
  if gettickcount-lngstart>99 then   '之所以要去99,是因为每次判断不会完全精确,需要你手动的
      '执行你的处理过程
       lngStart=gettickcount    '更新新的起点坐标
  endif
loop until bolExit

这个循环在bolExit为False时,不过会退出循环,你可在外部设置bolExit为True,即可退出。

#14


你可测试一下你的程序执行一次数据采集需要多少毫秒,当你的时间间隔很小时可能以上程序需要修改一下,比如:你要间隔10ms采集一次,而每次你的采集过程执行时间是3ms你最好是这样写:
Public Declare Function GetTickCount Lib "kernel32" () As Long 
dim bolExit as boolean 
dim lngStart as long 
bolExit=false    '请将其定义为模块级变量 
lngStart=gettickcount 
do 
  DoEvents  '这个是必须的,不然响应其他操作会很慢 
  if gettickcount-lngstart>9 then  '之所以要去9,是因为每次判断不会完全精确,需要你手动的 
      lngStart=gettickcount    '更新新的起点坐标 
      '执行你的处理过程 
  endif 
loop until bolExit 

#15


好帖,顶!

#16


Timer要经过消息循环的,所以有可能会被堵塞,自己实现一个吧也不难

#17


cpu始终是18ms的

timer精度最高是18ms

#18


再次学习,多谢了!

#19


17楼正确.在最好的情况下,精度也不会超过18ms,何况程序还会自我阻塞.用单片机吧!

#20


vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

#21


引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

#22


引用 21 楼 veron_04 的回复:
引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

这不是精度误差造成的,而是Timer是靠消息队列产生的。如果超时,一些Timer会被抛弃。比如程序做运算的时候,会跳过刚好到来的Timer事件。

#23


2米99!!

#24


20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

#25


引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。

#26


引用 22 楼 caozhy 的回复:
引用 21 楼 veron_04 的回复:
引用 20 楼 test2002 的回复:
vb的Timer很差,时间一长,误差很大,VC程序的OnTimer则非常高精度,我运行一月,都差不了一秒。

真的假的?!那是相当的高。

这不是精度误差造成的,而是Timer是靠消息队列产生的。如果超时,一些Timer会被抛弃。比如程序做运算的时候,会跳过刚好到来的Timer事件。


你自己做个测试吧,VB6环境,什么都不做,每隔一个小时输出一次时间。你就可以发现VB6误差大到难以相信。

#27


好贴。。。

#28


引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


你是使用和系统时间比较吧,如果那样你将Timer 的间隔设置成100ms,一月后也能保持在100ms内

#29


路过...........

#30


引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


我就觉得VC的onTimer函数和VB的Timer控件是一样的!
因为两个都是处理窗口的WM_TIMER消息!

你所说的 onTimer 函数,只在MFC上面有,其实就是当系统接收到 WM_TIMER 消息时,把计时器的ID发送到 onTimer 函数中,在该函数里按照计时器的ID号不同而区分不同的计时器

而VB的Timer函数也一样,只不过它封装成一个控件,你在窗口上放一个 Timer 控件,设置好一些属性,那么这个控件就会用某些方法(例如SetTimer函数)使得窗体产生一个WM_TIMER消息,而控件就拦截到这个消息,然后判断计时器的ID是否属于Timer控件所拥有的(这个属性估计是隐藏的,VB可能是根据Timer控件的名称生成一个长整数类型来记录ID),如果是它所拥有的,则调用用户所写的函数。


至于你所说的差异,估计是编译器所造成的,VB是经过封装,中间所需处理很多细节,所以导致一些时间上的差异。

#31


好帖,顶一顶!

#32


才发现,1分帖...

#33


学习啦~~

#34


激光一般都是测量距离、位置和时间有关系吗?
lz:能够说的清楚点吗?

 ”激光测量系统100毫秒取一次数据“
是不是激光100ms输出数据
或者是100ms激光读取一个时基。再如何、如何呢?

对你的帖子内容感兴趣,说详细点!

#35


我在这里顶一下 思楼 格雷斯,书看得细。有权威的味道!

#36


引用 28 楼 huyongsc 的回复:
引用 25 楼 test2002 的回复:
引用 24 楼 cqcpl 的回复:
20楼的意见是否跑题了,用累计误差来估计精度不是很准确的说.就楼主的要求,不但要累计精度高,更要每个时间都精度高才行.

怎么跑题了,累计误差大的,精度肯定也差,这是肯定的。
我用VC的 OnTimer,  不管是精度,还是累计精度,是VB Timer望尘莫及的。VC是 ms级的。

我的程序定时输出,比方定在一个整点,输出,它每天都是在这个点输出,运行很长时间,在一秒以内。


你是使用和系统时间比较吧,如果那样你将Timer 的间隔设置成100ms,一月后也能保持在100ms内


别想当然,我VC中用一个函数计算当前时间到整点的秒数,做一个这个秒的定时,等这个定时到了,关闭这个定时启动一个定时,比方,定时一小时,则VC的定时是这样设置的,SetTiemr(99,1000*24*60,NULL),就是定时一个小时,然后程序就每个定点时间输出了,很容易观察的 。设置天也可以,不过VB Timer是太烂了,它不能设置>32535数,如果你想超过这个数的话,你要在定时函数中自己判断了,这当然要大大影响精度了。

#37


定时一小时VC是这样的:
SetTiemr(99,1000*60*60,NULL),
定时一天则这样:
SetTiemr(99,1000*60*60*24,NULL)

VB中的定时时间非常短,因为Timer的interval属性是integer型,不能大于65535/2=32768,也就是说如果不特殊处理,定时时长不超过33秒。

#38


我记得有个控件计算的时间很准的,在网上找找