Windows-Timer(genau?)

Software für PC wie Open Office, Antvirenprogramme, Firewalls usw. Programmiersprachen wie Visual Basic, Pascal, C++.

Software für PC wie Open Office, Antvirenprogramme, Firewalls usw. Programmiersprachen wie Visual Basic, Pascal, C++.

Moderator: Moderatorengruppe

Windows-Timer(genau?)

Neuer Beitragvon Master-Jimmy am Freitag 13. Juli 2007, 17:24

Die WindowsAPI bietet einem ja die Möglichkeit der Timer...
Meine Frage ist nun: Sind diese Timer eigentlich genau?

Beispiel:
Untenstehendes Programm gibt ein 1Hz-Rechteck auf Pin2 des LPT1 aus.-Das funktioniert auch ganz gut(Treiber "UserPort" installieren).
Es ist mal klar, dass folgender Teil eine kleine Ungenauigkeit verursacht:
Code: Alles auswählen
while(GetMessage(&msg,NULL,0,0))
{
   TranslateMessage(&msg);
   DispatchMessage(&msg);
}

Auch die Switches in der WinProc brauchen ihre Zeit.
Ausserdem bedeutet Windows unteranderem Multitasking, und die Ausführung meines Programms wird so doch wahrscheinlich hübsch "zerstückelt"?
Was dieser UserPort-Treiber genau macht ist mir auch nicht wirklich bekannt...
Hat jemand also eine Ahnung, in welcher Grössenordnung die Abweichungen sich ca. befinden könnten?

Code: Alles auswählen
#include <windows.h>
#include <conio.h>

#define    TIMER_FLAG              1
#define    LPT_PIN_1_TOGGELN       _outp(0x378,((_inp(0x378))^0x01));

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)
{   
   HWND      hWnd;
   MSG       msg;
   WNDCLASS  wc;

   wc.style           =   CS_HREDRAW|CS_VREDRAW;
   wc.lpfnWndProc     =   WndProc;
   wc.cbClsExtra      =   0;
   wc.cbWndExtra      =   0;
   wc.hInstance       =   hInstance;
   wc.hCursor         =   LoadCursor(NULL,IDC_ARROW);
   wc.hIcon           =   LoadIcon(NULL,IDI_APPLICATION);
   wc.hbrBackground   =   (HBRUSH)GetStockObject(WHITE_BRUSH);
   wc.lpszClassName   =   TEXT("Timer-Testprogramm");
   wc.lpszMenuName    =   NULL;
   RegisterClass(&wc);

   hWnd=CreateWindow(  TEXT("Timer-Testprogramm"),
                       TEXT("Timer-Testprogramm"),
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       NULL,
                       NULL,
                       hInstance,
                       NULL);

   ShowWindow(hWnd,iCmdShow);
   UpdateWindow(hWnd);

   SetTimer(hWnd,TIMER_FLAG,500,NULL);

   while(GetMessage(&msg,NULL,0,0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
   switch(message)
   {
      case WM_DESTROY:
      {
         PostQuitMessage(0);
         return 0;
      }
      case WM_TIMER:
      {
         switch(wParam)
         {
            case TIMER_FLAG:
            {
               LPT_PIN_1_TOGGELN
               break;
            }
            default:
            {
               ;
            }
         }
         return 0;
      }
      default:
      {
         ;
      }
   }
   return DefWindowProc(hWnd,message,wParam,lParam);
}


P.S.: Falls jemand das Programm testen will, aber keine Lust die Kiste hervor zu ziehen um den LPT zu messen: Es gibt da ein hübsches Programm namens parmon.exe, welches die Pegel am Druckerport grafisch anzeigt.(--> Link)
Mit dem Code könnte man vielleicht auch so ein "Hobby-Funktionsgenerator" basteln...
Benutzeravatar
Master-Jimmy
Threadstarter
27703
Titanium Mitlgied
 
Beiträge: 401
Registriert: Mittwoch 11. April 2007, 10:21
Postleitzahl: 00000
Land: not selected

Neuer Beitragvon anders am Mittwoch 25. Juli 2007, 06:18

Selbst wenn die Timer im Mittel keine Zyklen verlieren, kann das Timing nicht besser sein als der CPU-Quarz und der ist gewöhnlich kein Wunder an Genauigkeit.
Im Kurzzeitbereich wird durch höher priorisierte Interrupts sicherlich noch ein Jitter dazukommen.

Hätte ich kein Oszilloskop, würde ich versuchen es auf folgende Weise zu "messen":
Eine Muschel eines Stereokopfhörers wird über einen Kondensator (0,1..10µF) an einen Pin des LPT angeschlossen, auf dem dein Programm ein 0,5Hz (weil man beide Flanken hört) Rechteck ausgibt.
Die andere Kopfhörermuschel wird mit dem Motoranschluss eines billigen analogen Quarzweckers verbunden.
Irgendwie musst du deinem Programm dann noch beibringen, daß du den Startzeitpunkt des Timers mit dem Ticken des Weckers synchronisieren kannst.

Auf diese Weise kannst du problemlos hören, wenn die beiden Ticks voneinander abweichen.
Wenn du statt Tick-Tick-Tick ein symmetrisches Tick-Tack hörst, weisst du, daß der Zeitunterschied einige 100ms beträgt.

Wahrscheinlich erzeugt aber das zeitliche Auseinanderdriften der Zeitmarken einen ausgeprägten Richtungseffekt, der eine noch viel genauere Messung ermöglicht.
Wenn die Ticks zusammenfallen, sollte man die Schallquelle vor sich hören.
Wenn sich die Schallquelle von geradeaus auf 45° verschiebt, bedeutet das einen Zeitunterschied von weniger als 400µs.
Ich schätze, dass ein Jitter von 100µs einwandfrei hörbar ist. Unterschätze die Wetware zwischen den Ohren nicht!
anders
27846
Moderator
 
Beiträge: 4690
Registriert: Freitag 28. Februar 2003, 13:46


Zurück zu Computer Software

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste