Electronique > Réalisations > Diviseur fréquence 001

Dernière mise à jour : 14/02/2016

Présentation

Le système présenté ici est un diviseur de fréquence programmable basé sur un PIC de type 16F84A ou 16F628A, capable de diviser entre 1 et 1023, par pas de 1, au moyen de dix interrupteurs.

diviseur_frequence_001_pcb_3d_a

On peut se limiter à huit interrupteurs de programmation, si le taux de division maximal souhaité est de 256.
Fréquence maximale du signal d'entrée : entre 25 kHz et 30 kHz pour les versions 001a à 001c, 40 kHz pour la version 001d et 150 kHz pour la version 001e. Je conseille les deux dernières versions 001d et 001e (pour 16F628A).

Schémas 001 (code logiciel 001a à 001c, avec 16F84A)

Pas spécialement complexe, mais requiert un composant programmé. Un PIC, si vous voulez tout savoir.
Schéma désormais déconseillé, voir schéma 001d et 001e à base de 16F628A. Mais le descriptif texte est encore valable pour le principe de base.

diviseur_frequence_001

Principe de base
Il est extrêmement simple, et consiste à compter le nombre de changements d'état logique sur la ligne RB7 du PIC, configurée en entrée et recevant le signal d'horloge à diviser. Quant le nombre de changements d'état a atteint le facteur de division spécifié (entre 1 et 1024), la ligne RA4 du PIC, configurée en sortie, change d'état et le compteur d'impulsions d'entrée est remis à zéro.

Facteur de division
Il est spécifié au moyen de microswitches (ou tout autres types d'interrupteurs ou commande parallèle externe), sur un bus de 10 bits. Sur le schéma, l'interrupteur le plus à droite (faisant partie du bloc appelé SW1 et relié à RA0) est celui de poids faible, et celui le plus à gauche (relié à RB5) est celui de poids fort. Sur le schéma, les interrupteurs "activés" sont ceux dont la partie noire est en bas (côté ON de SW1), en l'occurence les deuxième et quatrième interrupteurs en partant de la droite. Le deuxième interrupteur (toujours en partant de la droite) correspond à la valeur "2 puissance 1", soit 2. Le quatrième interrupteur correspond quant à lui à la valeur "2 puissance 3", soit 8. Si on additionne ces deux valeurs, on obtient 10 (8 + 2) : le facteur de division est donc de 10, et pour un signal entrant de fréquence 10 KHz, on dispose d'un signal sortant de fréquence 1 KHz.
Limitation à un facteur de division de 256
Vous pourrez préférer n'utiliser que huit microswitches au lieu de 10. Si tel est le cas, rien de plus simple, il vous suffit d'ignorer les lignes RB4 et RB5, qui restent portées au potentiel de masse au travers des résistances de rappel de 10K prévues sur le schéma. Si vous voulez économiser sur ces deux résistances, n'oubliez pas de mettre ces deux lignes RB4 et RB5 à la masse !

Relation de phase entre entrée et sortie
Il est important de noter que le traitement des changements d'états du signal d'entrée prend un certain temps, qui est lié à la durée d'exécution des routines du programme interne au PIC. Le signal de sortie n'est donc pas en phase avec le signal d'entrée, et la valeur du déphasage dépend de la fréquence du signal d'entrée. Ce n'est pas gênant pour certaines applications, mais ça peut l'être pour d'autres.

Niveaux d'entrée et de sortie
Le schéma électronique est simplifié au maximum, il n'y a ni adaptation en entrée, ni adaptation en sortie. Cela va très bien pour des signaux au format TTL (0V / +5V). Mais si vous souhaitez appliquer à l'entrée du montage des signaux d'amplitude inférieure, il faut impérativement ajouter un petit étage d'entrée, de préférence à haute ou moyenne impédance (un simple NPN de type BC109 - ou même un FET, pourquoi pas - conviendra très bien). Pour la sortie, même topo : un petit buffer de sortie permettra de ne pas exposer la sortie du PIC à un environnement qui peut parfois s'avérer "hostile". Vue les fréquences maximales mises en jeux, vous pouvez fort bien vous contenter d'une paire de transistors classiques (2N1711 + 2N2905) montés en push-pull.

Schéma 001d (code logiciel 001d, avec 16F628A)

Schéma légèrement modifié suite remplacement 16F84A par 16F628A (celui à base de 16F84 est désormais déconseillé).

diviseur_frequence_001d

Rien de spécial à dire, c'est le schéma que je préconise désormais. Les modifications matérielles suivantes ont été apportées :
- L'entrée se fait désormais sur la broche RB0 du PIC, les entrées de sélection du taux de division on été décallées en conséquence.
- Le changement du taux de division se fait désormais via la broche de reset général.

Schéma 001e (code logiciel 001e, avec 16F628A)

Schéma 001d légèrement modifié pour utilisation du Timer1 en mode compteur, les interruptions sur RB0 ne sont plus utilisées.

diviseur_frequence_001e

Avec la moitié inférieure de ce schéma 001e et le code 001e, la fréquence d'entrée max peut désormais atteindre 150 kHz. Mais petit inconvénient, la configuration des switches correspond à un taux de division double. Par exemple en configurant les switches SW1 pour un taux de division de 5, la fréquence du signal de sortie est 10 fois moindre que celle du signal d'entrée. Cela est lié au fait que le Timer1 configuré en compteur ne peut s'incrémenter que sur des fronts montants ou descendants, mais pas les deux. En préchargeant par exemple la valeur 65530 dans le Timer1, le débordement à lieu après six périodes complètes du signal entrant, et on a donc une division par 12 au lieu de 6. Une solution consiste à ajouter en amont du PIC, un circuit détecteur de fronts qui délivre une brève impulsion positive à chaque front montant ET desendant du signal entrant. C'est ce circuit que l'on voit en haut du schéma, et qui ne comporte que de classiques portes logiques TTL (ce bout de schéma peut bien sûr être utilisé à d'autres sauces). En procédant ainsi, le taux de division réel correspond bien à la valeur spécifiée par SW1. Pourquoi ne pas avoir adopté le circuit - bien plus simple - du détecteur de fronts composé d'une porte XOR et d'un circuit RC retardateur ? Tout simplement pour que notre circuit puisse fonctionner sur une large plage de fréquence.
Remarque : si le facteur de division souhaité est toujours un multiple de 2, point besoin de s'embêter avec ce complexe ajout, il suffit d'appliquer le signal à diviser directement sur la broche RB6 (JP1 orienté vers l'entrée In) !

Approches pour les différents programmes (16F84A ou 16F628A)

J'ai adopté deux approches (deux programmes différents) pour la lecture du signal d'horloge appliqué sur l'entrée RB7 :
Programme "diviseur_frequence_001a"
Approche avec interruptions pour le comptage des impulsions d'horloge : le programme ne réagit que lors des changements d'état du signal d'entrée, et le reste du temps il ne fait rien. Avec un quartz 20 MHz, j'obtiens une division correcte jusqu'à 34 KHz en entrée.
Programme "diviseur_frequence_001b"
Approche dans laquelle l'entrée d'horloge est continuellement analysée, dans la routine principale du programme. Avec un quartz 20 MHz, j'obtiens une division correcte jusqu'à 25 KHz en entrée. C'est donc un peu moins "bon" et l'on préfèrera sans doute la version avec interruptions.
Programme "diviseur_frequence_001c"
Même approche qu'avec le programme 001a, mais avec moins de code dans la routine d'interruption, le plus gros étant désormais déporté dans la procédure principale. Merci à Pierre pour ses conseils utiles !
Programme "diviseur_frequence_001d"
Même code que le programme 001c, mais avec 16F628A, désormais moins cher que le 16F84. La fréquence du signal d'entrée peut grimper un peu plus haut (40 kHz au lieu de 30 kHz auparavant).
Programme "diviseur_frequence_001e"
Dans ce programme, on utilise le Timer1 configuré en compteur avec entrée de comptage externe. Cette méthode permet de faire grimper la fréquence d'entrée max à une valeur de 150 kHz.

Comparaison avec des diviseurs spécialisés

Une fréquence d'entrée maximale de 150 kHz (ou pire encore de 25 kHz) peut prêter à sourire, si on la compare aux fréquences maximales tolérées par les circuits spécialisés, qu'ils appartiennent à la famille TTL ou CMOS. L'idée est ici de disposer d'un compteur programmable simple à mettre en oeuvre, avec un seul composant. Et le code que j'ai écrit, malgré son évidente simplicité, n'est sans doute pas un exemple à suivre d'un point de vue optimisation et compacité. Comme pour tout programme, il y a bien souvent possibilité de faire mieux. Mais à l'époque où j'ai développé les codes 001a à 001d, je débutais tout juste dans le monde des PICs, et il ne fallait pas trop m'en demander ;-)
Edition 12/12/2010 : ça monte maintenant à 40 kHz avec le 16F628A (version 001d). Cool. A la prochaine mise à jour, ça montera peut-être à 45 kHz ;-)
Edition 14/02/2016 : ça monte maintenant à 150 kHz avec le 16F628A (version 001e).

Le truc idiot qui m'a fait perdre une journée entière (c'était en 2010)

Quand j'ai entrepris ce montage, j'étais vraiment débutant dans la programmation des PIC. Je suis resté bloqué sur un problème qui m'a pris une pleine journée et pour lequel je ne m'en suis sorti qu'avec l'aide de personnes compétentes, sur le forum de MikroPascal. L'ensemble tournait correctement me semblait-il, mais version avec ou sans interruptions, le montage bloquait après le premier changement d'état de la sortie RA4, qui avait pourtant toujours lieu au bon moment, c'est à dire une fois que le nombre de changements d'état logique de l'entrée RB7 avait atteint la valeur du facteur de division spécifé. Le changement d'état avait lieu, oui, mais en même temps, il me semblait que la sortie RA4 restait dans un état indéterminé, au lieu de passer franchement à l'état logique haut. Cela aurait pû me mettre la puce à l'oreille, mais j'étais tellement persuadé que j'avais fait une erreur dans le logiciel, qu'il ne m'est pas venu un seul instant à l'esprit, que le problème pouvait être d'ordre matériel. Oui, j'avais lu le datasheet du PIC 16F84. Mais une information essentielle m'avait échappée :
"Pin RA4 is multiplexed with the Timer0 module clock input to become the RA4/T0CKI pin. The RA4/T0CKI pin is a Schmitt Trigger input and an open drain output. All other RA port pins have TTL input levels and full CMOS output drivers."
La sortie RA4, contrairement aux autres "sorties" du port RA, est de type Drain ouvert et l'on doit donc impérativement y racorder une résistance de rappel vers la borne positive de l'alimentation. Il est fort probable que j'aurais rapidement localisé l'erreur en allant consulter des schémas existants sur le net. Mais je cherchais désespérement des exemples logiciels et non des exemples matériels ! Oh, je sais, j'en verrai d'autres du même genre...

Code source

L'archive zip suivante contient l'ensemble des fichiers sources et compilés du programme du PIC (versions 001a, 001b, 001c pour 16F84A et 001d/001e pour 16F628A), ainsi que le fichier source de Isis (Proteus). Bien entendu, les codes sources ne vous seront utiles que si vous disposez des logiciels aptes à les ouvrir (Proteus pour la partie électronique et MikroPascal pour la partie logiciel). Si vous ne disposez pas de ces logiciels, vous pouvez toujours utiliser les fichiers compilés (format hex) pour programmer votre PIC.
Diviseur fréquence 001 - (14/02/2016)
Si vous souhaitez recevoir par la poste un PIC préprogrammé et prêt à utiliser, merci de consulter la page PIC - Sources.

Circuit imprimé

Non réalisé. La vue 3D n'est là que pour donner un aperçu des composants utilisés.

Historique

14/02/2016
- Ajout version 001e qui permet de passer d'une fréquence d'entrée max de 40 kHz à une fréquence d'entrée max de 150 kHz.
12/12/2010
- Remplacement PIC 16F84A par un PIC 16F628A.
- Portage code logiciel sous MikroPascal Pro V3.80.
- L'entrée se fait désormais sur la broche RB0 du PIC, les entrées de sélection du taux de division on été décallées en conséquence.
- Le changement du taux de division se fait désormais via la broche de reset général. Cela permet de simplifier le code et de le faire tourner un peu plus vite (25% plus rapide).
xx/01x/2010
- Première mise à disposition