-
c语言入门之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. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结束之前,注意一定不能再次启动该定时器,不然将迅速造成死机。
张云洲 梁科山
---- 在工业控制软件中,数据采集和实时控制是经常性的工作。目前,工业控制软件已经从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. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结束之前,注意一定不能再次启动该定时器,不然将迅速造成死机。
最新更新
python爬虫及其可视化
使用python爬取豆瓣电影短评评论内容
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比