- Zašto timer kad imamo Delay ()?
- Tajmeri PIC mikrokontrolera:
- Programiranje i radno objašnjenje:
- Kružni dijagram i simulacija Proteja:
Ovo će biti peti tutorial u našoj PIC Tutorial Series, koji će vam pomoći naučiti i koristiti odbrojavanje u PIC16F877A. U našim prethodnim tutorijalima započeli smo s Uvodom u PIC i MPLABX IDE, zatim smo napisali svoj prvi PIC program za treptanje LED-a pomoću PIC-a, a zatim napravili LED treptajuću sekvencu pomoću funkcije odgode u PIC mikrokontroleru. Sada upotrijebimo isti redoslijed treptanja LED-a koji smo koristili u prethodnom hardveru tutorijala, a s tim ćemo naučiti kako koristiti tajmere u našem PIC MCU-u. Upravo smo dodali još jedan gumb na LED ploču za ovaj vodič. Prođite kroz vodič da biste saznali više.
Tajmeri su jedan od važnih radnih konja za ugrađeni programer. Svaka aplikacija koju dizajniramo nekako će uključivati vremensku aplikaciju, poput UKLJUČIVANJA ili ISKLJUČANJA nečega nakon određenog vremenskog intervala. U redu, ali zašto nam trebaju odbrojavači kad već imamo makronaredbe odgode (__delay_ms ()) koje rade istu stvar !!
Zašto timer kad imamo Delay ()?
Makro za odgodu naziva se kašnjenjem "dump". Budući da tijekom izvršavanja funkcije odgode MCU sjeda na zemlju samo stvarajući kašnjenje. Tijekom ovog postupka MCU ne može slušati svoje ADC vrijednosti niti čitati bilo što iz svojih Registra. Stoga nije preporučljivo koristiti funkcije odgode, osim za programe poput treptanja LED-a gdje vremensko odgađanje ne mora biti točno ili dugo.
Makronaredbe odgode također imaju sljedeće kratke dolaske,
- Vrijednost kašnjenja mora biti konstanta za makronaredbe kašnjenja; ne može se mijenjati tijekom izvršavanja programa. Stoga ostaje definirano programerom.
- Odgoda neće biti točna u usporedbi s korištenjem odbrojavanja.
- Veće vrijednosti kašnjenja ne mogu se stvoriti pomoću makronaredbi, na primjer kašnjenje od pola sata ne može se stvoriti makronaredbama odgode. Maksimalno kašnjenje koje se može koristiti temelji se na korištenom kristalnom oscilatoru.
Tajmeri PIC mikrokontrolera:
Fizički, tajmer je registar čija se vrijednost neprestano povećava na 255, a zatim započinje ispočetka: 0, 1, 2, 3, 4… 255…. 0, 1, 2, 3…… itd.
PIC16F877A PIC MCU ima tri timera modula. To su imena kao Timer0, Timer1 i Timer2. Timer 0 i Timer 2 su 8-bitni timeri, a Timer 1 je 16-bitni timer. U ovom uputstvu koristit ćemo timer 0 za našu aplikaciju. Jednom kad shvatimo Timer 0, lako će se raditi i na Timeru 1 i Timeru 2.
Tajmer / brojač modula Timer0 ima sljedeće značajke:
- 8-bitni timer / brojač
- Čitljivo i zapisljivo
- 8-bitni softverski programibilni prescaler
- Odaberite unutarnji ili vanjski sat
- Prekid pri prelijevanju s FFh na 00h
- Odabir ruba za vanjski sat
Da bismo počeli koristiti timer, trebali bismo razumjeti neke otmjene pojmove poput 8-bitnog / 16-bitnog timera, Prescaler-a, Timer-prekida i Focs-a. Sada, da vidimo što svaki od njih zapravo znači. Kao što je ranije rečeno, u našem PIC MCU-u postoje i 8-bitni i 16-bitni timeri, glavna razlika između njih je ta što 16-bitni timer ima puno bolju rezoluciju od 8-bitnog timer-a.
Prescaler je naziv za dio mikrokontrolera koji dijeli oscilator sat prije nego što dosegne logiku koja povećava status tajmera. Raspon id-a prednamjenjivača je od 1 do 256, a vrijednost uređaja za predskaliranje može se postaviti pomoću registra OPTION (Isti onaj koji smo koristili za natezne otpore). Na primjer, ako je vrijednost prescaler je 64, onda za svaki 64 -og puls timer će se povećati za 1.
Kako se tajmer povećava i kada dosegne maksimalnu vrijednost 255, aktivirat će prekid i ponovno se inicijalizirati na 0. Taj se prekid naziva Timer Interrupt (Prekid timer). Ovaj prekid obavještava MCU da je to određeno vrijeme isteklo.
FOSC označava frekvenciju oscilatora, to je frekvencija kristala koji se koriste. Vrijeme potrebno za registar Timer ovisi o vrijednosti Prescalera i vrijednosti Fosca.
Programiranje i radno objašnjenje:
U ovom uputstvu postavit ćemo dvije tipke kao dva ulaza i 8 LED kao 8 izlaza. Prvi će se gumb koristiti za postavljanje vremenskog kašnjenja (500 ms za svaki pritisak), a drugi će se gumb koristiti za pokretanje treperenja sekvence timera. Na primjer, ako se prva tipka pritisne tri puta (500 * 3 = 1500 ms), kašnjenje će se postaviti na 1,5 sek. Kad se pritisne tipka dva, svaka LED lampica će se UKLJUČITI i ISKLJUČITI s unaprijed definiranim vremenskim odgodom. Pogledajte demonstracijski video na kraju ovog vodiča.

Sada, s tim osnovama na umu, pogledajmo naš program dan na kraju u odjeljku Code.
U redu je ako niste dobili program, ali ako jeste !! Dajte si kolačić i bacite program da biste uživali u svojim rezultatima. Za ostale ću podijeliti program na značajne dijelove i objasniti vam što se događa u svakom bloku.
Kao i uvijek prvih nekoliko redaka koda su postavke konfiguracije i datoteke zaglavlja, neću to objašnjavati jer sam to već učinio u svojim prethodnim tutorijalima.
Dalje, preskočimo sve redove i uskočimo ravno u glavnu funkciju void, unutar koje imamo PORT konfiguraciju za Timer0.
void main () {/ ***** Konfiguracija porta za odbrojavanje ****** / OPTION_REG = 0b00000101; // Timer0 s vanjskom frekvencijom i 64 kao predskalarom // Omogućuje i PULL UPs TMR0 = 100; // Učitavanje vremenske vrijednosti za 0,0019968s; delayValue može biti između 0-256 samo TMR0IE = 1; // Omogući bit prekida timera u PIE1 registru GIE = 1; // Omogući globalni prekid PEIE = 1; // Omogući periferni prekid / *********** ______ *********** /
Da bismo to razumjeli, moramo pogledati OPTION registar u našoj tablici podataka PIC-a.

Kao što je raspravljeno u prethodnom vodiču, bit 7 se koristi za omogućavanje slabog otpora za PORTB. Pogledajte gornju sliku, bit 3 je napravljen 0 da uputi MCU da se sljedeći uređaj za predskaliranje koji se postavlja treba koristiti za Timer, a ne za WatchDogTimer (WDT). Način odbrojavanja odabire se brisanjem bita 5 T0CS
(OPTION_REG <5>)
Sada se bits2-0 koristi za postavljanje vrijednosti pretcjenjivača za tajmer. Kao što je prikazano u gornjoj tablici da bi se postavila vrijednost pretcjelice 64, bitovi moraju biti postavljeni kao 101.
Dalje, pogledajmo registre povezane s Timer0

Tajmer će se početi povećavati jednom postavljenim i prelijevanjem nakon dostizanja vrijednosti 256, kako bi se omogućio prekid Timer-a tijekom ove točke, registar TMR0IE mora biti postavljen visoko. Budući da je timer 0 sam po sebi periferni uređaj, moramo omogućiti periferni prekid tako da napravimo PEIE = 1. Konačno, moramo omogućiti globalni prekid kako bi MCU bio obaviješten o prekidu tijekom bilo koje radnje, to se postiže tako da GIE = 1.
Odgoda = ((256-REG_val) * (Prescal * 4)) / Fosc
Gornja formula koristi se za izračunavanje vrijednosti odgode.
Gdje
REG_val = 100;
Prescal = 64
Fosc = 20000000
Ovo na izračunu daje, Kašnjenje = 0,0019968s
Sljedeći niz linija je postavljanje I / O portova.
/ ***** Konfiguracija porta za I / O ****** / TRISB0 = 1; // uputite MCU da se PORTB pin 0 koristi kao ulaz za gumb 1. TRISB1 = 1; // uputite MCU da se PORTB pin 1 koristi kao ulaz za gumb 1. TRISD = 0x00; // uputite MCU da svi pinovi na PORTU D imaju izlaz PORTD = 0x00; // Inicijalizirajte sve pribadače u 0 / *********** ______ *********** /
To je isto kao i u našem prethodnom vodiču jer koristimo isti hardver. Osim što smo dodali još jedan gumb kao ulaz. To se radi linijom TRISB1 = 1.
Dalje, beskonačna while petlja iznutra prema van imamo dva bloka koda. Jedan se koristi za dobivanje unosa tajmera od korisnika, a drugi za izvršavanje niza kašnjenja preko LED-a. Objasnio sam ih koristeći komentare uz svaki redak.
while (1) {count = 0; // Ne pokreći tajmer dok ste u glavnoj petlji // ******* Dobijte odgodu broja od korisnika **** ////// if (RB0 == 0 && flag == 0) // Kada unos dan {get_scnds + = 1; // get_scnds = get_scnds + http: // Povećaj zastavicu varijable = 1; } if (RB0 == 1) // Za sprečavanje neprekidnog povećavanja zastavica = 0; / *********** ______ *********** /
Varijabla koja se naziva get_scnds povećava se svaki put kada korisnik pritisne gumb 1. Varijabla zastavice (definirana softverom) koristi se za zadržavanje postupka povećavanja sve dok korisnik ne ukloni prst s gumba.
// ******* Izvršiti niz sa zakašnjenjem **** ////// while (RB1 == 0) {PORTD = 0b00000001 <
Sljedeći blok započinje akcijom ako se pritisne gumb dva. Budući da je korisnik već definirao potrebno vremensko kašnjenje pomoću gumba jedan i ono je spremljeno u varijablu get_scnds. Koristimo varijablu koja se naziva hscnd, a ovu varijablu kontrolira ISR (Interrupt service rutina).
Prekid usluge rutinu je prekid koji će se zvati svaki put Timer0 je prelijeva. Pogledajmo kako se njime kontrolira ISR u sljedećem bloku, kao što želimo povećati vremensko kašnjenje za pola sekunde (0,5 s) pri svakom pritisku gumba, a zatim trebamo povećavati varijablu hscnd za svake pola sekunde. Kao što smo programirali tajmer za prekomjerni protok za svakih 0,0019968s (~ 2ms), tako bi za brojanje pola sekunde varijabla brojanja trebala biti 250, jer 250 * 2ms = 0,5 sekunde. Dakle, kada brojanje dobije 250 (250 * 2ms = 0,5 sekunde), znači da je prošlo pola sekunde pa hscnd povećavamo za 1 i inicijaliziramo brojanje na nulu.
void interrupt timer_isr () {if (TMR0IF == 1) // Oznaka timera aktivirana je zbog prelijevanja timera {TMR0 = 100; // Učitaj timer Vrijednost TMR0IF = 0; // Očisti broj zastavica prekida timera ++; } if (count == 250) {hscnd + = 1; // hscnd će se povećavati za svakih pola sekunde count = 0; }}
Stoga koristimo ovu vrijednost i uspoređujemo je s našim hscnd-om i pomičemo LED diodu na temelju korisnički definiranog vremena. Također je vrlo sličan prošlom tutorialu.
To je to što naš program razumijemo i radimo.
Kružni dijagram i simulacija Proteja:

Kao i obično dopuštamo prvo provjeriti izlaz koristeći Proteus, ovdje sam povezao shematske datoteke Proteusa.
Dodajte gumb na našu prethodnu LED ploču i naš je hardver spreman za rad. To bi trebalo izgledati otprilike ovako:



Nakon završetka veze, prenesite kôd i provjerite izlaz. Ako imate bilo kakvih problema, upotrijebite odjeljak za komentare. Također pogledajte video u nastavku da biste razumjeli cijeli postupak.
