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;
}