e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Přesný čas na počítačích PC

Pavel Mach

Při práci na počítačích PC se vyskytne mnoho situací, kdy potřebujeme změřit přesný časový interval. Funkce dosu (interrupt 21h, při ah=2ch) nám sice vrací čas s přesností na setiny, ale to v mnoha situacích nestačí (zvlášť když je čas počítán v 55ms inkrementech, takže o přesnosti na setiny sekundy vůbec nemůžeme mluvit). Se stejným výsledkem se můžeme obrátit na přerušení 1Ah BIOSu.

Kde tedy zjistíme přesnější časovou informaci?
Počítače PC jsou vybaveny obvodem 8253 (u AT 8254), který obsahuje tři nezávislé kanály čítače/časovače s kmitočtem 1193180 Hz. Komunikace s obvodem probíhá přes porty 40h-43h. Kanál 0 (port 40h) se využívá systémovými hodinami a časují se jím diskové operace, kanál 1 je využit pro občerstvování paměti a kanál 2 je připojen na reproduktor a slouží ke generování zvuků. Všechny kanály jsou ovládány portem 43h.

Pro zjištění přesného časového intervalu jsem použil kanál 0. Tento kanál je standartně naprogramován tak, že každých 65536 tiků hodin (asi 18,2 krát za sekundu) vyvolá přerušení 8h. Toto přerušení pokaždé inkrementuje čtyřbajtovou proměnnou na adrese 0:46Ch. Pro zjištění přesného počtu 1,19 megahertzových tiků stačí přečíst hodnotu na této adrese, vynásobit ji 65536 a přičíst k ní hodnotu z portu 40h. Realizaci v jazyce C a ASM uvádím níže. Je provedena formou makra, neboť volání funkce by výsledek zkreslilo.

Nejdelší interval, který je možno změřit, je o něco menší než 1 hodina.

// Příklad a definice maker: unsigned long TIMER0; // proměnná použitá v makru GT // Makro RT uloží do parametru t hodnotu // z adresy 0:46Ch (počet tiků děleno // 65536) a do parametru a uloží počet tiků // modulo 65536 (přečteno z portu 40h) #define RT(t,a) asm { mov al,00000110b; out 43h,al; in al,40h; mov ah,al;\ in al,40h; xor cx,cx; mov es,cx; mov cx,word ptr es:[46ch];\ mov dx,word ptr es:[46ch+2]; xchg ah,al; mov word ptr t,cx;\ mov word ptr t+2,dx; mov word ptr a,ax; } // Makro GT vloží do parametru q rozdíl // současného počtu tiků a počtu tiků // v proměnné TIMER0 #define GT(tq) asm { mov al,00000110b; out 43h,al; in al,40h; mov ah,al; in al,40h; xor cx,cx; mov es,cx; mov cx,word ptr es:[46ch]; mov dx,word ptr es:[46ch+2]; xchg ah,al; sub cx,word ptr TIMER0; not ax; inc ax; mov word ptr tq,ax; mov word ptr tq+2,cx; } #define TPS 1193180L // počet tiků za sekundu // funkce inittimer inicializuje proměnnou TIMER0 void settimer( void ) { unsigned a; do RT(TIMER0,a) while (a > 3); // u PC 16MHz a lepších lze místo 3 psát 2, 1 nebo i 0 } void test_func( void ) { unsigned i; for (i = 0; i < 65535; i++) ; } // Příklad použití #include <conio.h> main() { unsigned long t_zacatek,t_konec; // proměnné pro uložení začátku a konce měřeného intervalu settimer(); // inicializujem proměnnou TIMER0 GT(t_zacatek); // přečteme hodnotu časovače na začátku // měření delay(6000); // zavoláme funkci, jejíž dobu trvání // chceme měřit GT(t_konec); // přečteme časovač na konci měření printf("\nDoba provedení funkce je %1.4fs\n", (double)(t_konec-t_zacatek)/TPS); return; }


Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC