基于plc实现三相异步电动机七段速调速实验_第1页
基于plc实现三相异步电动机七段速调速实验_第2页
基于plc实现三相异步电动机七段速调速实验_第3页
基于plc实现三相异步电动机七段速调速实验_第4页
基于plc实现三相异步电动机七段速调速实验_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、PAGE PAGE 28基于PLC实现的三相异步电动机七段速调速实验 学院: 专业: 学号: 姓名: 引言三相异步电动机的应用非常广泛,具有机构简单,效率高,控制方便,运行可靠,易于维修成本低的有点,几乎涵盖了工农业生产和人类生活的各个领域,在这些应用领域中,三相异步电动机运行的环境不同,所以造成其故障的发生也很频繁,所以要正确合理的利用它。要合理的控制它。这个系统的控制是采用PLC的编程语言梯形图,梯形语言是在可编程控制器中的应用最广的语言,因为它在继电器的基础上加进了许多功能,使用灵活的指令,使逻辑关系清晰直观,编程容易,可读性强,所实现的功能也大大超过传统的继电器控制电路,可编程控制器是

2、一种数字运算操作的电子系统,它是专为在恶劣工业环境下应用而设计,它采用可编程序的存储器,用来在内部存储执行逻辑运算,顺序控制,定时,计数和算术等操作的指令,并采用数字式,模拟式的输入和输出,控制各种的机械或生产过程。长期以来,PLC始终处于工业自动化控制领域的主战场,为各种各样的自动化设备提供了非常可靠的控制应用,它能够为自动化控制应用提供安全可靠和比较完善的解决方案,适合于当前工业,企业对自动化的需要。进入20世纪80年代,由于计算机技术和微电子技术的迅猛发展,极大地推动了PLC的发展,使得PLC的功能日益增强,目前,在先进国家中,PLC已成为工业控制的标准设备,应用面几乎覆盖了所有工业,企

3、业。由于PLC综合了计算机和自动化技术,所以它发展日新月异,大大超过其出现时的技术水平,它不但可以很容易的完成逻辑,顺序,定时,计数,数字运算,数据处理等功能,而且可以通过输入输出接口建立与各类生产机械数字量和模拟量的联系,从而实现生产过程的自动化控制。特别是超大规模集成电路的迅速发展以及信息,网络时代的到来,扩展了PLC的功能,使它具有很强的联网通讯能力,从而更广泛的运用于众多行业。一、实验名称:基于PLC实现的三相异步电动机七段调速实验二、实验目的:1. 通过电动机变频调速控制系统实验,进一步了解可编程控制器在电动机变频调速控制中的应用。2. 通过系统设计,进一步了解PLC、变频器及编码器

4、之间的配合关系。3. 通过实验线路的设计,实际操作,使理论与实际相结合,增加感性认识,使书本知识更加巩固。4. 培养动手能力,增强对可编程控制器运用的能力。5. 培养分析,查找故障的能力。6. 增加对可编程控制器外围电路的认识。三、实验器件:220V PLC实验台一套、380V变频器实验台一套、三相电动机一台(Nr=1400r/min,p=2)、光电编码器一个(864p/r)、万用表一个、导线若干。四、实验原理:1.实验原理图:2.实验原理:通过光电编码器将电动机的转速采集出来并送入PLC中,通过实验程序将采集到的信息与DM3X(加速)/DM4X(减速)区的设定值进行比较,当频率满足设定值时用

5、PLC控制变频器(变频器工作在端子调速模式下),电动机停止加速,保持匀速5S,5S后PLC控制变频器加速端子继续加速。从而实现完成七段速逐段加速。以15HZ为基准加速频率上限为45Hz(可以根据具体情况设定),并在最高段速保持10s,此后电机开始减速,当到达设定的频率时,PLC控制变频器停止加速,保持匀速5S,5S后PLC控制变频器减速端子继续减速;反转的运动过程与正转正转过程相似。实验速度曲线如下图:五、实验相关器件特点:1.欧姆龙CPM2AH:CPM2A在一个小巧的单元内综合有各种性能,包括同步脉冲控制,中断输入,脉冲输出,模拟量设定,和时钟功能等。CPM2A CPU单元又是一个独立单元,

6、能处理广泛的机械控制应用,所以它是在设备内用作内装控制单元的理想产品,完整的通信功能保证了与个人计算机、其它OMRON PC和OMRON可编程终端的通信。这些通信能力使用户能设计一个经济的分布生产系统。CPM2A计有五个高速计数器输入。一个响应频率为20 kHz/5 kHz的高速计数器输入,与四个响应频率为2 kHz的高速计数器输入(在计数器方式下)。高速计数器可以用在四种输入方式中的任一种下;微分相位方式(5 kHz),脉冲+方向输入方式(20 kHz),增/减脉冲方式(20 kHz),或递增方式(20 kHz)。当计数与一设置值匹配或下降在一规定范围内时,能触发中断。中断输入(计数器方式)

7、可用递增计数器或递减计数器(2 kHz)并在计数与目标值匹配时触发中断(执行中断程序)。2.光电编码器:光电编码器,是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器, 光电编码器是由光栅盘和光电检测装置组成。光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,光栅盘与电动机同速旋转,经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号,通过计算每秒光电编码器输出脉冲的个数就能反映当前电动机的转速。此外,为判断旋转方向,码盘还可提供相位相差90的两路脉冲信号。3.变频器:()变频器可以分为四个部分。通用变

8、频器由主电路和控制回路组成。给异步电动机提供调压调频电源的电力变换部分,称为主电路。主电路包括整流器、中间直流环节(又称平波回路)、逆变器。 = 1 * GB2 整流器。它的作用是把工频电源变换成直流电源。 = 2 * GB2 平波回路(中间直流环节)。由于逆变器的负载为异步电动机,属于感性负载。无论电动机处于电动状态还是发电状态,起始功率因数总不会等于1。因此,在中间直流环节和电动机之间总会有无功功率的交换,这种无功能量要靠中间直流环节的储能元件电容器或电感器来缓冲,所以中间直流环节实际上是中间储能环节。 = 3 * GB2 逆变器。与整流器的作用相反,逆变器是将直流功率变换为所要求频率的交

9、流功率。逆变器的结构形式是利用6个半导体开关器件组成的三相桥式逆变器电路。通过有规律的控制逆变器中主开关的导通和断开,可以得到任意频率的三相交流输出波形。 = 4 * GB2 控制回路。控制回路常由运算电路,检测电路,控制信号的输入、输出电路,驱动电路和制动电路等构成。其主要任务是完成对逆变器的开关控制,对整流器的电压控制,以及完成各种保护功能。控制方式有模拟控制或数字控。六、各器件参数设置:1.变频器参数设置:端口设定值功能端口设定值功能F2001启动方式:端子控制F41114(OP4)反转F2021停止方式:端子控制F41211(OP5)增速F2042端子调速控制F41312(OP6)减速

10、F2062正反转端子脉冲给定方向F4147(OP7)停止F4096(OP2)运行F41013(OP3)正转2.内部寄存器参数设置:内部端口设定值(十六进制)内部端口设定值(十六进制)DM300242DM410790DM310336DM410730DM320420DM420650DM330504DM430560DM340588DM440470DM350672DM450370DM360770DM46 0270DM66421142DM66420003高速计数器模式0:微分相位模式(5kHz)1:脉冲方向输入模式(20kHz)2:增/减输入模式(20kHz);4:增量模式(20kHz)0407高速计数

11、器复位模式0:Z相和软件复位;1:仅软件复位08150:Z相和软件复位;1:仅软件复位00:不使用任意功能;01:作为高速计数器使用;02:作为同步脉冲控制使用(10500Hz)03:作为同步脉冲控制使用(201kHz)04:作为同步脉冲控制使用(30020kHz)3.编码器接口:颜色接口棕色24V电源“+”蓝色24V电源“-”黑色(A)0.00白色(B)0.01橙色(C)0.024.PLC端口配置:端口功能端口功能003正转1103反转004停止1004加速005反转1005减速006加速1006停止007减速1102正转1101运行七、实验结论:按照原理图接好线经检查无误后,上电下载编好的

12、程序,并在编程模式下,打开PLC的内存,在DM数据区从DM30DM36依次写入0242、0336、0420、0504、0588、0672、0770七个加速比较的十六进制数据,DM40DM46依次写入0780、0730、0650、0560、0470、0370、0270七个减速比较的十六进制数据,并在DM6642 数据区写入0112,设置高速计数器工作模式。之后保存并在线传送到PLC,再将PLC切换到运行模式。按下正转按钮后,变频器启动运行电动机正转加速,频率达到每一个阶梯后延时5秒再加速,在45Hz左右后,开始减速,减速到停止;反转类似于正转。当按下停止按钮后,变频器停止工作电机停止转动。电机匀

13、速的频率为:5.42Hz、14.89Hz、25.04Hz、35.26Hz、46.03Hz。比较接近预期值,符合实验要求。力控PLC变频器监控平台I/O设备组态(采用host link协议)2、力控数据库组态器件定义关联点器件定义关联点正传按钮20600二段指示20701反转按钮20601三段指示20702停止按钮20602四段指示20703加速按钮20603五段指示20704减速按钮20604六段指示20705减速指示20006七段指示20706运行指示20108增速指示20603一段指示207003、监控平台4、运行结果图 图1 加速过程 图2 减速过程九、程序流程图及程序清单,流程图梯形图

14、程序变频器调速程序清单LD P_On变频器调速程序清单OUT 200.00LD 200.00ANDNOT TIM000TIM 000 #1LD TIM000PRV(62) 0 0 DM0LDNOT TIM000DIFU(13) 200.01LD 200.01OUT 252.00LD 200.10OR 203.07OR 200.08ANDNOT 200.03ANDNOT 203.00OUT 203.07LD 200.00OUT TR0AND 203.07CMP(20) DM30 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.00LD 201.00OR 203.00AND

15、NOT 200.03ANDNOT 203.01OUT 203.00LD 203.00OR 204.05OUT 208.00LD 203.01OR 204.04OUT 208.01LD 203.02OR 204.03OUT 208.02LD 203.03OR 204.02OUT 208.03LD 203.04OR 204.01OUT 208.04LD 203.05OR 204.00OUT 208.05LD 200.00OUT TR0AND 203.00CMP(20) DM31 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.01LD 201.01OR 203.01ANDN

16、OT 200.03ANDNOT 203.02OUT 203.01LD 200.00OUT TR0AND 203.01CMP(20) DM32 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.02LD 201.02OR 203.02ANDNOT 200.03ANDNOT 203.03OUT 203.02LD 200.00OUT TR0AND 203.02CMP(20) DM33 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.03LD 201.03OR 203.03ANDNOT 200.03ANDNOT 203.04OUT 203.03LD 200

17、.00OUT TR0AND 203.03CMP(20) DM34 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.04LD 201.04OR 203.04ANDNOT 200.03ANDNOT 203.05OUT 203.04LD 200.00OUT TR0AND 203.04CMP(20) DM35 DM0LD TR0LD P_LTOR P_EQANDLDOUT 201.05LD 201.05OR 203.05ANDNOT 200.03ANDNOT 203.06OUT 203.05LD 200.00OUT TR0AND 203.05CMP(20) DM36 DM0LD

18、 TR0LD P_LTOR P_EQANDLDOUT 201.06LD 201.06OR 203.06ANDNOT TIM004ANDNOT 200.03OUT 203.06LD 203.06TIM 004 #100LD 201.00OR 201.01OR 201.02OR 201.03OR 201.04OR 201.05OR 201.10ANDNOT TIM001OUT 201.10LD 0.03OR 206.00OUT 200.10LD 200.10OR 201.08OR 200.08ANDNOT 200.03OUT 201.08LD 201.08OUT 11.01LD 0.07OR 20

19、6.02OUT 200.03LD 200.03OUT 10.06LD 200.10OR 200.04ANDNOT 200.03ANDNOT 200.09OUT 200.04LD 200.04OUT 11.02LD 200.04OR 200.09ANDNOT 200.05ANDNOT 203.06ANDNOT 210.00OUT 10.04OUT 206.03LD 201.10OR 201.12OR 200.05ANDNOT TIM001OUT 200.05LD 200.05TIM 001 #50LD TIM004OR 210.00ANDNOT 200.03OUT 210.00LD TIM004

20、OR 210.01ANDNOT 204.00ANDNOT 200.03OUT 210.01LD 210.00OUT TR0AND 210.01CMP(20) DM40 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.00LD TR0AND P_LTOUT 205.00LD 202.00OR 204.00ANDNOT 200.03ANDNOT 204.01OUT 204.00LD 210.00OUT TR0AND 204.00CMP(20) DM41 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.01LD TR0AND P_LTOUT 205.0

21、1LD 202.01OR 204.01ANDNOT 200.03ANDNOT 204.02OUT 204.01LD 210.00OUT TR0AND 204.01CMP(20) DM42 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.02LD TR0AND P_LTOUT 205.02LD 202.02OR 204.02ANDNOT 200.03ANDNOT 204.03OUT 204.02LD 210.00OUT TR0AND 204.02CMP(20) DM43 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.03LD TR0AND P_L

22、TOUT 205.03LD 202.03OR 204.03ANDNOT 200.03ANDNOT 204.04OUT 204.03LD 210.00OUT TR0AND 204.03CMP(20) DM44 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.04LD TR0AND P_LTOUT 205.04LD 202.04OR 204.04ANDNOT 200.03ANDNOT 204.05OUT 204.04LD 210.00OUT TR0AND 204.04CMP(20) DM45 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.05LD

23、TR0AND P_LTOUT 205.05LD 202.05OR 204.05ANDNOT 200.03ANDNOT 204.06OUT 204.05LD 210.00OUT TR0AND 204.05CMP(20) DM46 DM0LD TR0LD P_GTOR P_EQANDLDOUT 202.06LD TR0AND P_LTOUT 205.06LD 202.06OR 204.06ANDNOT 200.03ANDNOT TIM005OUT 204.06LD 204.06TIM 005 #50LD 202.01OR 202.02OR 202.03OR 202.04OR 202.05OR 20

24、1.12ANDNOT TIM002ANDNOT 200.03OUT 201.12LD 201.12TIM 002 #50LD TIM002OR 200.06OR TIM004OR 205.00OR 205.02OR 205.01OR 205.03OR 205.04OR 205.05OR TIM005OR 205.06ANDNOT 200.03ANDNOT 200.05ANDNOT 202.06OUT 200.06LD 200.06ANDNOT 200.05OUT 10.05OUT 206.04LD 0.06OR 206.01ANDNOT 200.03OUT 200.08LD 200.08OR

25、200.09ANDNOT 200.04ANDNOT 200.03OUT 200.09LD 200.09OUT 11.03END(01)附录资料:不需要的可以自行删除C语言中如何获取时间?精度如何?1 使用time_t time( time_t * timer ) 精确到秒2 使用clock_t clock() 得到的是CPU时间精确到1/CLOCKS_PER_SEC秒3 计算时间差使用double difftime( time_t timer1, time_t timer0 )4 使用DWORD GetTickCount() 精确到毫秒5 如果使用MFC的CTime类,可以用CTime:Get

26、CurrentTime() 精确到秒6 要获取高精度时间,可以使用BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)获取系统的计数器的频率BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)获取计数器的值然后用两次计数器的差除以Frequency就得到时间。7 Multimedia Timer FunctionsThe following functions are used with multimedia timers.timeBeginPeriod/t

27、imeEndPeriod/timeGetDevCaps/timeGetSystemTime/*/用标准C实现获取当前系统时间的函数一.time()函数time(&rawtime)函数获取当前时间距1970年1月1日的秒数,以秒计数单位,存于rawtime 中。#include time.hvoid main ()time_t rawtime;struct tm * timeinfo;time ( &rawtime );timeinfo = localtime ( &rawtime );printf ( 007The current date/time is: %s, asctime (time

28、info) );exit(0);=#include - 必须的时间函数头文件time_t - 时间类型(time.h 定义是typedef long time_t; 追根溯源,time_t是long)struct tm - 时间结构,time.h 定义如下:int tm_sec;int tm_min;int tm_hour;int tm_mday;int tm_mon;int tm_year;int tm_wday;int tm_yday;int tm_isdst;time ( &rawtime ); - 获取时间,以秒计,从1970年1月一日起算,存于rawtimelocaltime ( &

29、rawtime ); - 转为当地时间,tm 时间结构asctime ()- 转为标准ASCII时间格式:星期 月 日 时:分:秒 年二.clock()函数,用clock()函数,得到系统启动以后的毫秒级时间,然后除以CLOCKS_PER_SEC,就可以换成“秒”,标准c函数。clock_t clock ( void );#includeclock_t t = clock();long sec = t / CLOCKS_PER_SEC;他是记录时钟周期的,实现看来不会很精确,需要试验验证;三.gettime(&t); 据说tc2.0的time结构含有毫秒信息#include#includein

30、t main(void)struct time t;gettime(&t);printf(The current time is: -:d:d.dn,t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);return 0;time 是一个结构体, 其中成员函数 ti_hund 是毫秒。四.GetTickCount(),这个是windows里面常用来计算程序运行时间的函数;DWORD dwStart = GetTickCount();/这里运行你的程序代码DWORD dwEnd = GetTickCount();则(dwEnd-dwStart)就是你的程序运行时间,

31、 以毫秒为单位这个函数只精确到55ms,1个tick就是55ms。五.timeGetTime()t,imeGetTime()基本等于GetTickCount(),但是精度更高DWORD dwStart = timeGetTime();/这里运行你的程序代码DWORD dwEnd = timeGetTime();则(dwEnd-dwStart)就是你的程序运行时间, 以毫秒为单位虽然返回的值单位应该是ms,但传说精度只有10ms。=/*Unix#unix时间相关,也是标准库的/*1.timegm函数只是将struct tm结构转成time_t结构,不使用时区信息;time_t timegm(st

32、ruct tm *tm);2.mktime使用时区信息time_t mktime(struct tm *tm);timelocal 函数是GNU扩展的与posix函数mktime相当time_t timelocal (struct tm *tm);3.gmtime函数只是将time_t结构转成struct tm结构,不使用时区信息;struct tm * gmtime(const time_t *clock);4.localtime使用时区信息struct tm * localtime(const time_t *clock);1.time获取时间,stime设置时间time_t t;t =

33、time(&t);2.stime其参数应该是GMT时间,根据本地时区设置为本地时间;int stime(time_t *tp)3.UTC=true 表示采用夏时制;4.文件的修改时间等信息全部采用GMT时间存放,不同的系统在得到修改时间后通过localtime转换成本地时间;5.设置时区推荐使用setup来设置;6.设置时区也可以先更变/etc/sysconfig/clock中的设置再将ln -fs /usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效time_t只能表示68年的范围,即mktime只能返回1970-2038这一段范围的time_t看

34、看你的系统是否有time_t64,它能表示更大的时间范围/*windows#Window里面的一些不一样的/*一.CTime () 类VC编程一般使用CTime类 获得当前日期和时间CTime t = GetCurrentTime();SYSTEMTIME 结构包含毫秒信息typedef struct _SYSTEMTIME WORD wYear;WORD wMonth;WORD wDayOfWeek;WORD wDay;WORD wHour;WORD wMinute;WORD wSecond;WORD wMilliseconds; SYSTEMTIME, *PSYSTEMTIME;SYSTE

35、MTIME t1;GetSystemTime(&t1)CTime curTime(t1);WORD ms = t1.wMilliseconds;SYSTEMTIME sysTm;:GetLocalTime(&sysTm);在time.h中的_strtime() /只能在windows中用char t11;_strtime(t);puts(t);/*获得当前日期和时间CTime tm=CTime:GetCurrentTime();CString str=tm.Format(%Y-%m-%d);在VC中,我们可以借助CTime时间类,获取系统当前日期,具体使用方法如下:CTime t = CTim

36、e:GetCurrentTime(); /获取系统日期,存储在t里面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为星期六二.CTimeSpan类如果想计算两段时间的差值,可以使用CTimeSpan类,具体使用方法如下:CTime t1( 19

37、99, 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();/获取总共有多少秒三._timeb()函数_timeb定义在SYSTIMEB.H,有四个fieldsd

38、stflagmillitmtimetimezonevoid _ftime( struct _timeb *timeptr );struct _timeb timebuffer;_ftime( &timebuffer );取当前时间:文档讲可以到ms,有人测试,好象只能到16ms!四.设置计时器定义TIMER ID#define TIMERID_JISUANFANGSHI 2在适当的地方设置时钟,需要开始其作用的地方;SetTimer(TIMERID_JISUANFANGSHI,200,NULL);在不需要定时器的时候的时候销毁掉时钟KillTimer(TIMERID_JISUANFANGSHI

39、);对应VC程序的消息映射void CJisuan:OnTimer(UINT nIDEvent)switch(nIDEvent)#如何设定当前系统时间windowsSYSTEMTIME m_myLocalTime,*lpSystemTime;m_myLocalTime.wYear=2003;m_myLocalTime.wM;m_myLocalTime.wDay=1;m_myLocalTime.wHour=0;m_myLocalTime.wMinute=0;m_myLocalTime.wSec;m_myLocalTime.wMillisec;lpSystemTime=&m_myLocalTime

40、;if( SetLocalTime(lpSystemTime) ) /此处换成 SetSystemTime( )也不行MessageBox(OK !);elseMessageBox(Error !);SYSTEMTIME m_myLocalTime,*lpSystemTime;m_myLocalTime.wYear=2003;m_myLocalTime.wM;m_myLocalTime.wDay=1;lpSystemTime=&m_myLocalTime;if( SetDate(lpSystemTime) ) /此处换成 SetSystemTime( )也不行MessageBox(OK !);

41、elseMessageBox(Error !);本文来自CSDN博客,转载请标明出处:HYPERLINK /khuang2008/archive/2008/12/09/3483274.aspx/khuang2008/archive/2008/12/09/3483274.aspx一种制作微秒级精度定时器的方法当使用定时器时,在很多情况下只用到毫秒级的时间间隔,所以只需用到下面的两种常用方式就满足要求了。一是用SetTimer函数建立一个定时器后,在程序中通过处理由定时器发送到线程消息队列中的WM_TIMER消息,而得到定时的效果(退出程序时别忘了调用和SetTimer配对使用的KillTimer

42、函数)。二是利用GetTickCount函数可以返回自计算机启动后的时间,通过两次调用GetTickCount函数,然后控制它们的差值来取得定时效果,此方式跟第一种方式一样,精度也是毫秒级的。用这两种方式取得的定时效果虽然在许多场合已经满足实际的要求,但由于它们的精度只有毫秒级的,而且在要求定时时间间隔小时,实际定时误差大。下面介绍一种能取得高精度定时的方法。在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution performance counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。采用这种方法的步骤如下:1、首先调用QueryPerfo

43、rmanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数一般很大。2、在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f。下面举一个例子来演示这种方法的使用及它的精确度。在VC 6.0 下用MFC建立一个对话框工程,取名为HightTimer.在对话框面板中控件的布局如下图:其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACTUAL,通过MFC ClassWizar

44、d添加的成员变量也分别对应为DWORD m_dwTest和DWORD m_dwAct. “退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC ClassWizard添加此按纽的单击消息处理函数如下:void CHightTimerDlg:OnBTest()/ TODO: Add your control notification handler code hereUpdateData(TRUE); /取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中LARGE_INTEGER frequence;if(!QueryPerformanceFrequenc

45、y( &frequence) /取高精度运行计数器的频率,若硬件不支持则返回FALSEMessageBox(Your computer hardware doesnt support the high-resolution performance counter,Not Support, MB_ICONEXCLAMATION | MB_OK);LARGE_INTEGER test, ret;test.QuadPart = frequence.QuadPart * m_dwTest / 1000000; /通过频率换算微秒数到对应的数量(与CPU时钟有关),1秒=1000000微秒ret = M

46、ySleep( test ); /调用此函数开始延时,返回实际花销的数量m_dwAct = (DWORD)(1000000 * ret.QuadPart / frequence.QuadPart ); /换算到微秒数UpdateData(FALSE); /显示到对话框面板其中上面调用的MySleep函数如下:LARGE_INTEGER CHightTimerDlg:MySleep(LARGE_INTEGER Interval)/ 功能:执行实际的延时功能 / 参数:Interval 参数为需要执行的延时与时间有关的数量 / 返回值:返回此函数执行后实际所用的时间有关的数量 / LARGE_IN

47、TEGER privious, current, Elapse;QueryPerformanceCounter( &privious );current = privious;while( current.QuadPart - privious.QuadPart Interval.QuadPart )QueryPerformanceCounter( t );Elapse.QuadPart = current.QuadPart - privious.QuadPart;return Elapse;注:别忘了在头文件中为此函数添加函数声明。至此,可以编译和执行此工程了,结果如上图所示。在本人所用的机

48、上(奔腾366, 64M内存)测试,当测试时间超过3微秒时,准确度已经非常高了,此时机器执行本身延时函数代码的时间对需要延时的时间影响很小了。上面的函数由于演示测试的需要,没有在函数级封装,下面给出的函数基本上可以以全局函数的形式照搬到别的程序中。BOOL MySleep(DWORD dwInterval)/ 功能:执行微秒级的延时功能 / 参数:Interval 参数为需要的延时数(单位:微秒) / 返回值:若计算机硬件不支持此功能,返回FALSE,若函数执行成功,返回TRUE / BOOL bNormal = TRUE;LARGE_INTEGER frequence, privious,

49、current, interval;if(!QueryPerformanceFrequency( &frequence):MessageBox(NULL, Your computer hardware doesnt support the high-resolution performance counter,Not Support, MB_ICONEXCLAMATION | MB_OK); /或其它的提示信息return FALSE;interval.QuadPart = frequence.QuadPart * dwInterval / 1000000;bNormal = bNormal

50、& QueryPerformanceCounter( &privious );current = privious;while( current.QuadPart - privious.QuadPart interval.QuadPart )bNormal = bNormal & QueryPerformanceCounter( t );return bNormal;需要指出的是,由于在此函数中的代码很多,机器在执行这些代码所花费的时间也很长,所以在需要几个微秒的延时时,会影响精度。实际上,读者在熟悉这种方法后,只要使用QueryPerformanceFrequency和QueryPerfor

51、manceCounter这两个函数就能按实际需要写出自己的延时代码了。使用CPU时间戳进行高精度计时对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒

52、体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。本文要介绍的,是另一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于Windows图形编程一书,第15页17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主

53、频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C+语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:inline unsigned _int64 GetCycleCount() _asm RDTSC 但是不行,因为RDTSC不被C+的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码

54、形式0X0F、0X31,如下:inline unsigned _int64 GetCycleCount() _asm _emit 0 x0F _asm _emit 0 x31 以后在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样: unsigned long t; t = (unsigned long)GetCycleCount(); /Do Something time-intensive . t -= (unsigned long)GetCycleCount(); Windows图形编程第15页编写了一个类,把这

55、个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在Celeron 800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。 这个方法的优点是: 1.高精度。可以直接达到纳秒级的计时

56、精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。 2.成本低。timeGetTime 函数需要链接多媒体库winmm.lib,QueryPerformance* 函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考图形程序开发人员指南,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。 3.具有和CPU

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论