TTimer的困惑(10分)

M

mayong

Unregistered / Unconfirmed
GUEST, unregistred user!
我在开发模拟电度表控件中,对电度表的数字值使用了TTimer,对其定时的不精确头疼,请问多煤体定时器实现精确定时的方法,对不起,本人分数不多,节省为本,望不吝赐教!!!
 
文章太长了,不好在这里贴出来,已经发到您的信箱里头去了.
是<<微电脑世界>>上的一篇文章
 
好象有许多 第三方提供的类似控件,都说比原来的好,多数有 SOURCE
 
哈哈,CJCJC,我比你快.

btw: CJCJC,您到底有没有文章啊?详见我的提问.
 
接受答案了.
 
这篇文章能不能贴出来,我也想看一下.(发到我的信箱也可以,
但后来者又看不到了.)另外,请问第三方的空间有哪些?
 
文章贴出:
Windows 3.X环境下定时器的使用
马兴录
一、问题的提出
在编制实时软件时,会遇到各种各样的定时要求,有的要求定时间
隔为几秒,有的要求几毫秒,甚至有要求以微秒为单位的。
作者在实际工作中,曾遇到这样的要求:同时使用多个定时器,有
的定时间隔为几百毫秒;而有的则要求几个毫秒;而且要求能通过I/O
板发出宽度仅为几十微秒的矩形波。
针对上述要求,作者使用Borland C++3.1在中文Windows 3.2下实
现了多种精度的定时器需要。

二、低精度定时器
Windows提供的定时器是建立在DOS的1CH中断基础上的。该中断
每秒钟发生18.2次,即时间间隔为54.945ms。如果定时间隔是该数的
整数倍时,使用这个定时器则是最简单的方法。
使用定时器的窗口可定义如下:
class WyWindows:public……
{
private:
virtual void TimerHandle ()=[WM-FIRST+WM-TIMER];
//响应定时消息WM-TIMER
};
在窗口的某个函数内启动定时器:
if (SetTimer(hWnd,1,110,NULL)==NULL)//时间间隔为//110ms,
定时器标识为1
{
错误处理;
}
定时器使用完后,应及时关闭:
KillTimer(1);//关闭1号定时器
如果定时间隔不是55ms的整数倍,则不能用上述方法实现。即使
使用SstTimer(..,..,1 00,NULL)来设置定时器也是不行的。实际使
用中会发现,这样作的定时间隔是110ms,而不是100ms.

三、高精度定时器
当定时间隔小于55ms,或者不是55ms的整数倍时,则必须另辟途径
。大家知道,虽然Wind ows是基于DOS的,但它对多媒体的支持却很优
秀。Windows下有一套多媒体编程接口,这套接口函数包含于mmsystem
.dll动态链接库中。Borland C++3.1提供了相应的头文件mmsystem.
h。在这个编程接口中,有一套定时器操作函数,可用来实现高精度的
定时器,其计时精度可达1ms。这套函数主要包括:
timeGetDevCaps()——获取定时器的一些参数;
timeBeginPeriod()——设置定时器的定时精度;
timeSetEvent ()——设置定时间隔并启动定时器;
timeKillEvent ()——关闭定时器;
timeEndPeriod ()——释放定时器。
根据面向对象的编程思想,对上述几个函数进行封装,实现了自定
义的MyTimer类。该类定义如下:
//----MyTimer.h
#define MY-TIMER(WM-USER+101)//定时器发给父窗口的消息ext
ern″C″
{
//定时器回调函数
void far PASCAL-export IntRout (WORD,WORD,DWORD,DWORD,DW
ORD);
}
-CLASSDEF(MyTimer)
typedef struct -df{
int Timer ID;//定时器标识
int MinRes;//最小计时精度
int DevCaps;//定时间隔
HWND hWnd;//拥有该定时器的窗口
long TCount;//总的计时时间
}MyTmID;
class -export Mytimer //MyTimer类定义
{
private:
MyTmID TData;
public:
MyTimer(HWND hw,WORD Gap);//参数为父窗口及定时间隔
-MyTimer();
BOOL Start();//定时器启动函数
void End();//关闭定时器
long GetTime();//获取定时时间
};
其主要函数实现如下:
//----MyTimer.cpp
#include <owl.h>
#include <mmsystem.h>
#include "mxltimer.h"
PTModule MyTimerLib;
/*------定时器回调函数------*/
void far PASCAL-export IntTout (WORD,WORD,DWORD dwUser,D
WORD)
{My TmID *data;
data=(MyTmID *)dwUser;
if(data->TimeID)
{data->TCount+=data->DevCaps;//计时
if(data->hWnd!=NULL)
PostMessage(data->hWnd,MY-TIMER,0,01);
//向拥有该定时器//的窗口发送MY-TIMER消息
}
}
MyTimer::MyTimer(HWND hw,WORD Gap)
{
TIMECAPS Tcps;
//初始化定时器参数
if(timeGetDevCaps(&Tcps,sizeof(TIMECAPS))!=TIMERR-NOCAND
O)
{TData.MinRes=Tcps.wPeriodMin;
timeBeginPeriod(Tcps.wPeriodMin);
TData.TimerID=0;
TData.hwnd=hw;
TData.DevCaps=Gap;
TData.TCount=0;
}
}
MyTimer::-MyTimer 0//释放定时器
{
if (TData.Timer ID)
{timeKillEvent(TData.Timer ID);
timeEndPeriod(TData.MinRes);
TData.Timer ID=0;
}
}
BOOL MyTimer::Start()//启动定时器
{
TData.Tcount=0;
TData.TimerID=timeSetEvent(TData.DevCaps,TData.MinRes,(L
PTIMECALLBACK)Int
Ro
ut,(DWORD)&TData,TIME-PERIODIC);
if(!TData.TimerID) return 0;
return 1;
}
void MyTimer::End()//停止定时器
{
if(TData.TimerID)
{timeKillEvent(TData.TimerID);
TData.TimerID=0;
}
}
long MyTimer::GetTime()//获取计时时间
{
return TData.TCount;
}
MyTimer类应该用动态链接库来实现,即将上述程序单独编译为.D
LL文件,然后可以直接链接到自己的程序中去。该类的功能及使用方
法如下。
1.可以和任何一个窗口连接,定时向该窗口发送MY-TIMER消息。
使用方法和低精度定时器基本一致。
class MyWindow:public…
{private:
MyTimer *MTimerPtr;//定义一定时器指针
void TimerHandle()=[WM-FIRST+MY-TIMER];
//响应定时消息
.
.
};
在MyWindow的创建函数中建立定时器:
void MyWindow::SetupWindow()
{.
.
MTimerPtr=new MyTimer(hWnd,10);//定时间隔为10ms
}
在MyWindow的折构函数中释放定时器:
void MyWindow::-MyWindow()
{.
.
if(MTimerPtr)delete MTimerPtr;
}
可在任何合适的函数内启动或停止定时器:
启动定时器:if(MTimerPtr)MTimerPtr->start();
停止定时器:if(MTimerPtr)MTimerPtr->end();
在MyWindow的TimerHandle()函数中响应定时事件。
2.单纯用作计时器,如同一个跑表一样。这时定时器的拥有窗口
可设为NULL。其使用方法可见下面的程序示例。

四、矩形波的产生
如果要求产生微秒级的矩形波,则完全可以使用程序延时来实现
。在这段时间内完全占用CPU资源,因为这段时间毕竟是较短的。而如
果矩形波宽度在毫秒级以上,则可使用高精度定时器来实现。
要实现程序的准确延时,必须准确测定机器的运行速度。使用高
精度定时器可以准确测量机器速度。
void Test-Cpu-Speed()
{MyTimer*TmTemp;
TmTemp=new MyTimer(NULL,1);//定时精度1ms
if(TmTemp==NULL)return;
TmTemp->Start();//启动定时器
for (int i=0;i<20;i++)//延时
{
asm mov cx,0xffff;
tcpus:asm loop tcpus;
}
TmTemp->End();//关闭定时器
T50=(int)(65535L/(TmTemp->GetTime()*1000));
//延时50us的循环次数计算公式
}
发出50us宽度矩形波的程序如下:
outportb(..); /*发出波形*/
asm mov cx,T50;//延时50us
13:asm loop 13;
outportb(..);//波形结束

五、结束语
一旦实现了高精度定时器,便可满足各种各样的定时要求。在使
用时应注意,当定时间隔很短时,应保证能及时响应定时消息,否则有
可能丢失定时消息,使定时不准。
(作者地址:青岛高校科技培训学院,266042)
 

Similar threads

顶部