Visual+C++实现微秒级精度定时器

合集下载

VC++中使用定时器的方法

VC++中使用定时器的方法

1.启用一个定时器直接调用函数:SetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms 可以在按钮按下时启用定时器:void CTimeDlg::OnButton1(){// TODO: Add your control notification handler code hereSetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms }2.关闭定时器:可以在按钮中调用如下函数关闭某定时器: void CTimeDlg::OnButton2(){// TODO: Add your control notification handler code hereKillTimer(1); //关闭1号定时器KillTimer(2); //关闭2号定时器}3.添加定时器时间到的处理代码:1)在开发界面中Ctrl+W 进入MFCclass wizard页面2)选择Message Maps选项卡3)在Project中选择你的工程4)在object Ids:中选择C…..Dlg5)在Messages:中选择WM_TIMER,此时,Member functions中自动定位到: W OnTimer ON_WM_TIMER,6) 单击EDIT code(或双击W OnTimer ON_WM_TIMER)自动进入如下函数:void CTimeDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultswitch(nIDEvent){case 1: //1号定时器应该处理的事情//…..break;case 2: //2号定时器应该处理的事情//…..break;}CDialog::OnTimer(nIDEvent); //此句VC自动生成}秘密在VC中,定时有三种方法,一是利用WM_TIMER消息的API函数,二是使用多媒体定时器,三是多线程定时器(不知道是不是可以这样分啊)。

vc++实现非窗口类中使用定时器的方法

vc++实现非窗口类中使用定时器的方法

vc++实现非窗口类中使用定时器的方法2010-09-17 21:44:35| 分类:默认分类| 标签:非窗口回调函数|字号大中小订阅定时器在视窗系统的程式中的作用不可忽略,也随处可见。

设定一个时间间隔每0.5秒或1秒钟刷新一次时钟,这样就能完成一个简单的电子钟程式。

在不同的编程工具中定时器的用法也不同,Visual C++中也给我们提供了实现这种功能的方法,而且方法不只一种。

在窗口类中是使用定时器比较简单,用SetTimer()设置了定时器之后,并在Class Wizard中添加了WM_TIMER消息映射后,你就能在映射函数OnTimer()中添加代码实现,来定时完成你的任务,而且还支持任意多个定时器,这种方法大家可能都会用。

不过在非窗口的类中,使用定时器就没那么简单了,在类消息映射中就未找到OnTimer()方法了,类中也没有hWnd 这个属性,SetTimer()也不能象原来那样使用了,下面给出了一种既不破坏类的完整性的同时又能巧妙的使用定时器的方法。

一、实现方法在非窗口类中使用定时器,需要了解的知识比较多。

首先非窗口类中没有消息映射,也没有象CWnd 类具有的SetTimer()方法来设置定时器。

没有消息映射,就只能靠我们自己定义的回调函数来处理定时器的消息,因此大家有必要了解一下回调函数的概念。

因为回调函数只能用全局函数或静态成员函数来实现,而为了维持类的完整性,又需求使用类的静态成员函数来作为回调函数,所以我们又需要了解一下静态数据成员和静态成员函数的性质。

又因为定时器是在我们的程式中产生的,这又需要来管理定时器,所以又用到了映射表类CMap,因此介绍一下CMap的简单用法也是必不可少的。

所谓回调函数就是按照一定的形式由研发人员定义并编写实现内容,当发生某种事件时由系统或其他函数来调用的函数。

使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己编写的一个函数(也就是回调函数)的地址作为参数传递给那个函数。

C语言中如何获取毫秒级和微秒级时间

C语言中如何获取毫秒级和微秒级时间

C语言中如何获取毫秒级和微秒级时间在C语言中,获取毫秒级和微秒级时间通常需要使用系统提供的函数库来实现。

下面将介绍两种常用的方法。

clock(函数可以返回程序执行起点到调用时所使用的处理器时钟计时单元(即时钟周期数),而CLOCKS_PER_SEC常量表示每秒钟的处理器时钟计时单元数。

具体步骤如下:
5. 计算执行时间(毫秒):`double milliseconds =
(double)duration / (double)CLOCKS_PER_SEC * 1000.0;`
需要注意的是,该方法的精度取决于操作系统提供的时钟精度。

常见的操作系统时钟精度为10毫秒,因此该方法一般只能达到10毫秒级别的精度。

具体步骤如下:
5.计算程序执行的时间差值:
6. 计算执行时间(毫秒):`double milliseconds = seconds * 1000.0 + microseconds / 1000.0;`
综上所述,以上两种方法分别适用于需求不同的情况。

如果要求较高的时间测量精度,推荐使用第二种方法。

VisualC++入门实例_制作计时器——巧用定时器函数[原创]

VisualC++入门实例_制作计时器——巧用定时器函数[原创]

Visual C++入门实例_制作计时器——巧用定时器函数制作计时器——巧用定时器函数在前面讲到进度条控件的使用时,曾经用到 WM_TIMER 消息及其相应的几个函数。

在本实例中将利用 SetTimer、OnTimer 和 KillTimer 这三个函数实现可调节计时器程序。

本实例编写的计时器有倒计时和正常计时两种计时方式,还可以水平滑块调节计时的快慢。

如果需要在计时结束时发出声音提示,可以选中复选框开启蜂鸣器响功能,如图 4.49 所示。

图 4.49 定时器程序运行界面1. 三个与时间有关的函数 SetTimer、OnTimer 和 KillTimerSetTimer 函数开启一个定时器,定义如下:UINT SetTimer( UINT nIDEvent, UINT nElapse,void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) ); nIDEvent 是定时器的标识符,nElapse 是定时器触发周期,单位是百万分之一秒,最后一个参数常设为 NULL。

每个触发周期结束,定时器都会发出 WM_TIMER 消息。

OnTimer 是 WM_TIMER 的消息响应函数,定义如下:void CEx17Dlg::OnTimer(UINT nIDEvent);nIDEvent 用于判别是哪个定时器发出的 WM_TIMER 消息。

KillTimer 函数关闭一个定时器,定义如下:BOOL KillTimer(UINT nIDEvent);nIDEvent 用于判别关闭哪个定时器。

2. 创建一个基于对话框的工程(01)打开菜单“File→New”,弹出新建(New)对话框。

(02)在工程(Projects)选项卡中选择“MFC AppW izard(exe)”,在右边的工程名(ProjectName)栏中输入“ex17”,在路径(Location)栏选择工程路径,然后单击确认(OK)按钮。

关于vc++时间函数的总结

关于vc++时间函数的总结

MFC提供了两个日期和时间类CTime和CTimeSpan,分别代表相对时间和绝对时间。

CTime是基于格林威治平均时间(GMT)的,本地的时间由环境变量TZ决定。

CTimeSpan代表了时间间隔。

CTime类由下列成员函数:CTime()创建一个CTime对象。

GetCurrentTime()由当前时间创建一个CTime对象。

GetTime()由CTime对象返回一个time_t变量。

GetYear()获取CTime对象代表的年。

GetMonth()获取CTime对象代表的月。

GetDay() 获取CTime对象代表的日期。

GetHour() 获取CTime对象代表的小时。

GetMinute()获取CTime对象代表的分。

GetSecond() 获取CTime对象代表的秒。

GetDayOfWeek() 获取CTime对象代表的周日,1代表周日,2代表周-等等。

Format() 将字符串转换成一个基于本地时区的格式字符串。

FormatGmt() 将字符串转换成一个基于UTC(世界时)的格式字符串。

operator = 赋予新的时间。

operator + 增加CTime和CTimeSpan对象。

operator –减小CTime和CTimeSpan对象。

operator += CTime对象加一个CTimeSpan对象。

operator -= CTime对象减一个CTimeSpan对象。

operator == 比较两个绝对时间是否相等。

operator != 比较两个绝对时间是否不相等。

operator < 比较两个绝对时间,是否前一个大于后一个。

operator > 比较两个绝对时间,是否前一个小于后一个。

operator >= 比较两个绝对时间,是否前一个大于等于后一个。

operator <= 比较两个绝对时间,是否前一个小于等于后一个。

把收获总结如下:首先看几个函数的原型的声明(在time.h中):clock_t clock( void ) clock_t是用来保存时间的数据类型,是long 型double difftime(time_t time1, time_t time0); 取时间间隔的函数time_t time(time_t * timer); 日历时间函数char * asctime(const struct tm * timeptr); 将tm 类的时间结构转化为固定时间格式char * ctime(const time_t *timer); 将日历时间转化为固定时间格式time_t mktime(struct tm * timeptr); 以年、月、日、时、分、秒等分量保存的时间结构struct tm * gmtime(const time_t *timer); 将日历时间转化为格林尼治时间struct tm * localtime(const time_t * timer); 将日历时间转化为当地时间tm 的定义:struct tm {int tm_sec; /* 秒–取值区间为[0,59] */int tm_min; /* 分- 取值区间为[0,59] */int tm_hour; /* 时- 取值区间为[0,23] */int tm_mday; /* 一个月中的日期- 取值区间为[1,31] */int tm_mon; /* 月份(从一月开始,0代表一月)- 取值区间为[0,11] */int tm_year; /* 年份,其值等于实际年份减去1900 */int tm_wday; /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推*/int tm_yday; /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推*/int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。

VC高精度多媒体定时器的使用

VC高精度多媒体定时器的使用
timeGetSystemTime, timeGetTime, timeSetEvent,timeKillEvent ,midiOutShortMsg, midiOutLongMsg,OutputDebugString。同时也不要使用完成时间很
长的 API 函数,程序尽可能简短。
使用以上一组函数就可以完成毫秒级精度的计时和控制(在 C++Builder 中使用时要将 头文件 mmsystem.h 加到程序中)。由于将定时控
该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一 旦被激活,便调用指定的回调函数,成功后返回事件的标识符代码,否则返回 NULL。参数 说明如下:
uDelay:以毫秒指定事件的周期。 UResolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为 1ms。 LpTimeProc:指向一个回调函数。 DwUser:存放用户提供的回调数据。 FuEvent:指定定时器事件类型: TIME_ONESHOT:uDelay 毫秒后只产生一次事件 TIME_PERIODIC :每隔 uDelay 毫秒周期性地产生事件。
22 g_wTimerID = timeSetEvent(6, wTimerRes, (LPTIMECALLBACK)SendFun, (DWORD )this, TIME_PERIODIC);
23 if(g_wTimerID == 0)
24
return false;
25
26 return true;
/******************************************************************\ function name : CreateTimer desc : create a realtime timer argument void ret code [HANDLE] ,the handle of the timer

Visual+C++实现微秒级精度定时器

Visual+C++实现微秒级精度定时器

Visual C++实现微秒级精度定时器在工产控制系统中,有许多需要定时完成的操作,如:定时显示当前时间,定时刷新屏幕上的进度条,上位机定时向下位机发送命令和传送数据等。

特别是在对控制性能要求较高的控制系统和数据采集系统中,就更需要精确定时操作。

众所周知,Windows是基于消息机制的系统,任何事件的执行都是通过发送和接收消息来完成的。

这样就带来了一些问题,如一旦计算机的CPU被某个进程占用,或系统资源紧张时,发送到消息队列中的消息就暂时被挂起,得不到实时处理。

因此,不能简单地通过Windows消息引发一个对定时要求严格的事件。

另外,由于在Windows中已经封装了计算机底层硬件的访问,所以要想通过直接利用访问硬件来完成精确定时,也比较困难。

在实际应用时,应针对具体定时精度的要求,采取与之相适应的定时方法。

本实例实现了一中微秒级的精确定时,程序的界面提供了两个"Edit"编辑框,其中一个编辑框输入用户理想的定时长度,另外一个编辑框返回实际的时间长度,经过大量的实验测试,一般情况下误差不超过5个微秒。

程序的运行界面如图一所示:图一、实现微秒级的精确定时器一、实现方法Visual C++中提供了很多关于时间操作的函数,利用它们控制程序能够精确地完成定时和计时操作。

Visaul C++中的WM_TIMER消息映射能进行简单的时间控制。

首先调用函数Se tTimer()设置定时间隔(退出程序时别忘了调用和SetTimer()配对使用的KillTimer ()函数),如SetTimer(0,200,NULL)即为设置200ms的时间间隔。

然后在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成到达定时时间的操作。

这种定时方法非常简单,但其定时功能如同Sleep()函数的延时功能一样,精度非常低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况。

如何在VC中定时

如何在VC中定时

如何在VC中定时?想在程序中使用定时功能,该怎么做?就是wm_timer里,你知道了吧,按ctrl+w找wm_timer网友:zkoperater第一种方法:创建timer:settime(1,1000,null);销毁timer:killtime(1);在ontime里做你想做的事情,如果你想每秒钟弹出一个messagebox,你就在ontime里面写messagebox("hi");由于ontime的消息也要放在消息队列里,所以这种方法有少许误差。

第二种方法:开一个线程,然后用gettickcount,线程里面代码如下:int ncounter=0;int nt1=gettickcount;int nt2;while(1){nt2=gettickcount();if(nt2-nt1>1000){//...messagebox("hi");//...nt1+=1000;}}这种方法更精确。

第三种方法:和第二种方法类似,但是用getporformancefrequency,getporformancecounter代替gettickcount这种方法更更更精确。

网友:kulukyo用settimer可以,但是不是很精确,它是以55ms为一个时钟周期的。

比如你定了小于55ms的时间,settimer(1,40,null)其实是到了55ms的时候才触发,但是对于一般的应用,已经够了,如果需要精确定时,可以使用multimedia timers,但是比较耗资源可以在msdn中索引“multimedia timers”找到相关介绍。

C语言精确微秒级的延时

C语言精确微秒级的延时

65535-(UБайду номын сангаасNT)(SYSCLK/1000000) * (UINT)(time_us) 定 时 器 需 要 TM_LODAE 指令周期才会溢出。该单片机的一个指令周期就是一个时 钟周期
TMR2H = TM_LODAE>>8; TMR2L = TM_LODAE&0x00FF;置定时器寄存器 的初值
TR2 = 1; 启动单片机计时
while (!TF2H); 等待定时器 2 寄存器溢出
TR2 = 0;停止计时
//-----------------------------------------------------------------------------
void Delay_us (unsigned char time_us)
{ unsigned long int TM_LODAE; TR2 = 0; // Stop timer TF2H = 0; // Clear timer overflow flag TM_LODAE = 65535-(UINT)(SYSCLK/1000000) * (UINT)(time_us); // TMR2 = -( (UINT)(SYSCLK/1000000) * (UINT)(time_us) ); TMR2H = TM_LODAE>>8; TMR2L = TM_LODAE&0x00FF; TR2 = 1; // Start timer while (!TF2H); // Wait till timer overflow occurs TR2 = 0; // Stop timer
C 语言精确微秒级的延时
在使用 C 语言编程时延时程序是非常常见的,但是实现一个精确 的延时是不太容易的,在给一个朋友的公司产品做维护时,发现一段 代码,可以实现微妙级的延时。看起来代码非常简单。但是我以前没 有想到过。我们一起来看看这段代码。

VC++获取系统时间、程序运行时间(精确到秒,毫秒)的五种方法

VC++获取系统时间、程序运行时间(精确到秒,毫秒)的五种方法

VC++获取系统时间、程序运⾏时间(精确到秒,毫秒)的五种⽅法1.使⽤CTime类(获取系统当前时间,精确到秒)CString str;//获取系统时间CTime tm;tm=CTime::GetCurrentTime();//获取系统⽇期str=tm.Format("现在时间是%Y年%m⽉%d⽇ %X");MessageBox(str,NULL,MB_OK);a,从CTimet中提取年⽉⽇时分秒CTime t = CTime::GetCurrentTime(); int d=t.GetDay(); //获得⼏号 int y=t.GetYear(); //获取年份 int m=t.GetMonth(); //获取当前⽉份 int h=t.GetHour(); //获取当前为⼏时 int mm=t.GetMinute(); //获取分钟 int s=t.GetSecond(); //获取秒 int w=t.GetDayOfWeek(); //获取星期⼏,注意1为星期天,7为星期六b,计算两段时间的差值,可以使⽤CTimeSpan类,具体使⽤⽅法如下:CTime t1( 1999, 3, 19, 22, 15, 0 );CTime t = CTime::GetCurrentTime();CTimeSpan span=t-t1; //计算当前系统时间与时间t1的间隔int iDay=span.GetDays(); //获取这段时间间隔共有多少天int iHour=span.GetTotalHours(); //获取总共有多少⼩时int iMin=span.GetTotalMinutes();//获取总共有多少分钟int iSec=span.GetTotalSeconds();//获取总共有多少秒c,获得当前⽇期和时间,并可以转化为CStringCTime tm=CTime::GetCurrentTime();CString str=tm.Format("%Y-%m-%d");//显⽰年⽉⽇2.使⽤GetLocalTime:Windows API 函数,获取当地的当前系统⽇期和时间(精确到毫秒) 此函数会把获取的系统时间信息存储到SYSTEMTIME结构体⾥边typedef struct _SYSTEMTIME{WORD wYear;//年WORD wMonth;//⽉WORD wDayOfWeek;//星期:0为星期⽇,1为星期⼀,2为星期⼆……WORD wDay;//⽇WORD wHour;//时WORD wMinute;//分WORD wSecond;//秒WORD wMilliseconds;//毫秒}SYSTEMTIME,*PSYSTEMTIME;例:SYSTEMTIME st;CString strDate,strTime;GetLocalTime(&st);strDate.Format("%4d-%2d-%2d",st.wYear,st.wMonth,st.wDay);strTime.Format("%2d:%2d:%2d",st.wHour,st.wMinute,st.wSecond) ;AfxMessageBox(strDate);AfxMessageBox(strTime);3.使⽤GetTickCount:从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD。

VC++中使用定时器的方法

VC++中使用定时器的方法

1.启用一个定时器直接调用函数:SetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms 可以在按钮按下时启用定时器:void CTimeDlg::OnButton1(){// TODO: Add your control notification handler code hereSetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms }2.关闭定时器:可以在按钮中调用如下函数关闭某定时器: void CTimeDlg::OnButton2(){// TODO: Add your control notification handler code hereKillTimer(1); //关闭1号定时器KillTimer(2); //关闭2号定时器}3.添加定时器时间到的处理代码:1)在开发界面中Ctrl+W 进入MFCclass wizard页面2)选择Message Maps选项卡3)在Project中选择你的工程4)在object Ids:中选择C…..Dlg5)在Messages:中选择WM_TIMER,此时,Member functions中自动定位到: W OnTimer ON_WM_TIMER,6) 单击EDIT code(或双击W OnTimer ON_WM_TIMER)自动进入如下函数:void CTimeDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultswitch(nIDEvent){case 1: //1号定时器应该处理的事情//…..break;case 2: //2号定时器应该处理的事情//…..break;}CDialog::OnTimer(nIDEvent); //此句VC自动生成}秘密在VC中,定时有三种方法,一是利用WM_TIMER消息的API函数,二是使用多媒体定时器,三是多线程定时器(不知道是不是可以这样分啊)。

用Visual C++ 6.0 实现高精度定时器

用Visual C++ 6.0 实现高精度定时器

用Visual C++ 6.0 实现高精度定时器
吴正平;熊晓东;姜吉发;魏斌
【期刊名称】《石油天然气学报》
【年(卷),期】2002(024)003
【摘要】采用Visual C++ 6.0中的GetTickCount()函数或QueryPerformance Frequency()函数和QueryPerformanceCounter()函数进行计时,再通过创建一个工作者线程 ,实现了定时精度为1 ms、最小定时时间小于55 ms的高精度定时器.【总页数】2页(P87-88)
【作者】吴正平;熊晓东;姜吉发;魏斌
【作者单位】江汉石油学院电子与信息工程系,湖北,荆州,434023;江汉石油学院电子与信息工程系,湖北,荆州,434023;辽河石油勘探局测井公司,辽宁,盘锦,124011;辽河石油勘探局测井公司,辽宁,盘锦,124011
【正文语种】中文
【中图分类】TP311.1
【相关文献】
1.基于Visual C++ 6.0 的多层前馈神经网络训练系统的实现 [J], 徐建安;张铭钧;郑金兴
2.在Visual C++ 6.0下采用多线程实现远程数据采集的方法 [J], 杨立环;吴希再
3.在Visual C++ 6.0中实现复数四则运算 [J], 李澄举
4.利用Visual C++ 6.0实现多线程编程 [J], 武雅丽
5.基于Visual C++的1780定时器采集卡内部晶振定时的实现 [J], 傅瑶;薛旭成;郝伟;孙雪晨;姜肖楠;韩诚山
因版权原因,仅展示原文概要,查看原文内容请购买。

VC中定时器用法

VC中定时器用法

关于WM_TIMER消息
wParam为计时器的ID;如果需要设定多个计时器,那么对每个计时器都使用不同的计时器ID。wParam的值将随传递到窗口过程中的WM_TIMER消息的不同而不同。
lParam为指向TimerProc的指针,如果调用SetTimer时没有指定TimerProc(参数值为NULL),则lParam为0(即NULL)。
关于SetTime建立的timer的ID,如果hWnd非NULL,返回一个非0整数,如果SetTimer调用失败则返回0
KillTimer的函数原型为:BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent ) ; 参数意义同SetTimer。
#define ID_TIMER 1
SetTimer(hWnd,ID_TIMER,1000,NULL) ;
KillTimer(hWnd,ID_TIMER) ;
方法二:调用SetTimer时指定窗口句柄hWnd,nIDEvent中指定计时器ID,lpTimerFunc参数不为NULL而指定为TimerProc函数的指针。这种方法使用TimerProc函数(名字可自定)处理WM_TIMER消息:
可见,计时器并不能严格按照指定的时间间隔发送WM_TIMER消息,它总要相差那么几毫秒。
即使忽略这几个毫秒的差别,计时器仍然不精确。请看原因二:
WM_TIMER消息放在正常的消息队列之中,和其他消息排列在一起,因此,如果在SetTimer中指定间隔为1000毫秒,那么不能保证程序每1000毫秒或者989毫秒就会收到一个WM_TIMER消息。如果其他程序的执行事件超过一秒,在此期间内,您的程式将收不到任何WM_TIMER讯息。事实上, Windows对WM_TIMER消息的处理非常类似于对WM_PAINT消息的处理,这两个消息都是低优先级的,程序只有在消息队列中没有其他消息时才接收它们。

Visual C++语言:定时器应用

Visual C++语言:定时器应用
);
KillTimer函数 ❖功能:销毁定时器
2020/12/12
BOOL KillTimer( HWND hWnd, // 安装定时器的窗口的句柄 UINT uIDEvent // 定时器标识符
);
定时器回调函数
2020/12/12
❖VOID CALLBACK TimerProc( HWND hwnd, // 与定时器关联的窗口句柄 UINT uMsg, // WM_TIMER消息号 UINT idEvent, // 定时器标识符 DWORD dwTime // 当前系统时间
);
WM_TIMER消息
❖字参数:wParam 定时器标识
❖长字参数:lParam 定时器回调函数地址 (TIMERPROC *) lParam
2020/12/12
应用举例
2020/12/12
定时器的应用
SetTimer函数
202imer(
HWND hWnd, // 与定时器关联的窗口句柄 UINT nIDEvent, // 定时器标识符 UINT uElapse, // 超时值(毫秒) TIMERPROC lpTimerFunc // 回调函数地址
销毁定时器boolkilltimerhwndhwnd安装定时器的窗口的句柄uintuidevent20201212定时器回调函数voidcallbacktimerprochwndhwnd与定时器关联的窗口句柄uintumsgwmtimer消息号uintidevent定时器标识符dworddwtime20201212wmtimer消息字参数

VC++中使用定时器的方法

VC++中使用定时器的方法

1.启用一个定时器直接调用函数:SetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms 可以在按钮按下时启用定时器:void CTimeDlg::OnButton1(){// TODO: Add your control notification handler code hereSetTimer(1,500,NULL);//定义时钟1,时间间隔为500ms SetTimer(2,1000,NULL);//定义时钟2,时间间隔为1000ms }2.关闭定时器:可以在按钮中调用如下函数关闭某定时器: void CTimeDlg::OnButton2(){// TODO: Add your control notification handler code hereKillTimer(1); //关闭1号定时器KillTimer(2); //关闭2号定时器}3.添加定时器时间到的处理代码:1)在开发界面中Ctrl+W 进入MFCclass wizard页面2)选择Message Maps选项卡3)在Project中选择你的工程4)在object Ids:中选择C…..Dlg5)在Messages:中选择WM_TIMER,此时,Member functions中自动定位到: W OnTimer ON_WM_TIMER,6) 单击EDIT code(或双击W OnTimer ON_WM_TIMER)自动进入如下函数:void CTimeDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultswitch(nIDEvent){case 1: //1号定时器应该处理的事情//…..break;case 2: //2号定时器应该处理的事情//…..break;}CDialog::OnTimer(nIDEvent); //此句VC自动生成}秘密在VC中,定时有三种方法,一是利用WM_TIMER消息的API函数,二是使用多媒体定时器,三是多线程定时器(不知道是不是可以这样分啊)。

VC中实现毫秒定时器

VC中实现毫秒定时器

VC中实现毫秒定时器很久之前就想给Vckbase写点什么东西了,毕业至今,在vckbase中学了不少东西,也拿了不少代码,今天决定要回报一下,不管老婆呆会会不会拧我耳朵了。

毫秒定时器,为什么要使用毫秒定时器呢?我想原因有两个。

第一:CWnd 里面的timer不能精确到毫秒级,所以必须要写一个精确到毫秒级的。

第二:用CWnd里面的timer代价太大,因为有时我们的类根本就没有窗口,为了使用timer,而不得不从CWnd里派生。

本人写的这个mmtimer,主要是为了解决上面这两点而设计的。

再加上,这段时间看了一下设计模式,所以基本上这些代码是我这几个月来设计模式的总结,如果写得不好,敬请各位大虾指教。

运行结果如下:图一毫秒定时器好了我们先来看看实现毫秒定时器的关键技术吧。

其实异常的简单,主要用到如下几个函数,(见代码中CMMTimers)1) timeGetDevCaps,得到当前计算机的时间精度。

2) timeBeginPeriod,设定当前定时器的精确度。

例如设定为5,表示误差不会大于5毫秒。

3) timeEndPeriod. 跟2相对应,结束了定时精度.(其实我的这些代码中有没有这三个函数,效果也是一样的)4) timeSetEvent(...pfn...).开始定时,该函数中,有一个参数时回调函数指针,以及回调函数的参数,我的代码中是internalTimerProc,和m_Recoder[MMRecoder::nRes](该参数指明定时器ID,一个CMMTimers的指针)5)timeKillEvent.终止定时器。

如果对上述函数不理解也没关系,我已经把它们封装成一个类了,对了就叫CMMTimers.为了使你不必去理解上述这些函数,我作出封装,CMMTimers主要有如下几个函数接口:1)bool stopTimer(int nTimerID) 作用跟KillTimer(int nTimerID) 一样.2)bool startTimer(UINT period,CTimerListener *pListener = NULL,int nTimerID = 1,bool oneShot = FALSE);相当于SetTimer(int nTimerID).nTimerID,就是定时器ID,oneShot就是是否只运行一次,你可能会说CTimerListener是个什么东西,这个下面我再解释。

基于VisualC++6.0的Windows应用程序定时器研究

基于VisualC++6.0的Windows应用程序定时器研究

收稿日期:2012-05-03;修回日期:2012-08-08基金项目:中航科学基金(20110181006)作者简介:王鹏飞(1982-),男,河南平顶山人,工程师,主要研究方向为雷达信号处理㊁嵌入式系统设计㊂基于Visual C ++6.0的Windows应用程序定时器研究王鹏飞,王㊀鹏(中国空空导弹研究院,河南洛阳471009)摘㊀要:Visual C++6.0是Window 平台下最为流行的编程工具之一㊂在测控系统中,PC 机与各种嵌入式系统之间的接口控制也通常采用VC6.0完成㊂然而嵌入式系统通常对时序有较高的要求,Windows 系统则并非实时操作系统㊂因此如何在VC6.0中实现各种不同精度的定时功能就成为许多面向嵌入式系统的VC6.0开发关键环节㊂文中研究和比较了VC6.0平台下各种定时器的用法和性能㊂根据试验结果,并针对某实际工程需要,采用时间戳计数器实现了一种微秒级定时器㊂通过测试,该定时器可以实现微秒级高精度定时,与某嵌入式系统平台配合良好,并通过了设备验收,证明了其设计有效性㊂关键词:定时器;精确定时;Windows 平台;嵌入式系统中图分类号:TN911.3㊀㊀㊀㊀㊀㊀文献标识码:A㊀㊀㊀㊀㊀㊀文章编号:1673-629X (2013)02-0044-05doi:10.3969/j.issn.1673-629X.2013.02.011Windows Platform Application Timer ResearchBased on Visual C++6.0WANG Peng -fei ,WANG Peng(China Airborne Missile Academy ,Luoyang 471009,China )Abstract :Visual C ++6.0(VC 6.0)is one of the most popular development environments for Windows platform.Therefore ,most of in-terface control of measurement &control system between embedded system and PC were also developed via VC 6.0.However ,since high -precision timing is often necessary for embedded system ,and Window operation system (OS )isn 't real -time OS.How to design timerto meet different embedded system requirement becomes a vital process for VC 6.0development.In this paper ,all kinds of timer design strategies were introduced and presented ,following with their comparison.Finally ,according to one project demand ,based on CPU time stamp counter technique ,a microsecond -level timer was presented.Whole project has been validated ,therefore this times strategy 's effect was also proved.Key words :timer ;precise timing ;windows platform ;high precision0㊀引㊀言随着信息和自动化测试技术的进步,利用计算机实现的数字控制技术已经广泛应用于工业生产中㊂典型的测控系统通常由PC 机㊁嵌入式系统板卡,以及上位机程序组成,而这些测控系统在采集数据㊁输出信号和刷新屏幕过程中都需要定时器,尤其是有实时性要求的数据采集控制系统,其对高精度定时器的要求就更为迫切[1]㊂VC 6.0作为微软公司于1998年推出的可视化编程工具,长期以来占据着Windows 平台下主流开发环境的地位㊂虽然此后微软又推出VC 6.0的更新版本,如VS 2005㊁VS 2008,直至最新的VS 2011,但VC 6.0仍以其强大的生命力在Windows 平台下占有重要席位[2],文中也正是在VC 6.0下完成各种定时器的设计㊂普通的Windows 系统定时器每秒钟只能产生18个定时信号,其定时精度仅为数十ms 数量级[3,4],这种精度只可满足一般桌面应用程序的定时需求,但在面向测控㊁嵌入式系统接口控制等领域时,其弊端就会充分暴露,而且随着时间变化,这种定时方式带来的累积误差会急剧增大,当定时中断要完成的任务较多时,两者的差值将更大㊂从Windows 的工作原理上分析,其程序的运行机制实际上是消息循环机制,如果某进第23卷㊀第2期2013年2月㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀计算机技术与发展COMPUTER TECHNOLOGY AND DEVELOPMENT㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀Vol.23㊀No.2Feb.㊀2013程已经占用了当前CPU,整个消息队列中的其他所有消息就不得不处于挂起状态,进而使这些程序得不到及时响应,最终导致定时精度的降低㊂因此,有必要对Windows下不同精度的定时器设计进行研究㊂文中详细说明了VC6.0平台下毫秒级和微秒级定时器的实现方法及其误差范围㊂1㊀常用定时方法1.1㊀Windows系统自带定时器该方法主要是采用SetTimer API函数,其原型及说明如下:UINT_PTR SetTimer(HWND hWnd,//窗口句柄UINT_PTR nIDEvent,//定时器IDUINT uElapse,//时间间隔,单位为毫秒TIMERPROC lpTimerFunc//回调函数,可留空);使用示例:SetTimer(m_hWnd,1,500,NULL);该函数调用即实现了一个每0.5秒触发一次的定时器㊂此外,如果是在MFC程序中使用,由于SetTimer已经被封装在CWnd类中,调用时可不指定窗口句柄,如UINT SetTimer(1,100,NULL)即可㊂该函数的返回值为此定时器的ID号㊂使用SetTimer()申请定时器资源后,其中断响应程序为OnTimer()函数,用户只需要在该函数中加入处理代码即可㊂如果不再需要定时器,用户可通过KillTimer()函数调用删除该定时器及占用资源㊂总体上看,该方法使用很简单,而且可以支持多个定时器并行处理㊂在定时器定时时间到时,Windows 系统会向应用程序发送WM_TIMER消息,并由用户在OnTimer()函数中处理㊂但其缺点也很明显:当程序定时过程中遭遇到系统忙时,很可能会导致定时时间已到但定时器仍未响应的结果㊂此外,该方案受限于系统时钟,定时精度很低,最好情况下也只能达到数十毫秒[5,6]㊂因此,这种定时思路虽然具有使用简单的优点,但一般只能用于某些精度要求不高的系统中㊂1.2㊀sleep()函数该方案采用sleep()函数达到延时的目的,它的定时最小单位也同样是毫秒㊂在MSDN文档中,该函数的最小可用参数为1ms,但经实际测试,该函数的最小延时精度在30ms以上,即sleep(1)和sleep(30)实现的延时效果是相同的㊂因此,该方法精度也非常低,而且采用sleep函数的一个重要缺点是在延时期间不能处理其他消息,如果延时时间过长,其表现形式如同系统死机,此时CPU的占用率也非常高㊂总体上看,sleep()函数也只能用于精度要求不高的延时程序中㊂1.3㊀GetTickCount()函数GetTickCount()函数可返回从计算机操作系统启动后到被调用时刻所经过的毫秒数,其返回值是DWORD类型㊂因此,利用其返回值,即可实现定时功能,下面给出了一个示例代码,实现了200ms的精确定时功能[7]㊂DWORD Start_t,Stop_t;Stop_t=GetTickCount();While(1){Start_t=Stop_t;ʊ上一次的中止值变成新的起始值do{//用户自定义代码Stop_t=GetTickCount();}while(Stop_t-Start_t<100);//检测定时时间是否已到}GetTickCount()函数的定时精度要比SetTimer()和GetTickCount()函数相对较高,可适用于要求更高一级的应用场合㊂1.4㊀timeGetTime()或timeGetSystemTime()函数timeGetTime()和timeGetSystemTime()均为多媒体库函数㊂首先介绍timeGetTime()函数,它返回了从系统启动所经过的时间,其函数原型为: DWORD㊀timeGetTime(void)该函数的最大计数周期为232ms(约49.71天),如果达到了最大计数周期,会从零重新开始累加㊂用户可通过查询方式来建立定时循环,进而控制定时事件㊂该函数使用也相对简单,同时定时精度亦可满足一般场合需求㊂但是,在采用轮询的方式进行查询以实现定时功能时,会在相当程度上增加程序资源开销,如果本来资源就很紧张,很明显该方法是不宜采用的[8,9]㊂timeGetSystemTime()的功能和用法类似,不再详述㊂1.5㊀多媒体定时器Windows中提供了高精度定时器的底层API支持,使应用程序可以得到周期性的时间中断,无论运行什么应用程序,操作系统都能在多媒体定时器事件到来时打断该程序而先去调用定时器的回调函数[10,11]㊂在Windows的多媒体扩展库中,提供了一系列定时器操作函数,分别说明如下: timeGetDevCaps():用于获取定时器的服务能力参数;timeBeginPeriod():用于设置定时器的定时精度; timeSetEvent():用于设置定时间隔并启动定时器;㊃54㊃㊀第2期㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀王鹏飞等:基于Visual C++6.0的Windows应用程序定时器研究timeKillEvent():用于删除定时事件; timeEndPeriod():用于释放定时器资源㊂下面给出使用该方法的步骤:1)调用timeGetDevCaps()函数,获取定时器服务能提供的最大和最小事件周期等参数;2)调用函数timeBeginPeriod(),设置定时器的最小计时精度,可由用户根据使用场合自行设定; 3)调用函数timeSetEvent(),初始化并启动定时器事件;然后明确定时器的周期㊁精度㊁以及回调函数名称;4)不需要使用定时器时,调用timeKillEvent()函数,以删除定时器事件;5)最后调用函数timeEndPeriod(),删除此前通过函数timeBeginPeriod()建立的最小定时器精度㊂这种方法能保证定时中断得到实时响应,最高定时精度可达到1ms,但使用时要注意的是该方法占用的资源较多㊂2㊀高精度定时器设计2.1㊀基于系统计数定时器VC6.0提供了系统函数QueryPerformanceFrequen-cy()和QueryPerformanceCounter(),编程者可通过这两个函数调用直接访问系统计数器[12]㊂首先介绍这两个函数的原型: BOOLQueryPerformanceFrequency(LARGE_INTE-GER*lpFrequency); BOOLQueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCounter)该方法的使用方法介绍如下:在定时之前,首先调用QueryPerformanceFrequency()函数,以获取机器内部定时器的时钟频率fCLK㊂然后在需要严格定时的事件前后均调用QueryPerformanceCounter()函数,将两次调用函数的*lpPerformanceCounter变量计数差与时钟频率fCLK相除,则可得到两次调用函数期间所经历的精确时间㊂2.2㊀基于CPU时间戳定时器该方案是最为底层的解决方案,它是采用的CPU 内建硬件寄存器㊂事实上,在目前使用所有的主流CPU芯片中均有一个时间戳计数器,该计数器以64位Unsigned Int的格式记录了自启动后经过的时钟周期数㊂它以CPU主频为基准计数,而考虑到现在的CPU 主频已经得到了突飞猛进的发展,普遍都在数GHz以上,因此,该计时器的计量精度极高,理论上可以达到纳秒级的精度[13]㊂要访问该时间戳计数器,传统的API和MFC函数是不直接支持的㊂但可以通过汇编指令RDTSC实现㊂该指令可将时间戳计数器的值保存在EDX:EAX寄存器对中㊂而在Windows系统下,EDX:EAX寄存器对正是C++程序保存函数返回值的专用寄存器㊂因此,只需要把这条指令看成一条普通的函数调用即可㊂读取时间戳计数器的参考C++/汇编混合代码: __int64GetTSC_cycle()//返回CPU当前时钟周期数{__int64Cnt;__asm㊀RDTSC;__asm㊀mov DWORD PTRCnt,EAX__asm㊀mov DWORD PTR(Cnt+4),EDX return Counter;}为了使用GetTSC_cycle函数完成精确定时功能,首先应获取系统的中央处理器CPU的真实频率,一种方便且常用的方法具体介绍如下:1)调用QueryPerformanceFrequency(),首先得到系统内部自带定时器的基准时钟频率f1;2)调用QueryPerformanceCounter(&S1),读取系统计数值;3)调用t1=GetTSC_cycle()读取当前CPU的时间戳计数器值;4)调用Sleep(2000)函数延时约2秒,这是为了保证计算样本足够多,用户也可设置为其它合适的时间;5)调用QueryPerformanceCounter(&S2),读取高精度计数器值;6)再次调用t2=GetTSC_cycle(),读取当前CPU 时间戳计数器值;7)CPU频率等于:(t2-t1)ˑf1/(S2-S1)㊂利用上述方式得到CPU的频率后,利用时间戳计数器,即可设计出所需的定时器㊂由于该方案直接采用CPU的时间戳计数器进行定时,因此其精度是各种方案中最高的,可达纳秒级,适合高精度定时场合㊂3㊀定时器精度综合比较前文给出了VC平台下各种常用的定时器设计方法,并分析了其各自的工作原理㊂但为了详细比较各定时器的性能,还需要对不同方案的定时间隔进行测量㊂由于CPU时间戳寄存器精度最高,因此选用该方案来测量各定时器的性能㊂以下详述测试方法:1)启动待测量定时器,设定定时器服务程序;2)在每次进入定时器服务程序时,均读取CPU时间戳计数器的值并记录在专用数组中,定时器运行1500个周期后停止;3)统计数组中相邻元素之差,此即为采用该定时器实际的定时间隔㊂本测试中,将定时间隔设置为1ms,各定时器测㊃64㊃㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀计算机技术与发展㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀第23卷图1㊀常规定时器测量精度图2㊀sleep定时器测量精度图3㊀GetTickCount ()定时器测量精度图4㊀timeGetTime ()定时器测量精度图5㊀多媒体定时器测量精度图6㊀基于系统计数定时器测量精度量的实际间隔时间如图1~6所示,图中,横轴代表进入定时器中断次数,纵轴则代表实际定时时间㊂从图中可以看出,常规定时器的最小定时间隔大约16ms,而sleep㊁GetTickCount 和timeGetTime 定时器的精度也都在15ms 左右,这些定时器显然不能用于精确定时㊂多媒体定时器的性能同样不稳定,在开始的大约50个周期内其定时间隔接近于0,此后定时器方能基本开始稳定工作,但即使如此,仍存在周期性的波动,波动周期大约40ms 此时定时间隔可达2ms㊂同样地,在使用基于系统计数定时器和基于CPU 时间戳定时器时也存在不稳定的现象,但持续时间明显短于多媒体定时器㊂此后,配合外部测试设备,又对这两种定时器进行了单独测试,证实这两种高精度定时器的定时误差分别为1μs 和0.1μs㊂在某雷达信号处理机测试设备中,需要实现PC 机与某VPX 系统板卡的高精度数据采集,且定时误差不能超过1μs㊂因此,采用时间戳定时器方案,很好地完成了数据定时采集任务,该系统目前已经通过设备验收,这也证实了时间戳定时器方案的有效性㊂4 结束语VC6.0作为目前最为流行的Windows 环境开发平台,在各种测控系统㊁实时数据采集系统中均得到了广㊃74㊃㊀第2期㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀王鹏飞等:基于Visual C++6.0的Windows 应用程序定时器研究泛应用,而在这些系统中,通常需要与嵌入式系统板卡进行各种高精度定时数据采集㊁处理等操作㊂因此,需要在VC 中方便地实现高精度定时器㊂因此,文中对VC 平台下各种定时器的设计进行了总结,并对其精度进行了详细测试㊂结果证实:通常的VC 定时器方案定时误差均在数十毫秒以上,根本无法满足高精度定时要求㊂而如果对定时精度要求较高,则需要采用CPU 自带的硬件寄存器完成定时功能,如文中2.1㊁2.2所示,此时其精度可达微秒级甚至更好㊂在某雷达信号处理机测试设备中,也正是采用2.2所示的时间戳定时器方案才达到了设计要求,并最终通过系统验收㊂总体上,Windows 系统常规定时器使用简单方便,但定时时间越短误差越大,适合于定时时间长,精度要求低的场合㊂sleep㊁GetTickCount 和timeGetTime 定时器精度与常规定时器性能相当㊂多媒体定时器可获得最高1ms 的定时精度,但需占用较多资源㊂基于系统计数定时器和CPU 时间戳的定时器具有微秒级的定时精度,且具有很高的稳定性,相应地,其缺点是资源占用率高,比较适用于对定时精度要求高的程序场合,如实时仿真和数据采集等㊂而且,事实上以上各种方法并不仅局限于VC 平台本身,因而在不同的软件开发平台下,各种定时方法均有其各自的优越性,具体应用时应根据实际的需要合理地进行选择,在定时器精度和系统开销之间取得较好的平衡㊂参考文献:[1]㊀卓红艳,赵㊀平.基于VC++的实时数据采集系统中定时器的使用与比较[J].现代电子技术,2007,18(2):129-132.[2]㊀Zhou Xuejun.Applied Mechanics and Materials[J].Applied Mechanics and Materials,2011,93(9):1795-1800.[3]㊀Zhu Yongguang,Sun Zhengshun,Zhao Nanyuan.Video Cap-ture Program Based on Visual C ++and the Application of Timer[J].Computer Engineering and Applications,2002,20(12):128-132.[4]㊀Tang Hongzhong,Huang Huixian,Yin Lin.Application of VC++DLL Timer in Design of Industrial Control Software [J].Ordnance Industry Automation,2003,18(6):781-786.[5]㊀郭占社,孟永钢,苏才钧.基于Windows 的精确定时技术及其在工程中的应用[J].哈尔滨工业大学学报,2005,18(12):38-41.[6]㊀姚㊀晔,胡益雄.VC++应用程序精确定时方法的实现[J].计算机系统应用,2001,22(9):192-195.[7]㊀何㊀斌,韦㊀工.基于多媒体时钟的定时控制[J].舰船电子工程,2006,26(4):4-8.[8]㊀洪锡军,李从心.Windows 下高精度定时的实现[J].计算机应用研究,2008,14(3):147-150.[9]㊀何㊀斌,耿春萍.多媒体时钟解决实时控制系统的定时[J].飞行器测控学报,2006,25(6):189-191.[10]李福华,李悦丽,段巧雄.Windows 环境下多串口控制软件设计中精确定时的实现[J].电子技术,2010,14(6):213-216.[11]刘春凤,田延岭.Windows 操作系统下的软件定时器的设计与应用[J].机电一体化,2004,10(5):39-42.[12]毕㊀业,史忠科.Windows2000下高精度定时器设计与实现[J].工业仪表与自动化装置,2007(1):53-56.[13]韩志勇,李先国.Windows 操作系统下高精度计时研究[J].计算机工程与设计,2005,24(9):췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍236-239.(上接第43页)[3]㊀Page L,Brin S,Motwani R,et al.The PageRank CitationRanking:Bringing Order to the Web [R].Stanford:StanfordInfoLab.,1999.[4]㊀曹㊀林,韩立新,吴胜利.元搜索引擎排序技术综述[J].计算机应用研究,2009,26(2):411-414.[5]㊀Regenwetter M,Tsetlin I.Approval voting and positional votingmethods:inference,relationship,examples[J].Social Choiceand Welfare,2004,22(3):539-566.[6]㊀盛宪锋,山㊀岚.基于元搜索引擎的专业式智能网络信息检索系统[J].计算机工程与设计,2004(1):69-73.[7]㊀Weiss O S.Conceptual Clustering Using Lingo Algorithm:E-valuation on Open Directory Project Data [C]//Proc of IIP-WM.[s.l.]:[s.n.],2004:369-377.[8]㊀严莉莉,王倩倩,孟㊀杰,等.基于聚类的个性化元搜索引擎设计[J].计算机技术与发展,2007,17(4):186-188.[9]㊀Bartell B T,Cottrell G W,Belew R K.Automatic Combinationof Multiple Ranked Retrieval Systems [C]//Proceedings ofthe 17th Annual International ACM-SIGIR Conference on Re-search and Development in Information Retrieval.Dublin,Ire-land:[s.n.],1994:173-181.[10]胡升泽.个性化元搜索引擎若干关键技术研究[D].长沙:国防科学技术大学,2008.[11]孟㊀星.基于Agent 的自适应信息检索系统技术研究[D].西安:西安电子科技大学,2009.[12]王㊀忠,程㊀磊.基于元搜索引擎的个性化Web 信息采集[J].计算机工程与设计,2009(13):3117-3119.㊃84㊃㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀计算机技术与发展㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀㊀第23卷基于Visual C6.0的Windows应用程序定时器研究作者:王鹏飞, 王鹏作者单位:中国空空导弹研究院,河南 洛阳 471009刊名:计算机技术与发展英文刊名:Computer Technology and Development年,卷(期):2013(2)本文链接:/Periodical_wjfz201302013.aspx。

用Visual C ++6.0实现高精度定时器

用Visual C ++6.0实现高精度定时器
现 起 来都 比较 困 难 。 笔 者 介 绍 在 Wid ws环 境 下 利 用 Vi a no s l u C“ 6 0的 GeTik o n . t c C u t( 函 数 或 ) Qu rP ro ma cF e u n y ( 函数 和 Qu r P roma cC u tr ( 函数 来 进 行 计 时 ,再 利 用 多线 ey efr n e rq e c ) ey ef r n e o ne )
Qu rP r r n e o n e ) 函数 进 行 计 时 .再 通 过 创 建 一 个 工 作 者 线 程 . 实现 了定 时 精 度 为 l ms 最 e y e f ma cG u t r( o 、
小 定 时 时 间 小 于 5 5ms的 高 精 度 定 时 器 。
[ 键 词 ] Vi a C一 6 0; 定 时器 ; 多线 程 ; 程 序 设 计 关 s l u . [ 图分 类 号 ] TP l . 中 3 11 [ 献标 识码]A 文 [ 文章 编 号 ] 10 9 5 (0 2 3— 0 7 0 0 0— 7 2 2 0 )0 0 8 2
Vi a C” 6 0中 ,为人 们 所 熟悉 的定 时 器 是 系统 定 时 器 ,它 使 用 函数 S l me )进 行 初 始 化 ,应 s l u . eTi r(
用程 序 响应 S t i r( 函数发 送 来 的消 息 w M —T ME 。该定 时器 在用 Viu l “ 6 0编 程 时使 e me ) r l R【 s a C .
程技 术 ,实 现 定 时精 度 为 lms 、最 小定 时 时 间小 于 5 的定 时器 程 序设 计 方法 。 5ms
1 设 计 步骤
Wid ws环境 虽 然不 直接 支 持硬 件 中断 ,但它 支 持 多线 程技 术 。线 程 是 W id ws系统 分 配 处 理 器 no no 时 间 资源 的基 本 单元 ,W id ws系统 是 一个 基 于 多线 程 的多任 务 系 统 。Viu l 6 0的 MF no sa C . C类 库 提 供 了多线 程编 程 的支 持 。在 MF C类 库 中 ,有 两 种类 型 的 线 程 :工 作 者 线 程 ( r e h e d 和用 户 Wo k rT ra )
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Visual C++实现微秒级精度定时器
在工产控制系统中,有许多需要定时完成的操作,如:定时显示当前时间,定时刷新屏幕上的进度条,上位机定时向下位机发送命令和传送数据等。

特别是在对控制性能要求较高的控制系统和数据采集系统中,就更需要精确定时操作。

众所周知,Windows是基于消息机制的系统,任何事件的执行都是通过发送和接收消息来完成的。

这样就带来了一些问题,如一旦计算机的CPU被某个进程占用,或系统资源紧张时,发送到消息队列中的消息就暂时被挂起,得不到实时处理。

因此,不能简单地通过Windows消息引发一个对定时要求严格的事件。

另外,由于在Windows中已经封装了计算机底层硬件的访问,所以要想通过直接利用访问硬件来完成精确定时,也比较困难。

在实际应用时,应针对具体定时精度的要求,采取与之相适应的定时方法。

本实例实现了一中微秒级的精确定时,程序的界面提供了两个"Edit"编辑框,其中一个编辑框输入用户理想的定时长度,另外一个编辑框返回实际的时间长度,经过大量的实验测试,一般情况下误差不超过5个微秒。

程序的运行界面如图一所示:
图一、实现微秒级的精确定时器
一、实现方法
Visual C++中提供了很多关于时间操作的函数,利用它们控制程序能够精确地完成定时和计时操作。

Visaul C++中的WM_TIMER消息映射能进行简单的时间控制。

首先调用函数Se tTimer()设置定时间隔(退出程序时别忘了调用和SetTimer()配对使用的KillTimer ()函数),如SetTimer(0,200,NULL)即为设置200ms的时间间隔。

然后在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成到达定时时间的操作。

这种定时方法非常简单,但其定时功能如同Sleep()函数的延时功能一样,精度非常低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况。

微软公司在其多媒体Windows中提供了精确定时器的底层API支持。

利用多媒体定时器可以很精确地读出系统的当前时间,并且能在非常精确的时间间隔内完成一个事件、函数或过程的调用。

利用多媒体定时器的基本功能,可以通过两种方法实现精确定时。

1)使用ti meGetTime()函数,该函数定时精度为ms级,返回从Windows启动开始所经过的时间。

由于使用该函数是通过查询的方式进行定时控制的,所以,应该建立定时循环来进行定时事件的控制。

2)使用timeSetEvent()函数,该函数原型如下:
该函数的参数说明如下:参数uDelay表示延迟时间;参数uResolution表示时间精度,在Windows中缺省值为1ms;lpTimeProc表示回调函数,为用户自定义函数,定时调用;参数dwUser表示用户提供的回调数据;参数fuEvent为定时器的事件类型,TIME_ONESHOT 表示执行一次;TIME_PERIODIC:周期性执行。

具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在lpTimeProc回调函数中(如:定时采样、控制等),从而完成所需处理的事件。

需要注意的是:任务处理的时间不能大于周期间隔时间。

另外,在定时器使用完毕后,应及时调用timeKillEvent()将之释放。

下面这段代码的主要功能是设置两个时钟定时器,一个间隔是1ms,一个间隔是2s。

每执行一次,把当前系统时钟值输入文件"cure.out"中,以比较该定时器的精确度。

在精度要求较高的情况下,如要求定时误差不大于1ms时,还可以利用GetTickCount ()函数返回自计算机启动后的时间,该函数的返回值是DWORD型,表示以ms为单位的计算机启动后经历的时间间隔。

通过两次调用GetTickCount()函数,然后控制它们的差值来取得定时效果.下列的代码可以实现50ms的精确定时,其误差是毫秒级的。

用上述两种方式取得的定时效果虽然在许多场合已经满足实际的要求,但由于它们的精度只有毫秒级的,而且在要求定时时间间隔小时,实际定时误差大。

对于精确度要求更高的定时操作,则应该使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数。

这两个函数是Visual C++提供并且仅供Windows 95及其后续版本使用,其精度与C PU的时钟频率有关,它们要求计算机从硬件上支持精确定时器。

QueryPerformanceFrequen cy()函数和QueryPerformanceCounter()函数的原型如下:
上述两个函数的参数的数据类型LARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构,其具体用法根据编译器是否支持64位而定。

该类型的定义如下:
使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数进行精确
定时的步骤如下:
1、首先调用QueryPerformanceFrequency()函数取得高精度运行计数器的频率f,单
位是每秒多少次(n/s),此数一般很大;
2、在需要定时的代码的两端分别调用QueryPerformanceCounter()以取得高精度运行计数器的数值n1、n2,两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f,当t大于
或等于定时时间长度时,启动定时器;
二、编程步骤
1、启动Visual C++6.0,生成一个基于对话框的应用程序,将程序命名为"HightTimer ";
2、在对话框面板中添加控件,布局如图一所示,其中包含两个静态文本框,两个编辑框和两个按纽。

上面和下面位置的编辑框的ID分别为IDC_TEST和IDC_ACTUAL,"EXIT"按纽的ID为IDOK,"TEST"按纽ID为ID_TEST;
3、通过Class Wizard添加成员变量,两个编辑框控件分别对应为DWORD m_dwTest和DWORD m_dwAct,另外添加"TEST"按纽的鼠标单击消息处理函数;
4、添加代码,编译运行程序。

三、程序代码
四、小结
本实例介绍了实现精确定时的不同方法,尤其是对于需要精确到微秒级别的定时处理,给出了实现的方法和代码,细心的读者朋友在运行程序的过程中可能会发现要求的定时长度和实际返回的时间长度还是有一些差异的,造成上述情况的原因是由于在进行定时处理时,还需要运行一些简单的循环代码,所以会产生微秒级的误差。

相关文档
最新文档