Fréquencemètre à microcontrôleur PIC – Mesure
La routine de mesure est le coeur du fréquencemètre. A chaque boucle du programme elle est appelée 2 fois:
- pour l’auto calibrage,
- pour la mesure réelle.
Description de la routine de mesure
La fréquence à mesurer est appliquée sur RA4/T0CKI. La routine est chargée de relever à chaque cycle le compteur TMR0. La représentation d’une fréquence maximum de 50 MHz nécessite en binaire, 25 bits, il faut donc utiliser 4 compteurs de 8 bits soit 32 bits. Comme TMR0 est limité à 8 bits, elle détecte le débordement de TMR0 en comparant sa valeur avec la valeur stockée au cycle précédent TMR0_old. Quand TMR0 < TMR0_old, elle reporte la retenue aux niveaux supérieurs. La durée d’un cycle de la routine de mesure est de 25 us avec un PIC 16F84 à 4 MHz. J’ai choisi cette durée qui est sous-multiple de 275 us, durée de l’auto calibrage, et de 500 ms durée de la mesure réelle.
Paramètres:
gateLow = nombre de cycles bas,
gateHigh = nombre de cycles haut,
Durée de la mesure = gateHigh x gateLow x 25us
Compteur Binary Frequency Counter = BFC3 (32 bits), BFC2, BFC1, BFC0 (LSB)
TMR0_old = valeur de TMR0 du cycle précédent, initialisée à zéro.
Auto calibrage
Il permet de régler le prescaler pour la mesure réelle. L’auto calibrage consiste à effectuer une mesure pendant 275us avec le prescaler = 256. A l’issue de cette mesure, nous obtenons dans le compteur BFC0 une approximation de la gamme de fréquence en MHz.
1 MHz x 275us / 256 = 1,07 => BFC0 = 1
2 MHz x 275us / 256 = 2,14 => BFC0 = 2
3 MHz x 275us / 256 = 3,22 => BFC0 = 3
…
10 MHz x 275us / 256 = 10,74 => BFC0 = 10
…
20 MHz x 275us / 256 = 21,48 => BFC0 = 21
…
50 MHz x 275us / 256 = 53,71 => BFC0 = 53
Remarque: compte-tenu de la durée de mesure de 275us et le la valeur du prescaler de 256, les fréquences < 1 x 256 / 275 soit 0,930908 MHz donneront BFC0 = 0.
Vous pouvez vérifier le résultat de l’auto calibrage sur l’afficheur. Dans le programme source rechercher la ligne ;#define AUTORANGE_TEST. Cette ligne est inactivée en commentaire. Rendez cette ligne active. Ré assemblez et vérifiez en connectant au fréquencemètre un VFO par exemple.
Calcul du pré diviseur (prescaler PS)
Le calcul est effectué simplement en examinant le bit de poids fort de BFC0 de la façon suivante:
bit 7 = 1 | 128 à 255 MHz et au dessus inutilisé
bit 6 = 1 | 064 à 128 MHz inutilisé
bit 5 = 1 | 032 à 064 MHz | PS = 5 | 64:1
bit 4 = 1 | 016 à 032 MHz | PS = 4 | 32:1
bit 3 = 1 | 008 à 016 MHz | PS = 3 | 16:1
bit 2 = 1 | 004 à 008 MHz | PS = 2 | 8: 1
bit 1 = 1 | 002 à 004 MHz | PS = 1 | 4:1
bit 0 = 1 | 000 à 002 MHz | PS = 1 | 4:1
Remarque: je n’ai pas utilisé la valeur PS=0. En effet, lors de mes essais avec cette valeur, j’obtenais une mesure erronée que je ne m’explique pas. Si un lecteur à la solution je suis preneur!
Vérifions la mesure maximum possible pour chaque gamme de fréquence, pour une durée de mesure de 500 ms:
64 MHz = 64 000 000 x 0,5 / 64 = 500 000 = 07 A1 20 (16)
32 MHz = 32 000 000 x 0,5 / 32 = 500 000 = 07 A1 20 (16)
16 MHz = 16 000 000 x 0,5 / 16 = 500 000 = 07 A1 20 (16)
08 MHz = 08 000 000 x 0,5 / 08 = 500 000 = 07 A1 20 (16)
04 MHz = 04 000 000 x 0,5 / 04 = 500 000 = 07 A1 20 (16)
Mesure réelle
Après l’auto calibrage, la mesure réelle est faite pendant 500 ms. Le résultat est ensuite multiplié une première fois par 2 (simple décalage à gauche avec report du bit de retenu) pour obtenir une valeur rapportée à une seconde. Ce résultat et encore multiplié par 2, autant de fois que l’indique le prescaler pour obtenir la valeur définitive de la fréquence en Hz. A cette valeur est éventuellement ajoutée ou ôtée IF selon l’option MODE du setup. La valeur binaire obtenue et ensuite transformée en décimal codé binaire dans BCD9 (MSB) à BCD0 (LSB) puis affichée.
Limites et précision
Avec une durée de mesure de 500 ms, la plus petite fréquence mesurable serait théoriquement de 2 Hz. Toutefois avec PS minimum = 4, la fréquence minimum mesurable = 1 x 4 / 0.5 = 8 Hz.
Précision:
- gamme 04 MHz = 008 Hz,
- gamme 08 MHz = 016 Hz,
- gamme 16 MHz = 032 Hz,
- gamme 32 MHz = 064 Hz,
- gamme 64 MHz = 128 Hz.
Modification de la durée du cycle de base de la routine de mesure
Avec une fréquence d’horloge de 10 MHz la routine ne doit pas être modifiée. Vous pouvez modifier les paramètres gateLow et gateHigh pour obtenir une durée proche de 256 us pour l’auto calibrage et une durée exacte de 500 ms pour la mesure réelle. Ainsi avec un quartz de 10 MHz, si le cycle de base = 10 us au lieu de 25 us, vous pouvez choisir 26 x 10 us = 260 us (> 256 us) pour l’auto calibrage et 200 x 250 x 10 us = 500 000 us = 500 ms pour la mesure réelle.
Si cela n’est pas suffisant il faut adapter la routine. Pour cela il faut distinguer les instructions nécessaires et suffisantes de celles qui sont là pour faire perdre du temps (nop en général). Voici la formule du cycle de base de notre routine:
cycle de base = 4p + (10+a)np + (3+b)p(n-1) + 2p + (3+c)(p-1) + 2 + 3
où
n = gateLow,
p = gateHigh,
a = temps perdu,
b = temps perdu,
c = temps perdu,
Les valeurs fixes 4, 10, 2, 3 sont la durée des instructions nécessaires avec une horloge de 4 MHz.
Avec ces valeurs pour obtenir un cycle de base de 25 us, poser n = 1 et p = 1, il vient:
cycle de base = 25 us = 4 + (10 + a) + 0 + 2 + 0 + 2 + 3 => a = 4,
poser n = 2 et p = 1, il vient
2 cycles de base = 50 us = 4 + (10 + 4)2 + (3 + b)1 + 2 + 0 + 2 + 3 => b = 8,
poser n = 1 et p = 2, il vient
2 cycles de base = 50 us = 4×2 + (10 + 4)2 + 0 + 2×2 + (3+ c) + 2 + 3 => c = 2, d’où
cycle de base = 4p + (10+4)np + (3+8)p(n-1) + 2p + (3+2)(p-1) + 2 + 3.
C’est la formule qui est utilisée dans ce programme.
a est obtenu avec 4 instructions nop, b avec 8 nop, c avec un goto supplémentaire.
Supposons par exemple une fréquence d’ horloge qui diviserait par 4 la durée des instructions et un cycle de base = 8 us, durée choisie car sous-multiple de 256 et 500000 qui peut être obtenu en faisant gateLow = 250 et gateHigh = 250 (chaque compteur est limité à 255).
Cycle de base = 8 us = p + (2.5 + a)np + (0.75 + b)p(n-1) + 0.5p + (0.75+c)(p-1) + 0.5 + 0.75,
avec n = 1 p = 1, il vient
cycle de base = 8us = 1 + (2.5 + a) + 0 + 0.5 + 0 + 0.5 + 0.75 => a = 2.75,
avec n = 2 et p = 1, il vient
2 cycles de base = 16 us = 1 +(2.5 + 2.75)2 + (0.75 + b) + 0.5 + 0 + 0.5 + 0.75 = b = 2,
avec n = 1 et p = 2, il vient
2 cycles de base = 16 us = 2 +(2.5 + 2.75)2 + 0 + 0.5×2 + (0.75+c) + 0.5 + 0.75 => c = 0.5, d’où
cycle de base = 8us = p + (2.5 + 2.75)np + (0.75 + 2)p(n-1) + 0.5p + (0.75+0.5)(p-1) + 0.5 + 0.75.
Avec ces valeurs pour l’auto calibrage = 256 us = 32 x 8 us, n = 32 et p = 1, il vient
32 cycles de base = 1 + (2.5 + 2.75)32 + (0.75 + 2)31 + 0.5 + 0 + 0.5 + 0.75 = 256 us C.Q.F.D.
La mesure réelle = 500 ms = 62500 x 8 us, n = 250 et p = 250, il vient
62500 cycles de base = 250 + (2.5 + 2.75)62500 + (0.75 + 2)250×249 + 0.5×250 + (0.75+0.5)249 + 0.5 + 0.75 = 500 000 us C.Q.F.D.
a pourrait être obtenu avec 11 nop, b avec 8 nop, c en laissant le même goto supplémentaire.
Dans le Debugger de MPLAB, il y a un excellent outil qui s’appelle StopWatch qui permet de connaître la durée exacte de notre routine. Indiquer au préalable la valeur de la fréquence horloge en choisissant Setting dans le menu du Debugger.
Ci-dessous la routine de mesure qui finalement contient peu d’instructions.
;******************************************************************************** ; Parameters : gate time high = p, gate time low = n ; Gate time = 4p + (10+4)np + (3+8)p(n-1) + 2p + (3+2)(p-1) + 2 + 3 ; One step = 25 us with XTAL = 4 MHz ; 275 us = 1 x 11 x 25 us => p = 1, n = 11 ; 500 ms = 100 x 200 x 0.025 ms => p = 100, n = 200 ;******************************************************************************** Measure BANK1 movwf OPTION_REG ; BANK0 clrf BFC0-1 ; clear 16 bits counter clrf BFC0-2 ; clear 24 bits counter clrf BFC0-3 ; clear 32 bits counter bcf PORTA,0x03 movf gateHigh,w movwf countHigh clrf TMR0_old clrf TMR0 COUNT_START ; start count M05 movfw gateLow ; | movwf countLow ; | = 4p goto M20 ; | M10 ; c goto M05 ; = 2(p-1) ; b = 8 nop M15 nop ; | nop ; | nop ; | nop ; | = 8p(n-1) nop ; | nop ; | nop ; | nop ; | M20 movf TMR0,w ; TMR0 rollover ? ; | subwf TMR0_old,f ; TMR0_old - TMR0 ; | btfss STATUS,Z ; 0 = no change ; | goto M25 ; | nop ; | nop ; | nop ; | goto M30 ; | M25 btfsc STATUS,C ; TMR0 < TMR0_old ? ; | = (10+4)np incf BFC0-1,f ; 16 bits counter ; | btfsc STATUS,Z ; | incf BFC0-2,f ; 24 bits counter ; | M30 movwf TMR0_old ; | ; a = 4 nop nop ; | nop ; | nop ; | nop ; | decfsz countLow,f ; = 2p goto M15 ; = 3p(n-1) decfsz countHigh,f ; = 2 goto M10 ; = 3(p-1) COUNT_STOP ; = 3 ; last value movf TMR0,w ; test for TMR0 rollover movwf BFC0 ; save 8 bits counter subwf TMR0_old,f btfsc STATUS,Z ; rollover ? goto M_35 ; no btfsc STATUS,C incf BFC0-1,f ; 16 bits counter btfsc STATUS,Z incf BFC0-2,f ; 24 bits counter M_35 retlw 0x00
Télécharger le fichier Kicad du schèma .
Télécharger les fichiers source et hexa du fréquencemètre .
Liens
Fréquencemètre à microcontrôleur PIC
Fréquencemètre à microcontrôleur PIC – Description
Fréquencemètre à microcontrôleur PIC – Structure du programme
Fréquencemètre à microcontrôleur PIC – Mesure
Fréquencemètre à microcontrôleur PIC – Commande de l’afficheur LCD
Fréquencemètre à microcontrôleur PIC – Réalisation
[...] PIC – Description Fréquencemètre à microcontrôleur PIC – Structure du programme Fréquencemètre à microcontrôleur PIC – Mesure Fréquencemètre à microcontrôleur PIC – Commande de l’afficheur LCD Fréquencemètre [...]