- Pourquoi Timer quand nous avons Delay ()?
- Minuteries de microcontrôleur PIC:
- Programmation et explication de travail:
- Schéma de circuit et simulation Proteus:
Ce sera le cinquième tutoriel de notre série de didacticiels PIC, qui vous aidera à apprendre et à utiliser les minuteries dans PIC16F877A. Dans nos tutoriels précédents, nous avions commencé avec Introduction à PIC et MPLABX IDE, puis nous avons écrit notre premier programme PIC pour faire clignoter la LED à l'aide de PIC, puis avons créé une séquence de clignotement de LED en utilisant la fonction de retard dans le microcontrôleur PIC. Maintenant, utilisons la même séquence de clignotement des LED que nous avons utilisée dans le matériel du didacticiel précédent et avec cela, nous allons apprendre à utiliser les minuteries dans notre MCU PIC. Nous venons d'ajouter un autre bouton dans la carte LED pour ce tutoriel. Parcourez le didacticiel pour en savoir plus.
Les minuteries sont l'un des principaux outils de travail pour un programmeur intégré. Chaque application que nous concevons impliquera en quelque sorte une application de minutage, comme activer ou désactiver quelque chose après un intervalle de temps spécifié. D'accord, mais pourquoi avons-nous besoin de minuteries alors que nous avons déjà des macros de retard (__delay_ms ()) faisant la même chose !!
Pourquoi Timer quand nous avons Delay ()?
Une macro de délai est appelée délai de «vidage». Parce que lors de l'exécution de la fonction Delay, le MCU effectue un vidage en créant simplement un retard. Pendant ce processus, le MCU ne peut pas écouter ses valeurs ADC ou lire quoi que ce soit à partir de ses registres. Par conséquent, il n'est pas conseillé d'utiliser les fonctions de délai, sauf pour des applications telles que le clignotement des LED où le délai n'a pas besoin d'être précis ou long.
Les macros de retard présentent également les inconvénients suivants,
- La valeur de délai doit être une constante pour les macros de délai; il ne peut pas être modifié pendant l'exécution du programme. Il reste donc défini par le programmeur.
- Le délai ne sera pas précis par rapport à l'utilisation de minuteries.
- Des valeurs de délais plus importantes ne peuvent pas être créées à l'aide de macros, par exemple un délai d'une demi-heure ne peut pas être créé par des macros de délai. Le délai maximum qui peut être utilisé est basé sur l'oscillateur à cristal utilisé.
Minuteries de microcontrôleur PIC:
Physiquement, le timer est un registre dont la valeur augmente continuellement jusqu'à 255, puis il recommence: 0, 1, 2, 3, 4… 255…. 0, 1, 2, 3……etc.
Le MCU PIC16F877A PIC dispose de trois modules de minuterie. Ce sont des noms comme Timer0, Timer1 et Timer2. La minuterie 0 et la minuterie 2 sont des minuteries 8 bits et la minuterie 1 est une minuterie 16 bits. Dans ce tutoriel, nous utiliserons le Timer 0 pour notre application. Une fois que nous aurons compris la minuterie 0, il sera facile de travailler également sur la minuterie 1 et la minuterie 2.
La minuterie / compteur du module Timer0 présente les caractéristiques suivantes:
- Minuterie / compteur 8 bits
- Lisible et inscriptible
- Prescaler programmable par logiciel 8 bits
- Sélection de l'horloge interne ou externe
- Interruption en cas de dépassement de FFh à 00h
- Sélection de bord pour l'horloge externe
Pour commencer à utiliser une minuterie, nous devons comprendre certains des termes sophistiqués tels que minuterie 8 bits / 16 bits, Prescaler, interruptions de minuterie et Focs. Maintenant, voyons ce que chacun signifie vraiment. Comme dit précédemment, il existe à la fois les minuteries 8 bits et 16 bits dans notre MCU PIC, la principale différence entre eux est que la minuterie 16 bits a une résolution bien meilleure que la minuterie 8 bits.
Prescaler est un nom pour la partie d'un microcontrôleur qui divise l'horloge de l'oscillateur avant qu'elle n'atteigne la logique qui augmente l'état de la minuterie. La plage de l'identifiant du prescaler est de 1 à 256 et la valeur du Prescaler peut être définie à l'aide du registre OPTION (le même que celui que nous avons utilisé pour les résistances de rappel). Par exemple, si la valeur du préréglage est de 64, alors pour chaque 64 e impulsion, la minuterie sera incrémentée de 1.
Au fur et à mesure que le minuteur s'incrémente et qu'il atteint sa valeur maximale de 255, il déclenchera une interruption et se réinitialisera à 0. Cette interruption est appelée interruption de la minuterie. Cette interruption informe le MCU que ce temps particulier est écoulé.
Le Fosc signifie fréquence de l'oscillateur, c'est la fréquence du cristal utilisé. Le temps nécessaire pour le registre Timer dépend de la valeur de Prescaler et de la valeur du Fosc.
Programmation et explication de travail:
Dans ce tutoriel, nous allons définir deux boutons comme deux entrées et 8 LED comme 8 sorties. Le premier bouton sera utilisé pour régler la temporisation (500 ms pour chaque pression) et le second bouton sera utilisé pour démarrer le clignotement de la séquence de minuterie. Par exemple, si le premier bouton est enfoncé trois fois (500 * 3 = 1500 ms), le délai sera réglé sur 1,5 s et lorsque le bouton deux est enfoncé, chaque LED s'allumera et s'éteindra avec le délai prédéfini. Consultez la vidéo de démonstration à la fin de ce didacticiel.
Maintenant, avec ces bases à l'esprit, regardons notre programme donné à la fin de la section Code.
Ce n'est pas grave si vous n'avez pas obtenu le programme, mais si vous l'avez fait !! Donnez-vous un cookie et videz le programme pour profiter de votre sortie. Pour d'autres, je diviserai le programme en parties significatives et vous expliquerai ce qui se passe dans chaque bloc.
Comme toujours les premières lignes du code sont les paramètres de configuration et les fichiers d'en-tête, je ne vais pas l'expliquer car je l'ai déjà fait dans mes tutoriels précédents.
Ensuite, sautons toutes les lignes et sautons directement dans la fonction principale void, à l'intérieur de laquelle nous avons la configuration PORT pour le Timer0.
void main () {/ ***** Configuration du port pour le minuteur ****** / OPTION_REG = 0b00000101; // Timer0 avec freq externe et 64 comme prescalaire // Active également PULL UPs TMR0 = 100; // Charge la valeur de temps pour 0.0019968s; delayValue peut être compris entre 0 et 256 uniquement TMR0IE = 1; // Activer le bit d'interruption du temporisateur dans le registre PIE1 GIE = 1; // Activer l'interruption globale PEIE = 1; // Activer l'interruption périphérique / *********** ______ *********** /
Pour comprendre cela, nous devons consulter le registre OPTION dans notre fiche technique PIC.
Comme indiqué dans le didacticiel précédent, le bit 7 est utilisé pour activer une résistance de rappel faible pour le PORTB. Regardez la figure ci-dessus, le bit 3 est mis à 0 pour indiquer à la MCU que le prescaler suivant qui est défini doit être utilisé pour la minuterie et non pour le WatchDogTimer (WDT). Le mode minuterie est sélectionné en effaçant le bit 5 T0CS
(OPTION_REG <5>)
Désormais, les bits2-0 sont utilisés pour définir la valeur du préréglage pour la minuterie. Comme indiqué dans le tableau ci-dessus pour définir une valeur de prédécaleur de 64, les bits doivent être définis sur 101.
Ensuite, examinons les registres associés à Timer0
La minuterie commencera à s'incrémenter une fois réglée et débordera après avoir atteint une valeur de 256, pour activer l'interruption de la minuterie pendant ce point, le registre TMR0IE doit être mis à l'état haut. Puisque le temporisateur 0 lui-même est un périphérique, nous devons activer l'interruption périphérique en faisant PEIE = 1. Enfin, nous devons activer l'interruption globale pour que le MCU soit informé de l'interruption pendant toute opération, cela se fait en faisant GIE = 1.
Délai = ((256-REG_val) * (Prescal * 4)) / Fosc
La formule ci-dessus est utilisée pour calculer la valeur du délai.
Où
REG_val = 100;
Prescal = 64
Fosc = 20000000
Ceci sur le calcul donne, Retard = 0,0019968 s
Le prochain ensemble de lignes consiste à définir les ports d'E / S.
/ ***** Configuration du port pour les E / S ****** / TRISB0 = 1; // Informe le MCU que la broche 0 du PORTB est utilisée comme entrée pour le bouton 1. TRISB1 = 1; // Informe le MCU que la broche PORTB 1 est utilisée comme entrée pour le bouton 1. TRISD = 0x00; // Indique au MCU que toutes les broches du PORT D sont sorties PORTD = 0x00; // Initialise toutes les broches à 0 / *********** ______ *********** /
C'est le même que celui de notre tutoriel précédent puisque nous utilisons le même matériel. Sauf que nous avons ajouté un autre bouton en entrée. Cela se fait par la ligne TRISB1 = 1.
Ensuite, à l'intérieur de la boucle while infinie, nous avons deux blocs de code. L'un est utilisé pour obtenir l'entrée de la minuterie de l'utilisateur et l'autre pour exécuter la séquence de retard sur les LED. Je les ai expliqués en utilisant des commentaires sur chaque ligne.
while (1) {count = 0; // Ne pas exécuter le minuteur pendant la boucle principale // ******* Obtenir le délai de nombre de l'utilisateur **** ////// if (RB0 == 0 && flag == 0) // Quand entrée donnée {get_scnds + = 1; // get_scnds = get_scnds + http: // Variable d'incrémentation flag = 1; } if (RB0 == 1) // Pour empêcher une incrémentation continue flag = 0; / *********** ______ *********** /
Une variable appelée get_scnds est incrémentée chaque fois que l'utilisateur appuie sur le bouton 1. Une variable d' indicateur (définie par logiciel) est utilisée pour maintenir le processus d'incrémentation jusqu'à ce que l'utilisateur retire son doigt du bouton.
// ******* Exécuter la séquence avec délai **** ////// while (RB1 == 0) {PORTD = 0b00000001 <
Le bloc suivant entre en action si le bouton deux est enfoncé. Puisque l'utilisateur a déjà défini la temporisation requise à l'aide du bouton 1 et qu'elle a été enregistrée dans la variable get_scnds. Nous utilisons une variable appelée hscnd, cette variable est contrôlée par l'ISR (Interrupt service routine).
La routine de service d'interruption est une interruption qui sera appelée chaque fois que le Timer0 débordera. Voyons comment il est contrôlé par l'ISR dans le bloc suivant, comme nous voulons incrémenter le délai d'une demi-seconde (0,5 s) à chaque pression de bouton, puis nous devons incrémenter la variable hscnd pour chaque demi-seconde. Comme nous avons programmé notre minuterie pour déborder toutes les 0,0019968s (~ 2 ms), pour compter une demi-seconde, la variable de comptage doit être de 250 car 250 * 2 ms = 0,5 seconde. Ainsi, lorsque count obtient 250 (250 * 2ms = 0,5 seconde), cela signifie que cela fait une demi-seconde, donc nous incrémentons hscnd de 1 et initialisons le compte à zéro.
void interruption timer_isr () {if (TMR0IF == 1) // L'indicateur de minuterie a été déclenché en raison d'un dépassement de la minuterie {TMR0 = 100; // Charge la minuterie Valeur TMR0IF = 0; // Effacer le nombre d'indicateurs d'interruption du minuteur ++; } si (nombre == 250) {hscnd + = 1; // hscnd sera incrémenté pour chaque demi-seconde count = 0; }}
Nous utilisons donc cette valeur et la comparons à notre hscnd et décalons notre LED en fonction du temps défini par l'utilisateur. Il est également très similaire au dernier tutoriel.
Voilà, notre programme est compris et fonctionne.
Schéma de circuit et simulation Proteus:
Comme d'habitude, vérifions d'abord la sortie en utilisant Proteus, j'ai lié ici les fichiers schématiques du Proteus.
Ajoutez un bouton à notre précédente carte LED et notre matériel est prêt à fonctionner. Ça devrait ressembler a quelque chose comme ca:
Une fois la connexion établie, téléchargez le code et vérifiez la sortie. Si vous rencontrez un problème, veuillez utiliser la section commentaires. Consultez également la vidéo ci-dessous pour comprendre l'ensemble du processus.