关于vb计时器精确计时问题

时间:2022-02-14 20:35:09
我想用vb做一个长时间采集数据的程序,采集间隔最小100ms,怎么才能做到时间上的精确呢?

刚开始把计时器间隔设为10ms,然后用GetTickCount计算,到达时间就进行采集,采集间隔为1S的时候依然有误差,并且GetTickCount到49.7天的时候就清零了,到时候肯定会造成时间计算上的混乱。

现在用QueryPerformanceCounter,但是刚才查了一下,好像这个也是计算从开机到现在的时间,时间长了肯定也会溢出的吧?并且如果用户做其他的事情,比如说移动窗体什么的,就会有影响了。

哪位有更好的方法?

27 个解决方案

#1


帮顶

#2


直接取系统时间计时

#3


蜘蛛?定期重爬

#4


网上看到一种多媒体计时器的方法,但是一运行就会出现内存错误,哪位还有更好的办法啊?

#5



2 楼好主意。如果不是要求采集那么准确的话,应该可以。而且每次都可以自对准的。

#6


引用 2 楼 jhone99 的回复:
直接取系统时间计时


毫秒级的可以吗?

#7


timer函数
可以到10ms和100ms ,1ms不行

#8


我现在做的是如果采集间隔大于等于1秒的话,把计时器间隔设为100MS,判断系统时间进行采集,如果小于1秒的话计时器的间隔就设为采集间隔,这样的话小于1秒的肯定会有误差的。

#9


引用 7 楼 king06 的回复:
timer函数
可以到10ms和100ms ,1ms不行


好的,谢谢

#10


引用 9 楼 congcong1105 的回复:
引用 7 楼 king06 的回复:
timer函数
可以到10ms和100ms ,1ms不行


好的,谢谢


如果采集的过程经过午夜时刻也会有误差的啊

#11


可以到毫秒级:

Public Declare Sub GetLocalTime Lib "kernel32" Alias "GetLocalTime" (lpSystemTime As SYSTEMTIME)

Type SYSTEMTIME
      wYear As Integer
      wMonth As Integer
      wDayOfWeek As Integer
      wDay As Integer
      wHour As Integer
      wMinute As Integer
      wSecond As Integer
      wMilliseconds As Integer '毫秒数
End Type

#12


Private Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)

Private Type SYSTEMTIME
 wYear As Integer
 wMonth As Integer
 wDayOfWeek As Integer
 wDay As Integer
 wHour As Integer
 wMinute As Integer
 wSecond As Integer
 wMilliseconds As Integer
End Type


Private Sub Form_Load()
 Dim st As SYSTEMTIME
  
 GetSystemTime st
  
 Dim stime As String
  
 stime = Now & "." & st.wMilliseconds
  
 Me.Caption = stime
End Sub

#13


SYSTEMTIME 类型的可以直接比较大小吗?

#14


timeGetTime也可以
Private Declare Function timeGetTime Lib "winmm.dll" Alias "timeGetTime" 

() As Long

'注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保留字去掉。



Dim tm1 As Long

Do

tm1 = timeGetTime

While timeGetTime - tm1 < 5 ' 等于 5/1000 = 0.005 秒

DoEvents

Wend

'...做某一件工作

Loop

#15


。。。午夜时刻采集,timer归零,可以加上过了午夜时刻的采集数据,需要处理一下,但并不影响计算精度

不过 上面可以 "取系统时间"到毫秒级更好,就用那个吧,不过还是得处理午夜时刻的数据.

#16


引用 14 楼 jhone99 的回复:
timeGetTime也可以
VB codePrivate DeclareFunction timeGetTime Lib"winmm.dll" Alias"timeGetTime" 

()AsLong'注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保留字去掉。Dim tm1AsLongDo

tm1= timeGetTimeWhile timeGetTime- tm1<5' 等于 5/1000 = 0.005 秒
DoEventsWend'...做某一件工作Loop


这个时间长了也会溢出的吧?

#17


用GetLocalTime ,当时间比较的时候是不是必须一级一级地比较啊?还有在此时间基础上加上一定时间的话是不是也必须一级一级进行计算啊?有没有直接的方法?

#18



溢出的问题实际上是可以避免的。你在数据采集后,将计时器高位清零就行了。

另外,Timer 方案的跨午夜问题也是可以通过代码处理的。只要超时变量超过 24 小时,减去 24 小时就可以了。

#19


引用 18 楼 of123 的回复:
溢出的问题实际上是可以避免的。你在数据采集后,将计时器高位清零就行了。

另外,Timer 方案的跨午夜问题也是可以通过代码处理的。只要超时变量超过 24 小时,减去 24 小时就可以了。


谢谢,计时器高位清零 是怎么回事啊?

#20


http://blog.csdn.net/chenjl1031/archive/2008/01/09/2032579.aspx

#21


引用楼主 congcong1105 的回复:
我想用vb做一个长时间采集数据的程序,采集间隔最小100ms,怎么才能做到时间上的精确呢?

刚开始把计时器间隔设为10ms,然后用GetTickCount计算,到达时间就进行采集,采集间隔为1S的时候依然有误差,并且GetTickCount到49.7天的时候就清零了,到时候肯定会造成时间计算上的混乱。

现在用QueryPerformanceCounter,但是刚才查了一下,好像这个也是计算从开机到现在的时间,时间长了肯定也会溢出的吧?并且如果用户做其他的事情,比如说移动窗体什么的,就会有影响了。

哪位有更好的方法?

使用QueryPerformanceCounter可以产生Double类型的数据,应该说范围宽了很多了。时间长度增加了很多。

#22


我用timer函数,收集间隔为1s,计时器间隔为20ms和50ms的时候都还是会有误差,还有没有好的办法?

#23


p_slgEndSecond = Timer
If p_slgEndSecond < p_slgStartSecond Then p_slgEndSecond = p_slgEndSecond + 86400
If (p_slgEndSecond - p_slgStartSecond) * 100 >= CDbl(p_iniSampleInterval) * 10 Then
    p_slgStartSecond = Timer
    采集数据
End If

p_iniSampleInterval的单位是100ms,帮我看看代码有没有不妥,为什么老是有误差呢。

#24


PS:我把采集数据的代码注释掉以后也是会有误差,

连续回复三次了。。。不能再发了。。。。555

#25


.给你断一下

#26


谢谢楼上,


为什么还是有误差啊?相对来说用GetTickCount精确度能高一些,但是我不知道怎么处理溢出的问题,总感觉很危险

#27


跟timer控件有没有关系啊?设置好的间隔有时候不去执行,不影响其它的前提下加个doevents试试

#1


帮顶

#2


直接取系统时间计时

#3


蜘蛛?定期重爬

#4


网上看到一种多媒体计时器的方法,但是一运行就会出现内存错误,哪位还有更好的办法啊?

#5



2 楼好主意。如果不是要求采集那么准确的话,应该可以。而且每次都可以自对准的。

#6


引用 2 楼 jhone99 的回复:
直接取系统时间计时


毫秒级的可以吗?

#7


timer函数
可以到10ms和100ms ,1ms不行

#8


我现在做的是如果采集间隔大于等于1秒的话,把计时器间隔设为100MS,判断系统时间进行采集,如果小于1秒的话计时器的间隔就设为采集间隔,这样的话小于1秒的肯定会有误差的。

#9


引用 7 楼 king06 的回复:
timer函数
可以到10ms和100ms ,1ms不行


好的,谢谢

#10


引用 9 楼 congcong1105 的回复:
引用 7 楼 king06 的回复:
timer函数
可以到10ms和100ms ,1ms不行


好的,谢谢


如果采集的过程经过午夜时刻也会有误差的啊

#11


可以到毫秒级:

Public Declare Sub GetLocalTime Lib "kernel32" Alias "GetLocalTime" (lpSystemTime As SYSTEMTIME)

Type SYSTEMTIME
      wYear As Integer
      wMonth As Integer
      wDayOfWeek As Integer
      wDay As Integer
      wHour As Integer
      wMinute As Integer
      wSecond As Integer
      wMilliseconds As Integer '毫秒数
End Type

#12


Private Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)

Private Type SYSTEMTIME
 wYear As Integer
 wMonth As Integer
 wDayOfWeek As Integer
 wDay As Integer
 wHour As Integer
 wMinute As Integer
 wSecond As Integer
 wMilliseconds As Integer
End Type


Private Sub Form_Load()
 Dim st As SYSTEMTIME
  
 GetSystemTime st
  
 Dim stime As String
  
 stime = Now & "." & st.wMilliseconds
  
 Me.Caption = stime
End Sub

#13


SYSTEMTIME 类型的可以直接比较大小吗?

#14


timeGetTime也可以
Private Declare Function timeGetTime Lib "winmm.dll" Alias "timeGetTime" 

() As Long

'注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保留字去掉。



Dim tm1 As Long

Do

tm1 = timeGetTime

While timeGetTime - tm1 < 5 ' 等于 5/1000 = 0.005 秒

DoEvents

Wend

'...做某一件工作

Loop

#15


。。。午夜时刻采集,timer归零,可以加上过了午夜时刻的采集数据,需要处理一下,但并不影响计算精度

不过 上面可以 "取系统时间"到毫秒级更好,就用那个吧,不过还是得处理午夜时刻的数据.

#16


引用 14 楼 jhone99 的回复:
timeGetTime也可以
VB codePrivate DeclareFunction timeGetTime Lib"winmm.dll" Alias"timeGetTime" 

()AsLong'注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保留字去掉。Dim tm1AsLongDo

tm1= timeGetTimeWhile timeGetTime- tm1<5' 等于 5/1000 = 0.005 秒
DoEventsWend'...做某一件工作Loop


这个时间长了也会溢出的吧?

#17


用GetLocalTime ,当时间比较的时候是不是必须一级一级地比较啊?还有在此时间基础上加上一定时间的话是不是也必须一级一级进行计算啊?有没有直接的方法?

#18



溢出的问题实际上是可以避免的。你在数据采集后,将计时器高位清零就行了。

另外,Timer 方案的跨午夜问题也是可以通过代码处理的。只要超时变量超过 24 小时,减去 24 小时就可以了。

#19


引用 18 楼 of123 的回复:
溢出的问题实际上是可以避免的。你在数据采集后,将计时器高位清零就行了。

另外,Timer 方案的跨午夜问题也是可以通过代码处理的。只要超时变量超过 24 小时,减去 24 小时就可以了。


谢谢,计时器高位清零 是怎么回事啊?

#20


http://blog.csdn.net/chenjl1031/archive/2008/01/09/2032579.aspx

#21


引用楼主 congcong1105 的回复:
我想用vb做一个长时间采集数据的程序,采集间隔最小100ms,怎么才能做到时间上的精确呢?

刚开始把计时器间隔设为10ms,然后用GetTickCount计算,到达时间就进行采集,采集间隔为1S的时候依然有误差,并且GetTickCount到49.7天的时候就清零了,到时候肯定会造成时间计算上的混乱。

现在用QueryPerformanceCounter,但是刚才查了一下,好像这个也是计算从开机到现在的时间,时间长了肯定也会溢出的吧?并且如果用户做其他的事情,比如说移动窗体什么的,就会有影响了。

哪位有更好的方法?

使用QueryPerformanceCounter可以产生Double类型的数据,应该说范围宽了很多了。时间长度增加了很多。

#22


我用timer函数,收集间隔为1s,计时器间隔为20ms和50ms的时候都还是会有误差,还有没有好的办法?

#23


p_slgEndSecond = Timer
If p_slgEndSecond < p_slgStartSecond Then p_slgEndSecond = p_slgEndSecond + 86400
If (p_slgEndSecond - p_slgStartSecond) * 100 >= CDbl(p_iniSampleInterval) * 10 Then
    p_slgStartSecond = Timer
    采集数据
End If

p_iniSampleInterval的单位是100ms,帮我看看代码有没有不妥,为什么老是有误差呢。

#24


PS:我把采集数据的代码注释掉以后也是会有误差,

连续回复三次了。。。不能再发了。。。。555

#25


.给你断一下

#26


谢谢楼上,


为什么还是有误差啊?相对来说用GetTickCount精确度能高一些,但是我不知道怎么处理溢出的问题,总感觉很危险

#27


跟timer控件有没有关系啊?设置好的间隔有时候不去执行,不影响其它的前提下加个doevents试试