Windows 7/32位需要稳定,准确的10mSec计时器 [英] Stable, accurate 10mSec timer required in Windows 7/32 bit

查看:187
本文介绍了Windows 7/32位需要稳定,准确的10mSec计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,需要在Windows 7/32位计算机上以10mSec速率(100hz)运行(该应用程序还将同时运行其他应用程序).我知道Windows不是RTOS,但是我们对使用它的要求有些拘束.此中断可以有一些最少的延迟(100uSec)响应,但一定不能长时间漂移.我有一个程序已加载并使用NtSetTimerResolution将计时器设置为10毫秒分辨率,然后使用CreateTimerQueue/CreateTimereQueueTimer函数以及用于切换GPIO引脚的回调例程(暂时)创建了计时器-这会产生只要我不对系统做任何其他事情,就可以预期方波.当我开始其他几个过程时,方波的精度超出了预期.有什么方法可以在计时器中断(或我可以使用的另一个计时器)上获得更高的优先级,从而产生更稳定的输出(也许是SMI)?我的代码在下面,并使用Windows DDK的x86检查的构建环境构建,并从具有管理员权限的命令外壳运行:


I have an application that I need to run at a 10mSec rate (100hz) on a Windows 7/32 bit computer (that will also be running other applications at the same time). I know that windows is not an RTOS, but we are sort of stuck with a requirement to use it. This interrupt can have some minimally late (100uSec) responses, but must not drift over a prolonged time. I have a program where I have loaded and used the NtSetTimerResolution to set the timers to 10msec resolution, and then created a timer using the CreateTimerQueue/CreateTimereQueueTimer functions with a callback routine that toggles a GPIO pin (for the time being) - this produces the expected square wave, so long as I am not doing anything else with the system. When I start a couple of other processes, the accuracy of my square wave goes out the window. Is there any way to get a higher priority level on the timer interrupt (or is there another timer that I can use) that will produce a more stable output (perhaps the SMI)? My code is below, and is built using the x86 checked build environment of the Windows DDK, and run from a command shell with administrator rights:


/*
Abstract:

Simple console test app for a 10mSec timer interrupt service

Enviroment:

Administrator Mode

*/


/* INCLUDES */

#include     <windows.h>
#include     <winioctl.h>
#include     <stdio.h>
#include     <string.h>
#include     <stdlib.h>
#include     <conio.h>
#include     <strsafe.h>

#include     <stdlib.h>
#include     <stdio.h>

#include     <winsock2.h>
#include     <mswsock.h>

#pragma warning(disable:4127)   // condition expression is constant

FARPROC pNtQueryTimerResolution;
FARPROC pNtSetTimerResolution;

static  HANDLE    NTDLLModuleHandle;
static  HINSTANCE hInpOutDll;

typedef         void  (   __stdcall  *lpOut32 )( short , short );
typedef  short        (   __stdcall  *lpInp32 )( short );
typedef  BOOL         (   __stdcall  *lpIsInpOutDriverOpen )( void );

//Some global function pointers (messy but fine for an example)
lpOut32              gfpOut32;
lpInp32              gfpInp32;
lpIsInpOutDriverOpen gfpIsInpOutDriverOpen;


void CALLBACK TimerProc(void* lpParameter,
    BOOLEAN TimerOrWaitFired);

// MAIN

VOID  __cdecl    main( void )
{
    ULONG ulMinRes = 0;
    ULONG ulMaxRes = 0;
    ULONG ulCurRes = 0;

    HANDLE phNewQueue;
    HANDLE phNewTimer;

    phNewQueue        = CreateTimerQueue( );

    NTDLLModuleHandle = LoadLibrary( "NTDLL.DLL" );

    if( NULL == NTDLLModuleHandle )
    {
        return;
    }

    // Get the function pointers,
    pNtQueryTimerResolution = GetProcAddress( NTDLLModuleHandle, "NtQueryTimerResolution" );
    pNtSetTimerResolution = GetProcAddress( NTDLLModuleHandle, "NtSetTimerResolution" );

    if( ( pNtQueryTimerResolution == NULL ) || ( pNtSetTimerResolution == NULL ) )
    {
        printf( "unable to link to ddl\n\n\n\n\n\n" );
        return;
    }

    pNtQueryTimerResolution( &ulMinRes, &ulMaxRes, &ulCurRes );
    printf( "MMR:  %d   %d   %d\n", ulMinRes, ulMaxRes, ulCurRes );

    ulMaxRes = 100000;
    pNtSetTimerResolution( ulMaxRes, TRUE, &ulCurRes );

    pNtQueryTimerResolution( &ulMinRes, &ulMaxRes, &ulCurRes );
    printf( "MMR:  %d   %d   %d\n", ulMinRes, ulMaxRes, ulCurRes );

    //Dynamically load the DLL at runtime (not linked at compile time)
    hInpOutDll = LoadLibrary( "InpOut32.DLL" );
    if( hInpOutDll != NULL )
    {
        gfpOut32 = ( lpOut32 )GetProcAddress( hInpOutDll, "Out32" );
        gfpInp32 = ( lpInp32 )GetProcAddress( hInpOutDll, "Inp32" );
        gfpIsInpOutDriverOpen
            = ( lpIsInpOutDriverOpen )GetProcAddress( hInpOutDll, "IsInpOutDriverOpen" );

        if( gfpIsInpOutDriverOpen( ) )
        {
            gfpOut32( 0xA01, 0x00 );
        }
        else
        {
            printf( "unable to create timer system\n\n\n\n\n\n" );
            return;
        }
    }

    CreateTimerQueueTimer( &phNewTimer, phNewQueue, TimerProc, NULL, 0, 10,
                       WT_EXECUTEINTIMERTHREAD );

    do
    {
        Sleep( 1 );
    } while( TRUE );
}

void CALLBACK TimerProc(void* lpParameter,
    BOOLEAN TimerOrWaitFired)
{
    WORD wData;

    UNREFERENCED_PARAMETER  ( lpParameter );
    UNREFERENCED_PARAMETER  ( TimerOrWaitFired );

    wData = gfpInp32( 0xA00 );
    wData++;
    gfpOut32( 0xA00, wData );
}

推荐答案

我不知道计时器的准确性,但是您可以使用SetThreadPriority来获取最接近真实的值在Windows上的时间是这样的:
I don''t know about the accuracy of the timer, but you can use SetThreadPriority to get the closest thing to true real time on Windows like so:
HANDLE hThread = GetCurrentThread(void);
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);


(摘自此处 [ ^ ])


(from here[^])


这篇关于Windows 7/32位需要稳定,准确的10mSec计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆