天天看點

MFC定時器的應用

在計算機程式設計領域,有很多功能是周期性執行的,       如:資料采集程式,系統時間的顯示等。 資料采集:周期性地獲得現場的實體量資訊 系統時間的顯示:周期性地獲得系統時間,并顯示出來。 完成上述這些功能的代碼都是按照一定的時間間隔周期性地執行的,這是就需要用到一個新的元件——定時器(TIMER)。       定時器是Windows系統的資源, Visual C++提供了定時器消息和一些與定時相關的函數。使用這些函數可以完成程式代碼的周期性執行。 Viusal C++提供了三種完成周期性操作的方法: 1、Sleep函數(延時函數)。 2、WM_TIMER消息(Windows視窗消息)。 3、多媒體定時器。 3.2.1 Sleep函數 while(1)   {   i=i+1; //此處添加需要周期性執行的代碼。  Sleep(1000); } Sleep函數:延時函數 參數:延時的時間(機關ms) 缺點: (1)CPU占用率高,一般适用于單任務的程式(如DOS作業系統的程式) (2)程式能夠完成的功能比較簡單。 (3)定時精度低,(據資料)最小誤差為54.915 ms,每秒18.2次 3.2.2 WM_TIMER 衆所周知,Windows系統是一個多任務的作業系統。即可以有多個任務并行,這時,周期性(定時)執行的任務在執行完畢後,應該将控制權交給系統,這樣程式的其它功能才能得以執行。 Windows系統提供了WM_TIMER消息來實作多任務系統的定時操作。     WM_TIMER是一個Windosws的視窗消息 1、WM_TIMER的功能:     (1)可以完成定時操作。     (2)定時任務執行完畢後,将控制權交回給程式。程式可以進行其它的操作。   2、使用WM_TIMER消息需要用到的函數 1) SetTimer() 功能:設定定時間隔并啟動定時器。 函數原型:UINT SetTimer(UINT nIDEvent,UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD)); 參數說明: nIDEvent:非0值辨別Timer的id 。 nElapse:以毫秒為機關的定時間隔時間 lpfnTimer 指向定時事件到達時調用的函數的指針,如果為NULL,那麼調用OnTimer() 例:SetTimer(1,200,NULL)設定并啟動一個時間間隔為200ms的定時器。消息響應函數為OnTimer() 例:SetTimer(2,1000, TimerProc );設定并啟動一個實間間隔為1s的定時器,該定時器的響應函數為TimerProc。 2)KillTimer(1) 功能:取消定時器,此函數調用後,相應的定時器将被關閉不再起作用。 參數:用SetTimer()函數建立的定時器辨別。 定時器使用總結: 1、在WM_CREATE消息中啟動定時器(SetTimer) 2、在WM_TIMER消息中編寫定時函數(即需要周期性完成的工作) 3、在定時工作完成之後關閉/停止定時器。(可選) WM_TIMER的缺點: 1、精度低,最小計時精度大約為55ms(Win95),或10ms左右(Win2000/xp) 2、定時器消息在多任務作業系統中的優先級較低,有時不能得到及時響應。(一旦計算機的CPU被某個程序占用,或系統資源緊張時,發送到消息隊列中的消息就暫時被挂起,WM_TIMER消息得不到及時處理。) 3.2.3 多媒體定時器 1、 針對前兩種定時器的缺點,MicroSoft公司提供了一種精度更高的定時器——多媒體定時器。 優點: (1)精度較高:多媒體定時器最小誤差為1毫秒。 (2)優先級較高,可以減輕資源緊張對定時器運作的影響。 2、多媒體定時器的使用 timeSetEvent 函數 功能:設定并啟動一個多媒體定時器。 函數原型: MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent ) 函數頭檔案:#include "mmsystem.h" MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent ) 參數說明: uDelay:以毫秒指定時的周期 Uresolution:以毫秒指定延時的精度,數值越小定時器事件分辨率越高。預設值為1ms。 LpTimeProc:指向一個回調函數,該回調函數包含需要定時執行的代碼。 DwUser:存放使用者提供的回調資料。 FuEvent:指定定時器事件類型:     TIME_ONESHOT:uDelay毫秒後隻産生一次事件。     TIME_PERIODIC :每隔uDelay毫秒周期性地産生事件。 3.3 其它定時方法 1、使用GetTickCount函數 2、使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數。 在精度要求較高的情況下,如要求定時誤差不大于1ms時,還可以利用GetTickCount()函數傳回自計算機啟動後的時間,該函數的傳回值是DWORD型,表示以ms為機關的計算機啟動後經曆的時間間隔。通過兩次調用GetTickCount()函數,然後控制它們的內插補點來取得定時效果。.下列的代碼可以實作50ms的精确定時,其誤差是毫秒級的。 3、使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數     對于更精确的定時操作,使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數。這兩個函數是Visual C++提供并且僅供Windows 95及其後續版本使用,其精度與CPU的時鐘頻率有關,它們要求計算機從硬體上支援精确定時器。QueryPerformanceFrequency()函數和QueryPerformanceCounter()函數的原型如下: BOOL QueryPerformanceFrequency (LARGE_INTEGER *lpFrequency);

BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount); 使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數進行精确定時的步驟如下:

  1、首先調用QueryPerformanceFrequency()函數取得高精度運作計數器的頻率f,機關是每秒多少次(n/s),此數一般很大;

  2、在需要定時的代碼的兩端分别調用QueryPerformanceCounter()以取得高精度運作計數器的數值n1、n2,兩次數值的內插補點通過f換算成時間間隔,t=(n2-n1)/f,當t大于或等于定時時間長度時,啟動定時器;

繼續閱讀