- Per què el temporitzador quan tenim Delay ()?
- Temporitzadors de microcontroladors PIC:
- Programació i explicació de treball:
- Diagrama de circuits i simulació de Proteus:
Aquest serà el cinquè tutorial de la nostra sèrie de tutorials PIC, que us ajudarà a aprendre i utilitzar temporitzadors a PIC16F877A. En els nostres tutorials anteriors, havíem començat amb Introducció a PIC i MPLABX IDE, després vam escriure el nostre primer programa PIC per parpellejar el LED mitjançant PIC i després vam fer una seqüència de parpelleig de LED mitjançant la funció de retard al microcontrolador PIC. Ara fem servir la mateixa seqüència de parpelleig de LED que hem utilitzat en el maquinari anterior del tutorial i, amb això, aprendrem a utilitzar els temporitzadors a la nostra PIC MCU. Acabem d'afegir un botó més al tauler LED per a aquest tutorial. Consulteu el tutorial per obtenir més informació.
Els temporitzadors són un dels cavalls de treball importants per a un programador incrustat. Totes les aplicacions que dissenyem implicaran d'alguna manera una aplicació de temps, com ara activar o desactivar alguna cosa després d'un interval de temps especificat. D’acord, però per què necessitem temporitzadors quan ja tenim macros de retard (__delay_ms ()) fent el mateix?
Per què el temporitzador quan tenim Delay ()?
Una macro de retard es denomina retard de "buidatge". Perquè durant l'execució de la funció de retard, l'MCU es troba a l'abocament creant només un retard. Durant aquest procés, la MCU no pot escoltar els seus valors ADC ni llegir res dels seus registres. Per tant, no és recomanable utilitzar funcions de retard excepte per a aplicacions com el LED parpellejant, on el retard de temps no ha de ser precís ni llarg.
Les macros de retard també tenen les següents novetats:
- El valor de delay ha de ser una constant per a les macros de delay; no es pot canviar durant l'execució del programa. Per tant, queda definit pel programador.
- El retard no serà precís en comparació amb l’ús de temporitzadors.
- No es poden crear valors més grans de retards mitjançant macros, per exemple, no es pot crear un retard de mitja hora mitjançant macros de retard. El retard màxim que es pot utilitzar es basa en l'oscil·lador Crystal utilitzat.
Temporitzadors de microcontroladors PIC:
Físicament, el temporitzador és un registre el valor del qual augmenta contínuament fins a 255, i després torna a començar: 0, 1, 2, 3, 4… 255… 0, 1, 2, 3……etc.
La MCU PIC PIC16F877A té tres mòduls temporitzadors. Són noms com Timer0, Timer1 i Timer2. El temporitzador 0 i el temporitzador 2 són temporitzadors de 8 bits i el temporitzador 1 és un temporitzador de 16 bits. En aquest tutorial utilitzarem el temporitzador 0 per a la nostra aplicació. Un cop entenguem el temporitzador 0, serà fàcil treballar també al temporitzador 1 i al temporitzador 2.
El temporitzador / comptador del mòdul Timer0 té les funcions següents:
- Temporitzador / comptador de 8 bits
- Es pot llegir i escriure
- Prescalador programable de programari de 8 bits
- Selecció de rellotge intern o extern
- Interrupció en desbordament de FFh a 00h
- Selecció de vora per al rellotge extern
Per començar a utilitzar un temporitzador hauríem d’entendre alguns dels termes més elegants, com ara temporitzador de 8 bits / 16 bits, Prescaler, Timer interruptors i Focs. Ara, anem a veure què significa realment cadascun. Com s'ha dit anteriorment, hi ha temporitzadors de 8 i 16 bits a la nostra MCU PIC, la principal diferència entre ells és que el temporitzador de 16 bits té una resolució molt millor que el temporitzador de 8 bits.
Prescaler és un nom per a la part d’un microcontrolador que divideix el rellotge de l’oscil·lador abans que arribi a una lògica que augmenta l’estat del temporitzador. L’interval de l’identificador de prescaler és d’1 a 256 i el valor de la prescaladora es pot establir mitjançant el registre OPTION (el mateix que hem utilitzat per a les resistències pull up). Per exemple, si el valor del prescaler és 64, llavors per cada 64è pols el temporitzador s'incrementarà en 1.
A mesura que el temporitzador augmenta i quan arriba al valor màxim de 255, activarà una interrupció i es tornarà a inicialitzar a 0. Aquesta interrupció s’anomena interrupció del temporitzador. Aquesta interrupció informa a la MCU que aquest temps concret ha caigut.
El Fosc significa Freqüència de l’oscil·lador, és la freqüència del cristall utilitzat. El temps necessari per al registre del temporitzador depèn del valor de Prescaler i del valor del Fosc.
Programació i explicació de treball:
En aquest tutorial establirem dos botons com a dues entrades i 8 LED com a 8 sortides. El primer botó s’utilitzarà per establir el retard de temps (500 ms per cada pulsació) i el segon botó s’utilitzarà per començar a parpellejar la seqüència del temporitzador. Per exemple, si es prem el primer botó tres vegades (500 * 3 = 1500 ms), el retard s'establirà durant 1,5 segons i, quan es prem el botó dos, cada LED s'encén i s'apaga amb el retard predefinit. Consulteu el vídeo de demostració al final d’aquest tutorial.

Ara, tenint en compte aquests conceptes bàsics, vegem el nostre programa que es dóna al final a la secció Codi.
Està bé si no va obtenir el programa, però si ho va fer !! Doneu-vos una galeta i desfeu el programa per gaudir de la vostra producció. Per a altres, dividiré el programa en parts significatives i us explicaré què passa a cada bloc.
Com sempre, les primeres línies del codi són els paràmetres de configuració i els fitxers de capçalera, no ho explicaré ja que ja ho he fet en els meus tutorials anteriors.
A continuació, saltem-nos totes les línies i saltem directament a la funció principal buida, dins de la qual tenim la configuració PORT per al temporitzador0.
void main () {/ ***** Configuració del port per al temporitzador ****** / OPTION_REG = 0b00000101; // Temporitzador0 amb freq extern i 64 com a prescalar // També habilita PULL UP TMR0 = 100; // Carregueu el valor de temps per a 0,0019968 s; delayValue només pot estar entre 0-256 TMR0IE = 1; // Activa el bit d’interrupció del temporitzador al registre PIE1 GIE = 1; // Activa la interrupció global PEIE = 1; // Activa la interrupció perifèrica / *********** ______ *********** /
Per entendre-ho, hem de mirar el registre OPTION al nostre full de dades PIC.

Com es va comentar en el tutorial anterior, el bit 7 s'utilitza per habilitar la resistència de pull up feble per al PORTB. Mireu la figura anterior, el bit 3 es fa 0 per indicar a la MCU que el precalificador següent que s'està configurant s'ha d'utilitzar per al temporitzador i no per al WatchDogTimer (WDT). Es selecciona el mode temporitzador esborrant el bit 5 T0CS
(OPTION_REG <5>)
Ara, els bits2-0 s’utilitzen per establir el valor del precalificador del temporitzador. Com es mostra a la taula anterior per establir un valor de prescaler de 64, els bits s’han d’establir com a 101.
A continuació, examinem els registres associats a Timer0

El temporitzador començarà a incrementar-se un cop configurat i desbordat després d’arribar a un valor de 256, per habilitar la interrupció del temporitzador durant aquest punt, s’ha de configurar el registre TMR0IE com a alt. Com que el Temporitzador 0 en si és un perifèric, hem d’habilitar la Interrupció Perifèrica fent PEIE = 1. Finalment, hem d’habilitar la interrupció global perquè es notifiqui a la MCU sobre la interrupció durant qualsevol operació; això es fa fent GIE = 1.
Retard = ((256-REG_val) * (Prescal * 4)) / Fosc
La fórmula anterior s’utilitza per calcular el valor de Retard.
On
REG_val = 100;
Prescal = 64
Fosc = 20000000
Això en el càlcul dóna, Retard = 0,0019968 s
El següent conjunt de línies és configurar els ports d'E / S.
/ ***** Configuració del port per a E / S ****** / TRISB0 = 1; // Indiqueu a la MCU que el pin 0 PORTB s'utilitzi com a entrada per al botó 1. TRISB1 = 1; // Indiqueu a la MCU que el pin 1 PORTB s'utilitzi com a entrada per al botó 1. TRISD = 0x00; // Indiqueu a la MCU que tots els pins de PORT D es generin PORTD = 0x00; // Inicialitzeu tots els pins a 0 / *********** ______ *********** /
Això és igual al del nostre tutorial anterior, ja que estem utilitzant el mateix maquinari. Llevat que hem afegit un altre botó com a entrada. Això es fa mitjançant la línia TRISB1 = 1.
A continuació, dins de bucle infinit mentre tenim dos blocs de codi. Un s'utilitza per obtenir l'entrada del temporitzador de l'usuari i l'altre per executar la seqüència de retard dels LED. Els he explicat fent servir comentaris contra cada línia.
while (1) {count = 0; // No executeu el temporitzador al bucle principal // ******* Obteniu el retard numèric de l'usuari **** ////// si (RB0 == 0 && flag == 0) // Quan entrada donada {get_scnds + = 1; // get_scnds = get_scnds + http: // Incrementa la variable variable = 1; } if (RB0 == 1) // Per evitar el senyal d'increment continu = 0; / *********** ______ *********** /
Una variable anomenada get_scnds s'incrementa cada vegada que l'usuari prem el botó 1. S'utilitza una variable de marca (definida pel programari) per mantenir el procés d'increment fins que l'usuari treu el dit del botó.
// ******* Executeu la seqüència amb retard **** ////// mentre (RB1 == 0) {PORTD = 0b00000001 <
El següent bloc entra en acció si es prem el botó dos. Atès que l'usuari ja ha definit el retard de temps necessari mitjançant el botó primer i s'ha desat a la variable get_scnds. Utilitzem una variable anomenada hscnd, aquesta variable està controlada per la ISR (Interrupt service routine).
La rutina del servei d'interrupcions és una interrupció que es cridarà cada vegada que es desborda el temporitzador0. Vegem com està controlat per l'ISR al següent bloc, com si volguéssim incrementar el retard de mig segon (0,5 s) en cada botó que premem, llavors haurem d'incrementar la variable hscnd per cada mig segon. Com hem programat el nostre temporitzador per excés de flux per cada 0,0019968 s (~ 2 ms), de manera que comptar la variable de recompte de mig segon hauria de ser 250 perquè 250 * 2 ms = 0,5 segon. Per tant, quan el recompte arriba a 250 (250 * 2 ms = 0,5 segon), vol dir que ha passat mig segon, de manera que incrementem hscnd per 1 i inicialitzem el recompte a zero.
void interrupt timer_isr () {if (TMR0IF == 1) // El marcador del temporitzador s'ha activat a causa del desbordament del temporitzador {TMR0 = 100; // Carregueu el temporitzador Valor TMR0IF = 0; // Esborra el compte de banderes d’interrupció del temporitzador ++; } if (compte == 250) {hscnd + = 1; // hscnd s'incrementarà per cada recompte de mig segon = 0; }}
Per tant, fem servir aquest valor i el comparem amb el nostre hscnd i canviem el LED segons el temps definit per l’usuari. També és molt similar a l’últim tutorial.
Això és tot, tenim el nostre programa entès i funcionant.
Diagrama de circuits i simulació de Proteus:

Com de costum permet verificar primer la sortida mitjançant Proteus, he enllaçat aquí els fitxers esquemàtics del Proteus.
Afegiu un botó a la nostra placa LED anterior i el nostre maquinari ja està a punt. Hauria de ser semblant a això:



Un cop feta la connexió, pengeu el codi i verifiqueu la sortida. Si teniu algun problema, utilitzeu la secció de comentaris. Consulteu també el vídeo següent per entendre tot el procés.
