Table of Contents
Menu 8254
Adresse de base
Cette boîte de dialogue est la même que celle du menu 8255.
Fréquence du Quartz
Cette boîte de dialogue permet de sélectionner la fréquence du quartz utilisé sur la carte. Cette fréquence est utilisée dans différents calculs, telle que la recherche du meilleur facteur de division pour le générateur de fréquence.
Générateur
Cette boîte de dialogue est identique au programme PIT8254.EXE qui a déjà été décrite précédemment.
Fréquencemètre
Le fréquencemètre n'a pu être incorporé au composant TPPI8254, à cause des détournements d'interruptions, et a été écrit directement dans le programme ETIPCBUS.EXE.
La fréquence mesurée par le fréquencemètre est issue du générateur décrit précédemment:
Principe de fonctionnement
Tout d'abord, un petit dessin pour mieux comprendre ce que je vais vous expliquer:
Le calcul de la fréquence se base sur le comptage du nombre d'impulsions issues du générateur. La durée de l'échantillonnage (choisie par l'utilisateur) est de 0.5, 1, 5 ou 10 secondes.
La première chose à savoir est que chaque seconde, 18.2 ticks sont émis par le processeur.
A chacun de ces ticks, la fonction pointée par le vecteur d'interruption 1C est exécutée. S'il on place une nouvelle fonction, à l'adresse pointée par ce vecteur, et que cette fonction décrémente un compteur à chaque fois qu'elle est appelée, on aura un moyen simple et précis de mesurer notre durée d'échantillonnage.
Le tableau ci-après montre l'équivalence qu'il y a entre la durée d'échantillonnage et le nombre de ticks qu'il faut compter:
Durée de l'échantillonage en [s] | Nombre de ticks |
---|---|
0,5 | 9 |
1 | 18 |
5 | 91 |
10 | 182 |
Comme le nombre d'impulsions à compter serait trop important si on les prenaient directement à la sortie du générateur, on utilise un second compteur qui envoie une impulsion toutes les 65535 impulsions reçues. Cette impulsion de sortie est envoyée sur l'IRQ 7 du bus du PC.
S'il on remplace la fonction appelée par le vecteur d'interruption de l'IRQ 7 par une nouvelle fonction qui incrémente un compteur à chaque fois qu'elle est appelée, le comptage des impulsions devient aisé.
Oui, mais si la fin de l'échantillonnage intervient avant la fin d'un cycle de comptage du fréquencemètre ? No problemo! Le PIT8254 possède une fonction LATCH qui bloque la valeur du compteur jusqu'à ce qu'elle soit lue.
Pour connaître le nombre total d'impulsion, il suffit d'additionner la dernière valeur présente sur le compteur au nombre de cycles comptés multiplié par 65536.
Notions de base sur les interruptions
Je viens à plusieurs reprises de vous parler d'interruptions, de vecteurs d'interruptions et du détournement de ces vecteurs. Qu'est-ce donc ?
Une interruption est un mécanisme qui permet à un périphérique d'interrompre brièvement le processeur dans l'exécution courante pour l'obliger à se brancher sur un sous programme appelé gestionnaire d'interruption. Chaque adresse de ces sous-programmes (il y en a 255) est stocké dans un tableau appelé “Table des vecteurs d'interruptions”.
Voici un extrait de la table des vecteurs:
N° du vecteur | Affectation |
---|---|
00 | CPU: Division par 0 |
01 | CPU: Pas à pas |
02 | CPU: NMI (Défaut dans RAM) |
05 | Copie écran |
07 | Réservé (80286 seul.) |
08 | IRQ 0: Timer (Appel 18,2 fois/sec) |
09 | IRQ 1: Clavier |
0A | IRQ 2: 2ème 8259 |
0B | IRQ 3: Com 2 |
0C | IRQ 4: Com 1 |
0D | IRQ 4: HD |
0E | IRQ 6: FDD |
0F | IRQ 7: Imprimante |
10 | BIOS: Fonctions vidéo |
18 | Appel BASIC en ROM |
19 | = CTRL-ALT-DEL |
1C | Appel après chaque INT8 |
28-3F | Réservé pour différentes fonctions non documentées du DOS |
42-45 | Réservé |
4B-67 | Librement définissable par le programme utilisateur |
70 | IRQ 8: Horloge en temps réel |
71 | IRQ 9 |
72 | IRQ 10 |
73 | IRQ 11 |
74 | IRQ 12 |
75 | IRQ 13 |
76 | IRQ 14 |
77 | IRQ 15 |
Pour changer la fonction appelée par un vecteur d'interruption, il faut tout d'abord lire ce pointeur. Sous DOS, en Turbo Pascal, il y avait 2 fonctions:
- GetIntVect pour lire un vecteur d'interruption
- SetIntVect pour initialiser un vecteur d'interruption
Ces deux fonctions n'existent plus sous Delphi… Mais il existe 2 fonctions similaires en mode protégé (ou DPMI). Il s'agit des fonctions 204h et 205h de l'INT 31h.
Voici le code utilisé pour l'appel de ces fonctions du mode DPMI:
PROCEDURE GetProtectedModeInt(IntNo:Byte;var Handler:Pointer); ASSEMBLER; ASM MOV AX, 0204h MOV BL, IntNo INT 31h LES DI, Handler MOV WORD PTR ES:[DI], DX MOV WORD PTR ES:[DI+2], CX END; {PROCEDURE GetProtectedModeInt} FUNCTION SetProtectedModeInt(IntNo:Byte; Handler:Pointer):Word; ASSEMBLER; ASM MOV BL, IntNo MOV DX, WORD PTR HANDLER MOV CX, WORD PTR HANDLER + 2 MOV AX, 0205h INT 31h JC @@ExitPoint XOR AX, AX @@ExitPoint: END; {FUNCTION SetProtectedModeInt}
Si une on détourne une interruption, il y a plusieurs points à respecter:
- Les procédures ou fonctions doivent être déclarées comme FAR.
- Le mot INTERRUPT doit être utilisé pour que le compilateur sache qu'il s'agit d'une interruption et non pas d'une procédure standard.
- A la fin du traitement, il faut soit appeler la procédure de traitement normal, soit quittancer le contrôleur d'interruption PIC8259 par l'envoi du mot de contrôle $20 à l'adresse $20.
- L'interruption utilisée ne doit pas être masquée
Voici les deux procédures utilisée dans notre programme:
{$F+} { Procédure déclarée comme FAR } PROCEDURE NewINT7; INTERRUPT; BEGIN Inc(NbInter); OutPortB($20, $20); { Quittance le contrôleur d'interrupt } END; {PROCEDURE NewINT7} {$F-} {$F+} { Procédure déclarée comme FAR } PROCEDURE NewINT1C; INTERRUPT; BEGIN Dec(Compteur); INLINE ( $9C ); { Mise en ordre de la pile (PUSH) } OldInt1CProc; { Execute l'ancienne fonction } END; {PROCEDURE NewINT1C} {$F-}
De plus, Microsoft nous donne l'information suivante dans le Technet:
QUESTION:
Comment rentre-t-on dans une section critique et en ressort-on pour récupérer tout le temps CPU sans être dérangé par le multitâche de Windows en mode 386, que ce soit dans une DLL, une application Windows ou un programme DOS tournant dans une boîte DOS sous Windows?
REPONSE:
Il suffit d'exécuter la fonction suivante
void NEAR PASCAL CriticalSectionON () {
asm push ax
asm mov ax, 0x1681
asm int 0x2F
}
pour forcer Windows à entrer dans une section critique. Pour sortir d'une section critique il suffit d'appeler la fonction suivante:
void NEAR PASCAL CriticalSectionOFF () {
asm push ax
asm mov ax, 0x1682
asm int 0x2F
}
Il ne faut surtout pas oublier de sortir d'une section critique car si la sortie n'est pas effectuée tout le fonctionnement de Windows se bloque.
Une dernière chose avant de vous montrer le résultat de tout ce développement: le calcul de la fréquence:
$f = \frac{1}{T} \Rightarrow f = \frac{DureeEchantillonage}{NombreImpulsions} \Rightarrow f = \frac{1}{\frac{DureeEchantillonage}{NombreImpulsions}} = \frac{NombreImpulsions}{DureeEchantillonage}$
La boîte de dialogue du fréquencemètre
Pour faciliter le développement, et diminuer le nombre de possibilités, seul le compteur 1 peut être utilisé et seule l'IRQ 7 est utilisable.
Après avoir choisi la durée de l'échantillonnage, le bouton Start est activé.
Une fois que l'échantillonnage est terminé, la fréquence trouvée est affichée.