4

Windows 7/32 ビット コンピューターで 10 ミリ秒 (100hz) の速度で実行する必要があるアプリケーションがあります (同時に他のアプリケーションも実行されます)。この割り込みには、最小限の遅延 (100uSec) の応答が含まれる可能性がありますが、長時間ドリフトしてはなりません。NtSetTimerResolution を読み込んで使用してタイマーを 10 ミリ秒の解像度に設定し、CreateTimerQueue/CreateTimereQueueTimer 関数を使用して GPIO ピンを切り替えるコールバック ルーチンを使用してタイマーを作成したプログラムがあります (当面の間)。システムで他に何もしていない限り、予想される方形波。他のいくつかのプロセスを開始すると、方形波の精度が限界に達します。より安定した出力 (おそらく SMI) を生成するタイマー割り込み (または使用できる別のタイマー) でより高い優先度レベルを取得する方法はありますか? 私のコードは以下で、Windows DDK の x86 チェック ビルド環境を使用してビルドされ、管理者権限でコマンド シェルから実行されます。

/*

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 );
}
4

2 に答える 2

2

SetThreadPriority重要なスレッドを優先するために使用できます。この場合、スレッドを明示的に作成し、の代わりに、、を使用する必要がありCreateWaitableTimerExます。重要なスレッドが待機の間に実行に時間がかかりすぎないようにしてください。そうしないと、Windowsが正常に動作しなくなる可能性があります。SetWaitableTimerExWaitForSingleObjectExCreateTimerQueueTimer

最大ラグが100マイクロ秒の場合、これでは不十分な場合があります。関数を使用してプロセス優先度クラスをREALTIME_PRIORITY_CLASSに設定する必要がある場合がありますSetPriorityClassが、プログラムがCPUを長時間保持しないようにしてください。そうしないと、Windowsが正常に動作しなくなります。特に、プログラムがハングすると、OS全体がハングします。この状況では、電源を切る以外にプログラムを停止する方法はありません。

これでも十分ではないかもしれません。Windowsはリアルタイムオペレーティングシステムではないため、要求したとおりに実行できない場合があります。

于 2012-05-24T01:27:45.080 に答える
-1

Windows とミリ秒に関する私の経験では、信頼性が低いということです。Nusbio デバイスを介してオシロスコープで Sleep API を測定しました。また、Sleep(0) は、メソッドをまったく呼び出さないこととは異なります。Sleep(5) と Sleep(15) は、待機時間が同じであっても一貫性のない結果を返すことがあります。

この精度が必要な場合は、Windows アプリケーションと通信できるマイクロ コントローラーが必要です。

于 2016-01-12T20:30:16.720 に答える