VB高精度计时器编程的讨论

上传人:飞*** 文档编号:42613242 上传时间:2018-06-02 格式:DOC 页数:8 大小:45KB
返回 下载 相关 举报
VB高精度计时器编程的讨论_第1页
第1页 / 共8页
VB高精度计时器编程的讨论_第2页
第2页 / 共8页
VB高精度计时器编程的讨论_第3页
第3页 / 共8页
VB高精度计时器编程的讨论_第4页
第4页 / 共8页
VB高精度计时器编程的讨论_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《VB高精度计时器编程的讨论》由会员分享,可在线阅读,更多相关《VB高精度计时器编程的讨论(8页珍藏版)》请在金锄头文库上搜索。

1、Private Sub Form_Load() Dim h As Single, v As Single Height = 8730 Width = 7695 AutoRedraw = True DrawWidth = 3 For i = 0 To 20 PSet (h, v) h = h + 500 v = v + 98 * i 9.8 为重力加速度,此处 98 是为了使效果明显而已 Next End Sub h 是水平位置,v 是垂直位置 这是平抛运动,至于自由落体,只要把 h 设为定值便可VB 高精度计时器编程的讨论高精度计时器编程的讨论VB 高精度计时器编程的讨论 VB 记时器编程的讨

2、论 在很多场合下编程(例如工业控制、游戏)中需要比较精确的记时器,本文讨论的是在 VB 下实现记时器的若干方法以及它们的精度控制问题。 在 VB 中最常用的是 Timer 控件,它的设置和使用都非常方便,理论上它的记时精度可以达到 1ms(毫秒)。但是众所周知的,实际上 Timer 在记时间隔小于 50ms 之下是精度是十分差的。它只适用于对于精度要求不太高的场合。 这里作者要介绍的是两中利用 Windows API 函数实现精确记时的方法。第一中方法是利用高性能频率记数(作者本人的称呼)法。利用这种方法要使用两个 API 函数 QueryPerformanceFrequency 和 Quer

3、yPerformanceCounter。QueryPerformanceFrequency 函数获得高性能频率记数器的震荡频率,该函数的定义如下: Private Declare Function QueryPerformanceFrequency Lib “kernel32“ _ (lpFrequency As LARGE_INTEGER) As Long 函数中的数据结构 LARGE_INTEGER 定义如下: Type LARGE_INTEGER lowpart As Long highpart As Long End Type 调用该函数后,函数会将系统频率记数器的震荡频率保存到 lp

4、PerformanceCount 中,其中低位保存到 lowpart 中,高位保存到 highpart 中。但是现在的 Windows 没有使用到 hightpart(系统频率记数器的震荡频率与计算机的主频无关,我在几台机上做过验证,都是 lowpart 为 1193180,highpart 为0)。 QueryPerformanceCounter 函数获得系统频率记数器的震荡次数,函数的定义如下 Private Declare Function QueryPerformanceCounter Lib “kernel32“ _ (lpPerformanceCount As LARGE_INTE

5、GER) As Long 获得记时器震荡次数保存在 lpPerformanceCount 中。 显然,如果首先获得利用 QueryPerformanceFrequency 函数获得频率记数器的震荡频率,然后在执行某个程序段之前调用 QueryPerformanceCounter 函数获得频率记数器的震荡次数,在程序段结束再调用 QueryPerformanceCounter 函数获得频率记数器的震荡次数,将两次获得的震荡次数相减后再除以震荡频率就获得的了两次间隔之间的时间(以秒为单位)。如果在程序中建立一个循环,在循环中不停的调用 QueryPerformanceCounter 获得频率记数器

6、的震荡次数并同先前的频率记数器的震荡次数相减,将结果除以频率记数器的震荡频率,如果达到一定的时间就执行某个任务,这样就实现了一个比较精确的记时器的功能。 另外的一种精确记时器的功能是利用多媒体记时器函数(这也是作者的定义,因为这个系列的函数是在Winmm.dll 中定义并且是为媒体播放服务的)。 实现多媒体记时器首先要定义 timeSetEvent 函数,该函数的定义如下: Public Declare Function timeSetEvent Lib “winmm.dll“ (ByVal uDelay As Long, ByVal _ uResolution As Long, ByVal

7、lpFunction As Long, ByVal dwUser As Long, _ ByVal uFlags As Long) As Long 函数定义中参数 uDelay 定义延迟时间,以毫秒为单位,该参数相当于 Timer 控件的 Interval 属性。参数 uResolution 定义记时精度,如果要求尽可能高的精度,要将该参数设置为 0;参数 lpFunction 定义了 timeSetEvent 函数的回调函数的地址。参数 dwUser 定义用户自定义的回调值,该值将传递给回调函数。参数 uFlags 定义定时类型,如果定义为 Time_OneShot,则只会在当达到 uDel

8、ay 定义的时间后调用回调函数一次,如果定义为 TIME_PERIODIC,则在每次达到定时时间后调用回调函数。 如果函数调用成功,在系统中建立了一个多媒体记时器对象,每当经过一个 uDelay 时间后 lpFunction 指定的函数都会被调用。同时函数返回一个对象标识,如果不再需要记时器则必须要使用 timeKillEvent 函数删除记时器对象。 由于 Windows 是一个多任务的操作系统,因此基于 API 调用的记时器的精度都会受到其它很多因素的干扰。到底这两中记时器的精度如何,我们来使用以下的程序进行验证: 设置三种记时器(Timer 控件、高性能频率记数、多媒体记时器)。将它们的

9、定时间隔设置为 10 毫秒,让它们不停工作直到达到一个比较长的时间(比如 60 秒),这样记时器的误差会被累计下来,然后同实际经过的时间相比较,就可以得到它们的精度。 下面是具体的检测程序。 首先建立一个工程文件,在 Form1 中加入一个 Timer 控件,两个 CommandButton 控件和三个 TextBox 控件,然后在 Form1 的代码窗口中加入以下代码 Option Explicit Private Sub Command1_Click() Dim lagTick1 As LARGE_INTEGER Dim lagTick2 As LARGE_INTEGER Dim lTen

10、 As Long Command2.Enabled = True Command1.Enabled = False iCountStart = 60 lmmCount = 60 TimerCount = 60 actTime1 = GetTickCount lTimeID = timeSetEvent(10, 0, AddressOf TimeProc, 1, 1) Timer1.Enabled = True lTen = 10 * lMSFreq Call QueryPerformanceCounter(lagTick1) lagTick2 = lagTick1 While iCountSt

11、art 0 Call QueryPerformanceCounter(lagTick2) 如果时钟震动次数超过 10 毫秒的次数则刷新 Text1 的显示 If lagTick2.lowpart - lagTick1.lowpart lTen Then lagTick1 = lagTick2 iCountStart = iCountStart - 0.01 Text1.Text = Format$(iCountStart, “00.00“) End If DoEvents Wend End Sub Private Sub Command2_Click() EndCount End Sub Pr

12、ivate Sub Form_Load() Dim lim As LARGE_INTEGER Text1.Text = “60.00“ Text2.Text = “60.00“ Text3.Text = “60.00“ Command1.Caption = “开始倒记时“ Command2.Caption = “停止记时“ Command2.Enabled = False 获得系统板上时钟频率 QueryPerformanceFrequency lim 将频率除以 1000 就的出时钟 1 毫秒震动的次数 lMSFreq = (lim.highpart * 2 16) 1000 + lim.l

13、owpart 1000 Timer1.Interval = 10 Timer1.Enabled = False End Sub Private Sub Timer1_Timer() TimerCount = TimerCount - 0.01 Text3.Text = Format$(TimerCount, “00.00“) If TimerCount = 0 Then Timer1.Enabled = False End If End Sub 在 Project 中加入一个 Module,然后在其中加入以下代码: Option Explicit Type LARGE_INTEGER lowp

14、art As Long highpart As Long End Type Public Declare Function QueryPerformanceCounter Lib “kernel32“ _ (lpPerformanceCount As LARGE_INTEGER) As Long Public Declare Function QueryPerformanceFrequency Lib “kernel32“ _ (lpFrequency As LARGE_INTEGER) As Long Public Declare Function timeSetEvent Lib “winmm.dll“ (ByVal uDelay As Long, ByVal _ uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, _ ByVal uFlags As Long) As Long Publi

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号