多媒体定时器

Windows定时器

  在以Windows以平台的实时控制系统中,常常需要定时或周期性的完成某个动作,采样时间的精度是系统得以正常运行的关键,对以Dos为平台的控制系统,可以通过对硬件的直接操作而得到精确的采样时间,而对于Windows平台,由于Windows平台为抢占式多任务操作系统,系统管理所有硬件资源,用户无法直接同硬件打交道,时间控制离不开操作系统的支持,因此,在Windows平台下如何精确的控制采样频率是一个很关键的技术。

一.普通定时器

  普通定时器是依赖消息机制的时间控制方法,首先由SetTimer函数创建一个内存对象,设定间隔时间,当到达要求的时间间隔时,计时器对象发送一个WM_TIMER消息,由相应函数处理,WM_TIMER消息优先级不高,且易出现消息合并情况,不能满足工业实时控制系统的要求。

二.多媒体定时器

  多媒体定时器不依赖消息机制,而是有TimeSetEvent()产生一个独立的线程,在一定的中断次数到达后,直接调用预先设置的回调函数进行处理,而不必等待应用程序的消息队列为空,保证的定时器的实时相应,是一种很理想的高精度定时器,可以实现精度为1ms的定时精度,相关的API如下:

1. MMRESULT timeGetDevCaps(

  LPTIMECAPS ptc, 

  UINT cbtc       

);

函数功能:获取定时器设备能力

参数:ptc指向一个TIMECAPS型的结构,TIMECAPS有两个成员,wPeriodMin和WperiodMax,表示定时器设备支持的最小时间周期和最大时间周期;cbtc表示TIMECAPS结构的大小

返回值:

2. MMRESULT timeBeginPeriod(

  UINT uPeriod 

);

函数功能:设置定时器设备的最小时间分辨率

参数:最小时间分辨率,以毫秒为单位

3. MMRESULT timeEndPeriod(

  UINT uPeriod 

);

函数功能:清除之前对定时器设备的设置

参数:timeBeginPeriod中指定的最小分辨率

注:

对定时器设备使用完成后,立刻调用这个函数,timeBeginPeriod和timeEndPeriod必须配对存在,并且指定的参数值也相同。

4. MMRESULT timeSetEvent(

  UINT           uDelay,     

  UINT           uResolution,

  LPTIMECALLBACK lpTimeProc, 

  DWORD_PTR      dwUser,     

  UINT           fuEvent     

);

函数功能:

创建并初始化定时器事件,给定定时器回调函数的入口地址

参数:

uDelay:定时器触发的时间间隔,以毫秒为单位

uResolution:定时器设备的时间精度,以毫秒为单位,应大于或等于timeBeginPeriod中设置的值,默认为1ms,精度越高,系统在定时器上的负载就越大,通常选择适合于应用程序的最大值

LpTimeProc:定时器触发的事件的回调函数的地址

dwUser:传递给回调函数的数据

fuEvent:定时类型,TIME_ONESHOT表示uDelay毫秒后只产生一次事件,TIME_PERIODIC表示每隔uDelay毫秒周期性的产生事件

返回值:返回定时器事件的ID

5. MMRESULT timeKillEvent(

  UINT uTimerID 

);

函数功能:删除一个指定的定时器事件

参数:指向要删除的定时器事件的ID

注:

timeSetEvent和timeKillEvent必须配对出现,释放系统为定时器分配的资源,定时器任务完成后,要及时删除定时器,否则占用太多内存,导致系统越来越慢。

6. void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUsers,DWORD dw1,DWORD dw2);

函数功能:回调函数

参数:uID,多媒体定时器的ID,ID值由timeSetEvent创建定时器事件时返回

uMsg,保留,当前未使用

dwUser,由timeSetEvent传递的用户数据

dw1,dw2保留未使用

三.使用多媒体定时器的程序例子:

#include <Windows.h>

#include <MMSystem.h>

#include <iostream>

using namespace std;

#pragma comment(lib, "winmm.lib")

void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUsers,DWORD dw1,DWORD dw2);

int main()

{

    UINT wTimerRes;

    UINT timerID;

    TIMECAPS ts;

    //确定多媒体定时器提供的最大和最小定时器事件周期

    timeGetDevCaps(&ts, sizeof(ts));

    wTimerRes = 1;

    //建立最小定时器精度

    timeBeginPeriod(wTimerRes);

    //启动定时器事件,设置定时周期为100ms,分辨率是10毫秒

    timerID = timeSetEvent(100,10,TimeProc,NULL,TIME_PERIODIC);

    Sleep(50000);

    //关闭定时器事件

    timeKillEvent(timerID);

    //清除最小定时器精度

    timeEndPeriod(wTimerRes);

    return 0;

};

void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUsers,DWORD dw1,DWORD dw2)

{

    cout<<uID<<endl;

}

posted @ 2013-06-13 15:25  liuhao2638  阅读(6146)  评论(0编辑  收藏  举报