Timer w Turbo C
cepa
Obsługa Timera systemowego pod Turbo C
Timer systemowy to prosty układ, ktory generuje 18,2 razy na sekunde przerwanie sprzetowe
08h. Programista ma do dyspozycji przerwanie programowe 1Ch podpiete pod przerwanie
sprzetowe 08h, ktore jest wywolywane standardowo co 54,9ms. Czestotliwosci da sie zwiekszyc
ale wiaze sie to z programowaniem PIT'u czyli programowalnego dzielnika czestotliwosci
zegara, ktory jest w kazdym komputerze PC.
Aby mozna bylo korzystac z timera trzeba podmnienic domyslna nic-nie-robiaca procedure
obslugi przerwania 1Ch na wlasna. Ogolny schemat dzialania programu wyglada tak:
1 - pobierz adres starej procedury obslugi przerwania 1Ch
2 - podczep nowa procedure pod przerwanie 1Ch
3 - rob program
4 - przed zakonczeniem podmnien aktualna procedure obslugi przerwania 1Ch na stara procedura.
To wszystko co trzeba wiedziec o timerku, teraz kod :P
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
volatile int counter = 0;
volatile int can_print = 0;
void interrupt (*old_timer_proc)(__CPPARGS) = NULL;
void interrupt timer_proc(__CPPARGS)
{
counter++;
can_print = 1;
}
int main()
{
old_timer_proc = getvect(0x1C);
setvect(0x1C,timer_proc);
while(!kbhit())
{
if(can_print)
{
printf("Timer Counter = %d\\r",counter);
can_print = 0;
}
}
setvect(0x1C,old_timer_proc);
return 0;
}
Program po uruchomieniu przejmuje przerwanie i zwieksza wyswietlana liczbe.
Zmienna old_timer_proc to wskaznik do starej procedury przerwania 1Ch, ktory jest ustawiany
przez funkcje getvect(0x1C). Funkcja setvect(0x1C,timer_proc); ustawia nowa procedure
obslugi przerwania czyli przechwytuje przerwanie zegara. Funkcja timer_proc jest typu void
interrupt co oznacza, ze jest funkcja obslugi przerwania, zwieksza ona zmienna counter i
zezwala na wyswietlenie wyniku w petli za pomoca can_print. Obie zmienne (counter i can_print)
sa typu volatile poniewaz w przypadku przerwan i timerow wazny jest brak optymalizacji
zmiennych dla unikniencia roznych dziwnych bledow.
Komentarza wymaga jescze definicja __CPPARGS. Jest ona potrzebna dla funkcji setvect i
getvect, w przypadku gdy zamiast funkcji z dos.h czyli setvect i getvect uzywamy assemblera
mozna wywalic wszystko z __CPPARGS.
Timer dla DJGPP:
#include <dpmi.h>
#include <go32.h>
int GetTime(void);/returns time from InitTimer() in ticks/
void Count(void);/don't call it - it's called by timer/
void InitTimer(void);/use before GetTime()/
void EndTimer(void);/use before exiting main()/
int counter=0;
_go32_dpmi_seginfo OldISR, NewISR;
int GetTime(void)
{
return counter;
}
void Count(void)
{
counter++;
return;
}
void InitTimer(void)
{
_go32_dpmi_lock_code(Count,(long)sizeof(Count));
_go32_dpmi_lock_data((void*)&counter,(long)sizeof(int));
_go32_dpmi_get_protected_mode_interrupt_vector(8,&OldISR);
NewISR.pm_offset=(int)Count;
NewISR.pm_selector=_go32_my_cs();
_go32_dpmi_chain_protected_mode_interrupt_vector(8,&NewISR);
return;
}
void EndTimer(void)
{
_go32_dpmi_set_protected_mode_interrupt_vector(8,&OldISR);
return;
}