如何精确计时? 越精确越好 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 这个问题很早就有人问了,只不过每人解决我把上次的方法搬出来参考1)timer2)gettickcount settickcount3)sleep4)创建一个超时的event。 Win95下高精度定时器的实现 国防科技大学机电工程与仪器系 张云洲 梁科山 ---- 在工业控制软件中,数据采集和实时控制是经常性的工作。目前,工业控制 软件已经从DOS和Windows3.x平台,转到了Windows95上。然而,Windows95并不能 直接支持中断,这就意味着在DOS和Windows3.x中的定时器中断不能为我们所用。 因此,我们必须寻求新的定时方式。 ---- 在C++ Builder和Delphi等典型的编程语言中,都提供了定时器控件,可以方 便地实现定时和事件响应。此外,Windows95还提供了SetTimer和KillTimer函数来 设置和删除一个定时器,在事件WM_TIMER响应函数中实现处理。然而,遗憾的是, 通过这些方式获得的Win95定时器最小只能精确到55毫秒,对于55毫秒以下的时间 精度便无能为力。这对于Win95下测控软件的开发是十分不利的。幸运的是,多媒 体定时器可以解决这一难题。 ---- 以下是一个完整的多媒体定时器设计示例程序,该定时器的精度为1毫秒。该 程序的内容十分简单:按下按钮1,启动定时器,在Edit框中显示定时值(计数值 ),按下按钮2则将关闭定时器。此程序在Windows95环境下,采用C++Builder3.0 编程并编译通过,但设计思想同样适用于其它高级语言。按照本程序中的实现方法 ,读者将可以轻松实现自己的高精度定时器。 ---- 程序清单如下: #include < vcl.h > #pragma hdrstop #include "mmsystem.h" //包含多媒体定时器函数的头文件 #define MilliSecond 1 //定时间隔1毫秒 #define Accuracy 1 //系统允许的分辨率最小值 #define Min(x,y) ((x < y) ? x : y) #define Max(x,y) ((x > y) ? x : y) #include "HighTimerU.h" //------------------------------------------------ #pragma package(smart_init) #pragma resource "*.dfm" UINT TimerID; //定义定时器句柄 int count; //定义一个变量以进行计数 int TimerAccuracy; TForm1 *Form1; //------------------------------------------------ __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } void PASCAL TimerCallProc(UINT TimerID, UINT msg,DWORD dwUser, DWORD dwa,DWORD dwb) //定义定时器事件的调用函数 { count++; Form1- >Edit1->Text=count; //在一个编辑框内显示计数值,即定时值 } //--------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { TIMECAPS timecaps; int TimerResolution; //从系统获得关于定时器服务能力的信息, //分辨率不能超出系统许可值(1到16毫秒) if (timeGetDevCaps(&timecaps,sizeof( TIMECAPS))==TIMERR_NOERROR) TimerAccuracy=Min(Max(timecaps.wPeriodMin, Accuracy),timecaps.wPeriodMax); timeBeginPeriod(TimerAccuracy); //设置定时器分辨率 TimerResolution=1; //设置定时间隔为1毫秒 //产生间隔1毫秒,周期执行的定时器事件;启动定时器 TimerID = timeSetEvent(TimerResolution,TimerAccuracy, &TimerCallProc,1,TIME_PERIODIC); } //------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { timeKillEvent(TimerID); //删除定时器事件 timeEndPeriod(TimerAccuracy); //清除定时器分辨率 } ---- 多媒体定时器对实现高精度定时是很理想的工具,而且其精度是十分可靠的 。但是,多媒体定时器也并不是完美的。因为它可靠的精度是建立在对系统资源的 消耗之上的。因此,在利用多媒体定时器完成工作的同时,必须注意以下几点: ---- 1. 多媒体定时器的设置分辨率不能超出系统许可范围。 ---- 2. 在使用完定时器以后,一定要及时删除定时器及其分辨率,否则系统会 越来越慢。 ---- 3. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结 束之前,注意一定不能再次启动该定时器不然迅速造成死机 Windows 95 中 的 定 时 器 的 应 用 李 振 ---- 在windows95 编 程 中 有 时 要 用 到 定 时 器 的 功 能, 大 家 常 用 的 是 通 过SetTimer 函 数 设 置 一 个 定 时 器, 在 事 件WM_TIMER 响 应 函 数 中 处 理, 然 后 用KillTimer 函 数 取 消 此 定 时 器。 但 此 种 方 式 的 定 时 器 只 能 精 确 到 大 约55 毫 秒, 对 于55 毫 秒 以 下 的 时 间 精 度 便 无 能 为 力。 ---- 笔 者 在 这 里 向 大 家 提 供 一 个 可 以 精 确 到1 毫 秒 的 定 时 器 — — 多 媒 体 定 时 器。 它 主 要 通 过 以 下 函 数 来 实 现: ---- timeBeginPeriod — — 建 立 应 用 程 序 使 用 的 定 时 器 分 辨 率; ---- timeEndPeriod — — 清 除 前 面 用timeBeginPeriod 函 数 建 立 的 最 小 定 时 器 分 辨 率; ---- timeSetEvent — — 产 生 一 个 在 指 定 的 时 间 或 时 间 周 期 间 隔 内 执 行 的 定 时 器 事 件; ---- timeKillEvent — — 删 除 前 面 用timeSetEvent 产 生 的 定 时 器 事 件; ---- timeGetDevCaps — — 返 回 关 于 定 时 器 服 务 能 力 的 信 息。 ---- 下 面 就 结 合 一 段 程 序 来 具 体 说 明 它 的 用 法。 这 段 程 序 的 主 要 功 能 是: 设 置 两 个 时 钟 定 时 器, 一 个 间 隔 是1 毫 秒, 一 个 间 隔 是2 秒, 每 执 行 一 次, 输 出 当 前 系 统 时 钟 值 到 文 件“cure.out”, 以 比 较 此 定 时 器 的 精 确 度。( 此 程 序 在 中 文windows95 及Microsoft VC5.0 编 译 通 过。 只 节 取 与 定 时 器 有 关 的 部 分 程 序。) #include < stdio.h > //包含所用系统函数的头文件, 如果编译有问题,可调整此语句的位置 #include < mmsystem.h > //定义1毫秒和2秒时钟间隔,以毫秒为单位 #define ONE_MILLI_SECOND1 #define TWO_SECOND 2000 //定义时钟分辨率,以毫秒为单位 #define TIMER_ACCURACY1 UINT wTimerRes_1ms,wTimerRes_2s; //定义时间间隔 UINT wAccuracy;//定义分辨率 UINT TimerID_1ms,TimerID_2s;//定义定时器句柄 CCureApp::CCureApp() ∶ fout("cure.out", ios::out)//打开输出文件“cure.out” { // TODO: add construction code here, // Place all significant initialization in InitInstance //给时间间隔变量赋值 wTimerRes_1ms = ONE_MILLI_SECOND ; wTimerRes_2s = TWO_SECOND; TIMECAPS tc; //通过函数timeGetDevCaps取出系统 的分辨率取值范围(对intel系统, 1~16毫秒),//如果无错则继续 if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR) { //分辨率的值不能超出系统的取值范围 wAccuracy = min(max(tc.wPeriodMin, TIMER_ACCURACY),tc.wPeriodMax); //调用timeBeginPeriod函数设置定时器 的分辨率,类似于for循环的步长 timeBeginPeriod(wAccuracy); //设置定时器 InitializeTimer(); } } CCureApp::~CCureApp() { //结束时钟 fout < < "结束时钟" < < endl; //删除两个定时器 timeKillEvent(TimerID_1ms); timeKillEvent(TimerID_2s); //删除设置的分辨率 timeEndPeriod(wAccuracy); } 注:使用完的定时器及分辨率一定 要删除,否则系统会越来越慢。 void CCureApp::InitializeTimer() { StartOneMilliSecondTimer(); StartTwoSecondTimer(); } //一毫秒定时器的回调函数, 类似于中断处理程序 voidPASCAL//一定要声明为全局PASCAL函数, 否则编译会有问题 OneMilliSecondProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { static int ms = 0;//定义计数器 CCureApp *app = (CCureApp *)dwUser; //取得系统时间以毫秒为单位 DWORD osBinaryTime = GetTickCount(); //输出计数器值和当前系统时间到文件 app- >fout < < ++ms < < ": 1ms : " < < osBinaryTime < < endl; } //加装1毫秒定时器 void CCureApp::StartOneMilliSecondTimer() { if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy, (LPTIMECALLBACK) OneMilliSecondProc,//回调函数 (DWORD)this,//用户自传送到回调函数的数据 /*周期调用,只使用一次用TIME_ONESHOT*/ TIME_PERIODIC)) == 0) { AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); } else//不等于0表明加装成功, 返回此定时器的句柄 fout < < "16ms计时:" < < endl; } 以下为2秒定时器的回调函 数和加装函数,与1毫秒的类似; void PASCAL TwoSecondProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { static int s = 0; CCureApp *app = (CCureApp *)dwUser; DWORD osBinaryTime = GetTickCount(); app- >fout < < "*********************** ***********************" < < endl; app- >fout < < ++s < < ": 2s : " < < osBinaryTime < < endl; } void CCureApp::StartTwoSecondTimer() { if((TimerID_2s = timeSetEvent(wTimerRes_2s, wAccuracy, (LPTIMECALLBACK) TwoSecondProc, (DWORD)this, TIME_PERIODIC)) == 0) { AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); } else fout < < "2s计时:" < < endl; } 其实多媒体计时器的原理跟SetTimer()产生计时器的原理是一样的,都是产生一个系统全局资源,运行在独立的线程中,定时到后调用回调函数区别就是多媒体计时器能够达到1ms的精度,而SetTimer()只能达到55毫秒的精度。可以參考一下:http://www2.ccw.com.cn/tips/2k01/011203_03.asphttp://www.gjwtech.com/scomm/sc2vc6highspeedcom.htmhttp://www.5xsoft.com/data/200112/2908075501.htmhttp://sanjianxia.myrice.com/vc/vc96.htmhttp://landcad.sdau.edu.cn/language/vc/vc17.html... GetTickCount();Return Values:The return value is the number of milliseconds that have elapsed since the system was started mfc 多文档程序的主窗口标题 有用过MSAcpi_ThermalZoneTemperature的朋友给指导一下 atl com组件 C++ 获取最顶层窗口 'RGB_GETRED' : undeclared identifier 用所有的分,请教关于SDI窗口的三个问题,谢谢! 怎么创建一个文件夹呀 如何获得目录下的文件列表信息? 对话框打印问题 若何计算time的加法??? 在windows sdk 编程中,SetCapture( )函数是什么意思? 如何取得一个进程占用内存的大小?
我把上次的方法搬出来参考
1)timer
2)gettickcount settickcount
3)sleep
4)创建一个超时的event。
Win95下高精度定时器的实现
国防科技大学机电工程与仪器系
张云洲 梁科山
---- 在工业控制软件中,数据采集和实时控制是经常性的工作。目前,工业控制
软件已经从DOS和Windows3.x平台,转到了Windows95上。然而,Windows95并不能
直接支持中断,这就意味着在DOS和Windows3.x中的定时器中断不能为我们所用。
因此,我们必须寻求新的定时方式。
---- 在C++ Builder和Delphi等典型的编程语言中,都提供了定时器控件,可以方
便地实现定时和事件响应。此外,Windows95还提供了SetTimer和KillTimer函数来
设置和删除一个定时器,在事件WM_TIMER响应函数中实现处理。然而,遗憾的是,
通过这些方式获得的Win95定时器最小只能精确到55毫秒,对于55毫秒以下的时间
精度便无能为力。这对于Win95下测控软件的开发是十分不利的。幸运的是,多媒
体定时器可以解决这一难题。
---- 以下是一个完整的多媒体定时器设计示例程序,该定时器的精度为1毫秒。该
程序的内容十分简单:按下按钮1,启动定时器,在Edit框中显示定时值(计数值
),按下按钮2则将关闭定时器。此程序在Windows95环境下,采用C++Builder3.0
编程并编译通过,但设计思想同样适用于其它高级语言。按照本程序中的实现方法
,读者将可以轻松实现自己的高精度定时器。
---- 程序清单如下:
#include < vcl.h >
#pragma hdrstop
#include "mmsystem.h" //包含多媒体定时器函数的头文件
#define MilliSecond 1 //定时间隔1毫秒
#define Accuracy 1 //系统允许的分辨率最小值
#define Min(x,y) ((x < y) ? x : y)
#define Max(x,y) ((x > y) ? x : y)
#include "HighTimerU.h"
//------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
UINT TimerID; //定义定时器句柄
int count; //定义一个变量以进行计数
int TimerAccuracy;
TForm1 *Form1;
//------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void PASCAL TimerCallProc(UINT
TimerID, UINT msg,DWORD dwUser,
DWORD dwa,DWORD dwb)
//定义定时器事件的调用函数
{
count++;
Form1- >Edit1->Text=count;
//在一个编辑框内显示计数值,即定时值
}
//---------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TIMECAPS timecaps;
int TimerResolution;
//从系统获得关于定时器服务能力的信息,
//分辨率不能超出系统许可值(1到16毫秒)
if (timeGetDevCaps(&timecaps,sizeof(
TIMECAPS))==TIMERR_NOERROR)
TimerAccuracy=Min(Max(timecaps.wPeriodMin,
Accuracy),timecaps.wPeriodMax);
timeBeginPeriod(TimerAccuracy);
//设置定时器分辨率
TimerResolution=1; //设置定时间隔为1毫秒
//产生间隔1毫秒,周期执行的定时器事件;启动定时器
TimerID = timeSetEvent(TimerResolution,TimerAccuracy,
&TimerCallProc,1,TIME_PERIODIC);
}
//-------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
timeKillEvent(TimerID); //删除定时器事件
timeEndPeriod(TimerAccuracy); //清除定时器分辨率
}
---- 多媒体定时器对实现高精度定时是很理想的工具,而且其精度是十分可靠的
。但是,多媒体定时器也并不是完美的。因为它可靠的精度是建立在对系统资源的
消耗之上的。因此,在利用多媒体定时器完成工作的同时,必须注意以下几点:
---- 1. 多媒体定时器的设置分辨率不能超出系统许可范围。
---- 2. 在使用完定时器以后,一定要及时删除定时器及其分辨率,否则系统会
越来越慢。
---- 3. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结
束之前,注意一定不能再次启动该定时器不然迅速造成死机
李 振
---- 在windows95 编 程 中 有 时 要 用 到 定 时 器 的 功 能, 大 家 常 用 的 是
通 过SetTimer 函 数 设 置 一 个 定 时 器, 在 事 件WM_TIMER 响 应 函 数 中 处
理, 然 后 用KillTimer 函 数 取 消 此 定 时 器。 但 此 种 方 式 的 定 时 器
只 能 精 确 到 大 约55 毫 秒, 对 于55 毫 秒 以 下 的 时 间 精 度 便 无 能 为
力。
---- 笔 者 在 这 里 向 大 家 提 供 一 个 可 以 精 确 到1 毫 秒 的 定 时 器 —
— 多 媒 体 定 时 器。 它 主 要 通 过 以 下 函 数 来 实 现:
---- timeBeginPeriod — — 建 立 应 用 程 序 使 用 的 定 时 器 分 辨 率;
---- timeEndPeriod — — 清 除 前 面 用timeBeginPeriod 函 数 建 立 的 最 小 定
时 器 分 辨 率;
---- timeSetEvent — — 产 生 一 个 在 指 定 的 时 间 或 时 间 周 期 间 隔 内
执 行 的 定 时 器 事 件;
---- timeKillEvent — — 删 除 前 面 用timeSetEvent 产 生 的 定 时 器 事 件;
---- timeGetDevCaps — — 返 回 关 于 定 时 器 服 务 能 力 的 信 息。
---- 下 面 就 结 合 一 段 程 序 来 具 体 说 明 它 的 用 法。 这 段 程 序 的 主
要 功 能 是: 设 置 两 个 时 钟 定 时 器, 一 个 间 隔 是1 毫 秒, 一 个 间
隔 是2 秒, 每 执 行 一 次, 输 出 当 前 系 统 时 钟 值 到 文 件“cure.out”,
以 比 较 此 定 时 器 的 精 确 度。( 此 程 序 在 中 文windows95 及Microsoft
VC5.0 编 译 通 过。 只 节 取 与 定 时 器 有 关 的 部 分 程 序。)
#include < stdio.h >
//包含所用系统函数的头文件,
如果编译有问题,可调整此语句的位置
#include < mmsystem.h >
//定义1毫秒和2秒时钟间隔,以毫秒为单位
#define ONE_MILLI_SECOND1
#define TWO_SECOND 2000
//定义时钟分辨率,以毫秒为单位
#define TIMER_ACCURACY1
UINT wTimerRes_1ms,wTimerRes_2s; //定义时间间隔
UINT wAccuracy;//定义分辨率
UINT TimerID_1ms,TimerID_2s;//定义定时器句柄
CCureApp::CCureApp()
∶ fout("cure.out", ios::out)//打开输出文件“cure.out”
{
// TODO: add construction code here,
// Place all significant
initialization in InitInstance
//给时间间隔变量赋值
wTimerRes_1ms = ONE_MILLI_SECOND ;
wTimerRes_2s = TWO_SECOND;
TIMECAPS tc;
//通过函数timeGetDevCaps取出系统
的分辨率取值范围(对intel系统,
1~16毫秒),//如果无错则继续
if(timeGetDevCaps(&tc, sizeof(TIMECAPS))
== TIMERR_NOERROR)
{
//分辨率的值不能超出系统的取值范围
wAccuracy = min(max(tc.wPeriodMin,
TIMER_ACCURACY),tc.wPeriodMax);
//调用timeBeginPeriod函数设置定时器
的分辨率,类似于for循环的步长
timeBeginPeriod(wAccuracy);
//设置定时器
InitializeTimer();
}
}
CCureApp::~CCureApp()
{
//结束时钟
fout < < "结束时钟" < < endl;
//删除两个定时器
timeKillEvent(TimerID_1ms);
timeKillEvent(TimerID_2s);
//删除设置的分辨率
timeEndPeriod(wAccuracy);
}
注:使用完的定时器及分辨率一定
要删除,否则系统会越来越慢。
void CCureApp::InitializeTimer()
{
StartOneMilliSecondTimer();
StartTwoSecondTimer();
}
//一毫秒定时器的回调函数,
类似于中断处理程序
voidPASCAL//一定要声明为全局PASCAL函数,
否则编译会有问题
OneMilliSecondProc(UINT wTimerID, UINT msg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
static int ms = 0;//定义计数器
CCureApp *app = (CCureApp *)dwUser;
//取得系统时间以毫秒为单位
DWORD osBinaryTime = GetTickCount();
//输出计数器值和当前系统时间到文件
app- >fout < < ++ms < < ": 1ms : "
< < osBinaryTime < < endl;
}
//加装1毫秒定时器
void CCureApp::StartOneMilliSecondTimer()
{
if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy,
(LPTIMECALLBACK) OneMilliSecondProc,//回调函数
(DWORD)this,//用户自传送到回调函数的数据
/*周期调用,只使用一次用TIME_ONESHOT*/
TIME_PERIODIC)) == 0)
{
AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK);
}
else//不等于0表明加装成功,
返回此定时器的句柄
fout < < "16ms计时:" < < endl;
}
以下为2秒定时器的回调函
数和加装函数,与1毫秒的类似;
void PASCAL
TwoSecondProc(UINT wTimerID, UINT msg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
static int s = 0;
CCureApp *app = (CCureApp *)dwUser;
DWORD osBinaryTime = GetTickCount();
app- >fout < < "***********************
***********************" < < endl;
app- >fout < < ++s < < ": 2s : "
< < osBinaryTime < < endl;
}
void CCureApp::StartTwoSecondTimer()
{
if((TimerID_2s = timeSetEvent(wTimerRes_2s, wAccuracy,
(LPTIMECALLBACK) TwoSecondProc,
(DWORD)this,
TIME_PERIODIC)) == 0)
{
AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK);
}
else
fout < < "2s计时:" < < endl;
}
都是产生一个系统全局资源,运行在独立的线程中,定时到后调用回调函数
区别就是多媒体计时器能够达到1ms的精度,
而SetTimer()只能达到55毫秒的精度。可以參考一下:
http://www2.ccw.com.cn/tips/2k01/011203_03.asp
http://www.gjwtech.com/scomm/sc2vc6highspeedcom.htm
http://www.5xsoft.com/data/200112/2908075501.htm
http://sanjianxia.myrice.com/vc/vc96.htm
http://landcad.sdau.edu.cn/language/vc/vc17.html
...
Return Values:
The return value is the number of milliseconds that have elapsed since the system was started