b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

使用Visual C ++制作一个微秒精度的计时器(Vb也适用)

电脑杂谈  发布时间:2020-05-01 02:03:15  来源:网络整理

vb定时器_vb定时自动运行程序_定时喷香器

使用Visual C ++制作微秒精度计时器

在工业生产控制系统中,需要定期完成许多操作,例如: 定期显示当前时间,定期刷新屏幕上的进度条,上位机发送命令并将数据传输到下位机特别是在需要高控制性能的控制系统和数据采集系统中,需要精确的定时操作. 众所周知,Windows是基于消息机制的系统,任何事件的执行都通过发送和接收消息来完成. 这就带来了一些问题,例如,一旦计算机的CPU被某个进程占用,或者当系统资源紧张时,发送到消息队列的消息将被暂时挂起,并且无法进行实时处理. 因此,您不能简单地通过Windows消息触发具有严格定时要求的事件. 另外,由于对计算机基础硬件的访问已经封装在Windows中,因此很难通过直接使用访问硬件来完成准确的计时. 在实际应用中,应采用适合于特定定时精度的定时方法.

此示例实现了微秒的精确计时. 程序界面提供两个“编辑”编辑框,其中一个输入用户的理想计时长度,另一个编辑框返回实际的时间长度. 经过大量的实验测试,正常情况下误差不超过5微秒. 该程序的运行界面如图1所示:

图1.实现微秒级的精确计时器

I. 实施方法

Visual C ++提供了许多与时间操作有关的功能,使用它们来控制程序可以准确地完成计时和计时操作. Visaul C ++中的WM_TIMER消息映射可以执行简单的时间控制. 首先调用函数SetTimer()设置计时间隔(退出程序时别忘了调用与SetTimer()配对的KillTimer()函数),例如SetTimer(0,200,NULL)是设置200ms的间隔. 然后在应用程序中添加计时器响应函数OnTimer(),并在函数中添加响应处理语句,用于完成达到计时器时间的操作. 这种计时方法非常简单,但是其计时功能就像Sleep()函数的延迟功能一样,其准确性也很低. 它只能用于实现动态显示不需要高定时精度的位图.

Microsoft在其多媒体Windows中为精确计时器提供了低级API支持. 多媒体计时器可用于准确读取系统的当前时间,并可以在非常精确的时间间隔内完成事件,功能或过程的调用. 使用多媒体计时器的基本功能,可以通过两种方式实现精确计时. 1)使用timeGetTime()函数,该函数的计时精度为ms级,并返回自Windows启动以来经过的时间. 由于此功能用于通过查询进行时序控制,因此应建立时序循环以控制时序事件. 2)使用timeSetEvent()函数,此函数的原型如下:

MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK lpTimeProc,

DWORD dwUser,UINT fuEvent);

函数的参数描述如下: 参数uDelay表示延迟时间; uResolution参数表示时间精度,Windows默认值为1ms. lpTimeProc表示回调函数,它是用户定义的函数,通常被调用;参数dwUser表示用户提供回叫数据;参数fuEvent是计时器的事件类型,TIME_ONESHOT表示执行一次; TIME_PERIODIC: 定期执行. 对于特定的应用程序,您可以通过调用timeSetEvent()函数来完成需要处理的事件,从而在lpTimeProc回调函数中定义需要定期执行的任务(例如: 定时采样,控制等). 需要说明的是,任务处理时间不能大于周期间隔时间. 另外,使用计时器后vb定时器,应及时调用timeKillEvent()释放它. 以下代码的主要功能是设置两个时钟定时器,一个间隔为1ms,一个间隔为2s. 每次执行时,都将当前系统时钟值输入文件“ cure.out”,以比较计时器的精度.

#define ONE_MILLI_SECOND 1 //以毫秒为单位定义1ms和2s时钟间隔;

#define TWO_SECOND 2000

#define TIMER_ACCURACY 1 //以ms为单位定义时钟分辨率.

UINT wTimerRes_1ms,wTimerRes_2s; //定义时间间隔

UINT wAccuracy; //定义分辨率

UINT TimerID_1ms,TimerID_2s; //定义计时器句柄

///////////////////////////////

CCureApp :: CCureApp(): fout(“ cure.out”,ios :: out)//打开输出文件“ cure.out”;

{

//分配时间间隔变量

wTimerRes_1ms = ONE_MILLI_SECOND;

wTimerRes_2s = TWO_SECOND;

TIMECAPS tc;

//使用timeGetDevCaps函数获取系统分辨率的范围,如果没有错误,请继续;

如果(timeGetDevCaps(&tc,sizeof(TIMECAPS))== TIMERR_NOERROR)

{

vb定时器_定时喷香器_vb定时自动运行程序

wAccuracy = min(max(tc.wPeriodMin,//分辨率值不能超过系统的值范围

TIMER_ACCURACY),tc.wPeriodMax);

//调用timeBeginPeriod函数以设置计时器的分辨率

timeBeginPeriod(wAccuracy);

//设置计时器

InitializeTimer();

}

}

CCureApp ::〜CCureApp()

{

fout

timeKillEvent(TimerID_1ms); //删除两个计时器

timeKillEvent(TimerID_2s); //删除设置的分辨率

timeEndPeriod(wAccuracy);

}

void CCureApp :: InitializeTimer()

{

StartOneMilliSecondTimer();

StartTwoSecondTimer();

}

// 1ms计时器回调函数,类似于中断处理程序,必须声明为全局PASCAL函数,

//否则编译会出现问题

void PASCAL OneMilliSecondProc(UINT wTimerID,UINT消息,DWORD dwUser,

DWORD dwl,DWORD dw2)

{

//定义计数器

static int ms = 0;

定时喷香器_vb定时器_vb定时自动运行程序

CCureApp * app =(CCureApp *)dwUser;

//以毫秒为单位获取系统时间

DWORD osBinaryTime = GetTickCount();

//输出计数器值和当前系统时间

app-> fout

}

//添加1ms计时器

void CCureApp :: StartOneMilliSecondTimer()

{

if(((TimerID_1ms = timeSetEvent(wTimerRes_1ms,wAccuracy,

(LPTIMECALBACK)OneMil liSecondProc,//回调函数;

(DWORD)this,//用户传输到回调函数的数据;

TIME_PERIODIC))== 0)//定期调用计时处理函数;

{

AfxMessageBox(“无法执行计时!”,MB_OK | MB_ICONASTERISK);

}

其他

fout

}

在对精度有较高要求的情况下,例如计时误差不大于1ms时,还可以使用GetTickCount()函数返回自计算机启动以来的时间. 此函数的返回值为DWORD类型,表示单位为ms计算机启动后的时间间隔. 通过调用两次GetTickCount()函数,然后控制它们之间的差异来实现定时效果. 下面的代码可以实现50ms的准确计时,误差约为毫秒.

//起始值和终止值

DWORD dwStart,dwStop;

dwStop = GetTickCount();

while(TRUE){

//最后一个停止值变为新的开始值

dwStart = dwStop; //在此处添加相应的控制语句

vb定时器_定时喷香器_vb定时自动运行程序

{

dwStop = GetTickCount();

}而(dwStop-50

}

尽管通过上述两种方法获得的定时效果在很多场合都满足了实际要求,但由于它们的精度仅为毫秒量级,并且当所需的定时间隔小时,实际的定时误差就很大. 对于需要更高准确性的计时操作,应使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数. 这两个功能由Visual C ++提供,并且仅由Windows 95及其后续版本使用. 它们的准确性与CPU的时钟频率有关. 他们要求计算机支持硬件中的精确计时器. QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:

BOOL QueryPerformanceFrequency(LARGE_INTEGER * lpFrequency);

BOOL QueryPerformanceCounter(LARGE_INTEGER * lpCount);

以上两个函数的参数的数据类型LARGE_INTEGER可以是8字节整数或两个4字节整数的联合结构. 具体用法取决于编译器是否支持64位. 此类型的定义如下:

typedef union _LARGE_INTEGER

{

结构{

DWORD LowPart; // 4字节整数

LONGHighPart; // 4字节整数

};

Long QuadPart; // 8字节整数

} LARGE_INTEGER;

使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数进行精确计时的步骤如下:

1. 首先调用QueryPerformanceFrequency()函数获取高精度运行计数器的频率f,单位是每秒多少次(n / s),这个数字通常很大;

2. 在需要定时的代码的两端调用QueryPerformanceCounter()以获取高精度的运行计数器值n1和n2. 将两个值之间的差通过f转换为时间间隔,t =(n2-n1)/ f,当t大于或等于时间长度时,启动计时器;

第二步,编程步骤

1. 启动Visual C ++ 6.0vb定时器,生成一个基于对话框的应用程序,并将程序命名为“ HightTimer”;

2. 将控件添加到对话框面板. 布局如图1所示,其中包含两个静态文本框,两个编辑框和两个按钮. 上方和下方的编辑框的ID为IDC_TEST和IDC_ACTUAL,“退出”按钮的ID为IDOK,而“测试”按钮的ID为ID_TEST;

3. 通过类向导添加成员变量,两个编辑框控件分别对应DWORD m_dwTest和DWORD m_dwAct,并添加“ TEST”按钮的鼠标点击消息处理功能;

4. 添加代码,编译并运行程序.

三,程序代码

///////////////////////////////////////////////// // ////////////////////////

LARGE_INTEGER MySleep(LARGE_INTEGER间隔)

vb定时自动运行程序_定时喷香器_vb定时器

//函数: 执行实际的延迟函数,Interval参数是需要执行的与时间有关的延迟量,此函数返回执行//行后实际花费的时间;

{

LARGE_INTEGER不公开,当前,已逝;

QueryPerformanceCounter(&privious);

current = privious;

同时(current.QuadPart-privious.QuadPart

QueryPerformanceCounter(和当前);

Elapse.QuadPart = current.QuadPart-privious.QuadPart;

返回过去;

}

void CHightTimerDlg :: OnTest()

{

// TODO: 在此处添加您的控制通知处理程序代码

UpdateData(TRUE); //将输入的测试时间值带到与编辑框关联的成员变量m_dwTest;

LARGE_INTEGER频率;

//获取高精度运行计数器的频率,如果硬件不支持,则返回FALSE

如果(!QueryPerformanceFrequency(&频率))

MessageBox(“您的计算机硬件不支持高分辨率性能计数器”,

“不支持”,MB_ICONEXCLAMATION | MB_OK);

LARGE_INTEGER测试,退回;

//将频率转换为微秒(与CPU时钟相关)的相应数字,即1秒= 1000000微秒;

test.QuadPart = frequence.QuadPart * m_dwTest / 1000000;

ret = MySleep(测试); //调用此函数开始延迟并返回实际费用;

m_dwAct =(DWORD)(1000000 * ret.QuadPart / frequence.QuadPart); //转换为微秒;

UpdateData(FALSE); //显示到对话框面板;

}

四个摘要

此示例介绍了实现精确计时的不同方法,尤其是对于需要精确到微秒级的计时处理,并提供了实现方法和代码. 细心的读者朋友可能会在运行程序的过程中发现要求. 时间长度和实际返回时间之间存在一些差异. 出现这种情况的原因是,在执行定时处理时,需要运行一些简单的循环代码,因此会出现微秒级的错误.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-194729-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...