在不采用硬件计时器的情况下如何创建更精确的计时器

在不采用硬件计时器的情况下如何创建更精确的计时器?最精确周期能否达到1毫秒?  对于精确值的要求不同,所采用的办法不同。以下阐述几种办法。  1、在单线程中循环调用API Sleep函数,Sleep函数精确程度为如果Sleep(N),那么实际睡眠时间在N到N+1毫秒之间。而且还要注意调用Sleep的线程优先级的问题。如果任务过多并且此线程优先级低,那误差就更大些。 

2、调用API QueryPerformanceCounter函数,举例如下:  LARGE_INTEGER  liFrequency;  if (QueryPerformanceFrequency(&liFrequency))  // 查询系统时钟的频率,这里将返回1000  {     liFrequency.QuadPart /= 1000;        LARGE_INTEGER  liTimeOut;        if (QueryPerformanceCounter(&liTimeOut))   //得到截至到当前累计发生的系统时钟中断次数     {        liTimeOut.QuadPart += liFrequency.QuadPart;   ///计算下一秒到来时总的中断次数是多少        LARGE_INTEGER  liCurrent;        do        {                    QueryPerformanceCounter(&liCurrent);    // 循环查询累计的的中断次数        } while (liCurrent.QuadPart < liTimeOut.QuadPart); ///到达下一秒     }  }  调用QueryPerformanceCounter同调用Sleep在本质上都是一样的,都是在单线程中无限循环等到周期一到执行任务,相比较 QueryPerformanceCounter要比Sleep更精确些,越精确就越要求线程的优先级,保障线程能够正常得到处理器。 

3、以上办法难以保证周期精确到1毫秒并且WINCE系统稳定地运行,所以要从中断入手。以x86平台为例,先在Timer.c中将默认的SetTimer0 (TIMER_COUNT)中的TIMER_COUNT /=2,SetTimer0函数负责设置系统时钟的频率,默认1毫秒发生一次中断,如果除以2就是0.5毫秒发生一次中断。然后在fwpc.c文件中修改ISR函数PeRPISR,因为原来默认是1毫秒发生一次中断,在处理INTR_TIMER0时系统负责累计计数、管理线程的调度,返回相应的SYSINTR值,而我们没有办法再添加代码返回自己定义的SYSINTR值,所以现在要修改原来的处理代码,例如设置一个BOOL型变量,TRUE就执行原来默认的代码,而FALSE就返回我们自己定义的SYSINTR值,这样即不影响原来的ISR处理,又加入了我们的中断响应代码。ISR返回我们定义的SYSINTR后WINCE内核激活相对应的EVENT事件,我们就可以在我们编写的IST里处理任务了。 

 

如何改系统调度的默认时间片值?  更改schedule.c文件中的dwDefaultThreadQuantum 变量,然后重新编译该文件并SYSGEN。调用API CeGetThreadQuantum就知道更改是否生效。 

你可能感兴趣的:(timer,api,Integer,任务,平台,WinCE)