c)使用QueryPerformanceCounter()函数结合多线程来实现:QueryPerformanceFrequency()和
QueryPerformaneeCounter()函数是VC提供的仅供Windows 95及其后续版本使用的精确时间函数,并要求计算机从硬件上支持精确定时器。 QueryPerformaneeFrequency()函数和QueryPerformanceCounter()函数的原型如下: BOOL QueryPerfonnanceFrequency(LARGE_INTEGER * lpFrequency); BOOL QueryPerformaneeCounter(LARGE_INTEGER * lpCount); 数据类型ARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构 ,其具体用法根据编译器是否支持64位而定。该类型的定义如下: typedef union_LARGE_INTEGER { struet { DWORD LowPart;//4字节整型数 LONG HighPart;//4字节整型数 }; LONGLONG QuadPart;//8字节整型数 }LARGE_INTEGER; 在进行定时之前,先调用QueryPerformaneeFrequeney()函数获得机器内部定时器的时钟频率,然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformaneeCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经历的精确时间。 使用时需要自行编写消息循环程序,下列代码实现1μs的精确定时: LARGE_INTEGER litmp; LONGLONG QPartl,QPart2;sp; double dtMinus,dfFreq,dtTim; QueryPerformanceFrequency(& litmp); dfFreq=(double)litmp.QuadPart;//获得计数器的时钟频率 QueryPerformanceCounter(&litmp); QPartl=litmp.QuadPart;//获得初始值 do { &
nbsp; QueryPerformanceCounter(& litmp); QPm2=litmp.QuadPart;//获得中止值 dfMinus=(double)(QPm2-QPartl); dfTim=dfMinus/dfFreq;//获得对应的时间值。单位为s } while(dtTim<O.000001); 经测试,其定时误差一般不超过0.5μs,精度与CPU等机器配置有关。本系统只需要30~300μs的精度,所以用此方法可以满足精度的要求。但是此方法依然存在缺点,程序要不断地运行,并不断地强制CPU中断,使用时会占用很高的CPU,若将其放在主程序中,甚至可能会使程序和系统假死。为了解决此问题,可以使用多线程技术。 用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义。 进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其他系统资源组成。进程在运行时创建的资源随着进程的终止而死亡。线程的基本思想很简单,它是一个独立的执行流,是进程内部的一个独立的执行单元,相当于一个子程序,它对应于Visual C++中的CWinThread类对象。单独一个执行程序运行时,缺省地包含的一个主线程,主线程以函数地址的形式出现,提供程序的启动点,如main()或WinMain()函数等。当主线程终止时,进程也随之终止。根据实际需要,应用程序可以分解成许多独立执行的线程,每个线程并行的运行在同一进程中。 一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行,由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU的时间,优先级高的线程优先运行,优先级低的线程则继续等待。 线程被分为两种:用户界面线程和工作线程(又称为后台线程)。用户界面线程通常用来处理用户的输入并响应各种事件和消息,其实,应用程序的主执行线程CWinAPP对象就是一个用户界面线程,当应用程序启动时自动创建和启动,同样它的终止也意味着该程序的结束,进程终止。工作线程用来执行程序的后台处理任务,比如计算、调度、对串口的读写操作等,它和用户界面线程的区别是它不用从CWinThread类派生来创建,对它来说最重要的是如何实现工作线程任务的运行控制函数。工作线程和用户界面线程启动时要调用同一个函数的不同版本;一个进程中的所有线程共享它们父进程的变量,但同时每个线程可以拥有自己的变量。 使用多线程可以减少程序对CPU的占用,使程序运行更高效、可靠。多线程的函数表述如下: UINT Work_Proc(LPVOID 1Param); 函数内完成功能的操作,并不断发送消息提示中断,以使CPU去处理实时性的事件。在MFC中,开启线程时使用AfxBeginThread(),开启后线程会能自动执行函数体的程序,主线程还可以继续自己的工作。也可以通过调用CWinThread::SetThreadPriority来设置线程的优先
级,用CWinThread::SuspendThread来挂起线程。如果线程被挂起,那么直到调用CWinThread::ResumeThread后线程才开始运行。若要中止线程,可使用ExitThread()函数,若要从外部中止线程,可用TerminateThread()函数。 3 结 论 经实验,使用多线程可以明显提高系统的响应和效率。只是由于中断的频率较高,CPU一直处于满负荷状态,但此方法解决了实时性和系统响应的问题,将实时控制周期减少到了1ms以内,基本满足了数控系统的实时性要求。
|