- Hvorfor timer når vi har forsinkelse ()?
- PIC-mikrocontroller-timere:
- Programmering og arbejdsforklaring:
- Circuit Diagram og Proteus Simulation:
Dette vil være den femte tutorial i vores PIC Tutorial Series, som hjælper dig med at lære og bruge timere i PIC16F877A. I vores tidligere tutorials var vi startet med Introduktion til PIC og MPLABX IDE, så skrev vi vores første PIC-program for at blinke LED'en ved hjælp af PIC og lavede derefter en LED-blinkende sekvens ved hjælp af forsinkelsesfunktion i PIC Microcontroller. Lad os nu bruge den samme LED-blinkende sekvens, som vi har brugt i tidligere tutorial-hardware, og med dette vil vi lære at bruge timere i vores PIC MCU. Vi har lige tilføjet endnu en knap i LED-kort til denne vejledning. Gå gennem vejledningen for at lære mere.
Timere er en af de vigtige arbejdsheste for en integreret programmør. Hver applikation, som vi designer, vil på en eller anden måde involvere en timing-applikation, som at tænde eller slukke for noget efter et bestemt tidsinterval. Okay, men hvorfor har vi brug for timere, når vi allerede har forsinkelsesmakroer (__delay_ms ()), der gør det samme !!
Hvorfor timer når vi har forsinkelse ()?
En forsinkelsesmakro kaldes en "dump" -forsinkelse. Fordi MCU sidder dump ved udførelsen af Delay-funktionen ved blot at oprette en forsinkelse. Under denne proces kan MCU ikke lytte til sine ADC-værdier eller læse noget fra sine registre. Derfor tilrådes det ikke at bruge forsinkelsesfunktioner undtagen applikationer som LED blinker, hvor tidsforsinkelsen ikke behøver at være nøjagtig eller lang.
Forsinkelsesmakroerne har også følgende korte tilføjelser,
- Værdien af forsinkelse skal være konstant for forsinkelsesmakroer; det kan ikke ændres under programudførelse. Derfor forbliver det, er programmørdefineret.
- Forsinkelsen er ikke nøjagtig sammenlignet med brugen af timere.
- Større værdier for forsinkelser kan ikke oprettes ved hjælp af makroer, f.eks. Kan en forsinkelse på en halv time ikke oprettes af forsinkelsesmakroer. Den maksimale forsinkelse, der kan bruges, er baseret på den anvendte krystaloscillator.
PIC-mikrocontroller-timere:
Fysisk er timer et register, hvis værdi konstant øges til 255, og derefter starter det forfra: 0, 1, 2, 3, 4… 255…. 0, 1, 2, 3……etc.
Den PIC16F877A PIC MCU har tre Timer moduler. De er navne som Timer0, Timer1 og Timer2. Timer 0 og Timer 2 er 8-bit Timere og Timer 1 er en 16-bit Timer. I denne vejledning bruger vi Timer 0 til vores applikation. Når vi først har forstået Timer 0, vil det også være let at arbejde på Timer 1 og Timer 2.
Timer0-modulets timer / tæller har følgende funktioner:
- 8-bit timer / tæller
- Læsbar og skrivbar
- 8-bit software programmerbar prescaler
- Valg af internt eller eksternt ur
- Afbryd ved overløb fra FFh til 00h
- Kantvalg til eksternt ur
For at begynde at bruge en timer skal vi forstå nogle af de smarte udtryk som 8-bit / 16-bit timer, Prescaler, Timer interrupts og Focs. Lad os nu se, hvad hver enkelt virkelig betyder. Som tidligere nævnt er der både 8-bit og 16-bit-timere i vores PIC MCU, den største forskel mellem dem er, at 16-bit-timeren har meget bedre opløsning end 8-bit-timeren.
Prescaler er et navn på den del af en mikrocontroller, der deler oscillatoruret, før det når logik, der øger timerstatus. Omfanget af prescaler-id er fra 1 til 256, og værdien af Prescaler kan indstilles ved hjælp af OPTION-registeret (det samme som vi brugte til pull up-modstande). For eksempel hvis værdien af prescaler er 64, så for hver 64 th pulsere Timeren vil blive forøget med 1.
Efterhånden som timeren øges, og når den når sin maksimale værdi på 255, udløser den en afbrydelse og initialiserer sig selv til 0 tilbage igen. Denne afbrydelse kaldes som Timer Interrupt. Denne afbrydelse informerer MCU om, at denne særlige tid er gået.
Den Fosc står for oscillatorens, det er frekvensen af Crystal brugt. Den tid, det tager for timerregistret, afhænger af værdien af Prescaler og værdien af Fosc.
Programmering og arbejdsforklaring:
I denne vejledning indstiller vi to knapper som to indgange og 8 lysdioder som 8 udgange. Den første knap bruges til at indstille tidsforsinkelsen (500 ms for hvert tryk), og den anden knap bruges til at starte timersekvensen med at blinke. For eksempel, hvis der trykkes på den første knap tre gange (500 * 3 = 1500 ms), indstilles forsinkelsen til 1,5 sek, og når der trykkes på knappen to, vil hver LED tænde og slukke med den foruddefinerede tidsforsinkelse. Tjek demonstrationsvideoen i slutningen af denne vejledning.
Lad os nu, med disse grundlæggende i tankerne, se på vores program, der er givet i slutningen i Kodeafsnittet.
Det er okay, hvis du ikke fik programmet, men hvis du fik det !! Giv dig selv en cookie og dump programmet for at nyde din produktion. For andre vil jeg opdele programmet i meningsfulde dele og forklare dig, hvad der sker i hver blok.
Som altid er de første par linjer i koden konfigurationsindstillinger og headerfiler, jeg vil ikke forklare dette, da jeg allerede har gjort det i mine tidligere tutorials.
Lad os derefter springe alle linjer over og springe direkte ind i den ugyldige hovedfunktion, inden for hvilken vi har PORT-konfigurationen til Timer0.
ugyldig main () {/ ***** Portkonfiguration til timer ****** / OPTION_REG = 0b00000101; // Timer0 med ekstern freq og 64 som prescalar // Aktiverer også PULL UPs TMR0 = 100; // Indlæs tidsværdien for 0,0019968s; delayValue kan være mellem 0-256 kun TMR0IE = 1; // Aktivér timerinterruptbit i PIE1-registeret GIE = 1; // Aktiver Global Interrupt PEIE = 1; // Aktivér den perifere afbrydelse / *********** ______ *********** /
For at forstå dette skal vi se på OPTION Register i vores PIC-datablad.
Som diskuteret i forrige tutorial bruges bit 7 til at muliggøre svag pull-up-modstand til PORTB. Se på ovenstående figur, bit 3 er lavet 0 for at instruere MCU'en om, at følgende prescaler, der indstilles, skal bruges til timeren og ikke til WatchDogTimer (WDT). Timertilstand vælges ved at rydde bit 5 T0CS
(OPTION_REG <5>)
Nu bruges bits2-0 til at indstille forkalkningsværdien for timeren. Som vist i tabellen ovenfor for at indstille en prescaler-værdi på 64, skal bitene indstilles til 101.
Lad os derefter se på de registre, der er knyttet til Timer0
Timeren begynder at inkrementere, når den er indstillet og overløber, når den har nået en værdi på 256, for at aktivere Timer-afbrydelsen i dette punkt, skal registeret TMR0IE indstilles højt. Da Timer 0 i sig selv er en perifer, er vi nødt til at aktivere Peripheral Interrupt ved at gøre PEIE = 1. Endelig er vi nødt til at aktivere Global Interrupt, så MCU'en får besked om Interrupt under enhver operation, dette gøres ved at gøre GIE = 1.
Forsinkelse = ((256-REG_val) * (Prescal * 4)) / Fosc
Ovenstående formel bruges til at beregne værdien af forsinkelse.
Hvor
REG_val = 100;
Prescal = 64
Fosc = 20000000
Dette ved beregning giver, Forsinkelse = 0,0019968s
Det næste sæt linjer er at indstille I / O-porte.
/ ***** Portkonfiguration til I / O ****** / TRISB0 = 1; // Instruer MCU'en, at PORTB-pin 0 bruges som input til knap 1. TRISB1 = 1; // Instruer MCU'en, at PORTB pin 1 bruges som input til knap 1. TRISD = 0x00; // Instruer MCU'en om, at alle ben på PORT D er output PORTD = 0x00; // Initialiser alle ben til 0 / *********** ______ *********** /
Dette er det samme som i vores tidligere tutorial, da vi bruger den samme hardware. Bortset fra at vi har tilføjet en anden knap som input. Dette gøres ved linjen TRISB1 = 1.
Derefter har vi to uendelige mens vi har to blokke kode. Den ene bruges til at få timerindgangen fra brugeren og den anden til at udføre forsinkelsessekvensen over lysdioderne. Jeg har forklaret dem ved at bruge kommentarer mod hver linje.
mens (1) {count = 0; // Kør ikke timer, mens du er i hovedsløjfe // ******* Få nummerforsinkelse fra bruger **** ////// if (RB0 == 0 && flag == 0) // Hvornår input givet {get_scnds + = 1; // get_scnds = get_scnds + http: // Increment variable flag = 1; } hvis (RB0 == 1) // For at forhindre kontinuerlig inkrementeringsflag = 0; / *********** ______ *********** /
En variabel kaldet get_scnds forøges, hver gang brugeren trykker på knappen 1. Et flag (software defineret) variabel bruges til at holde inkrementeringsprocessen, indtil brugeren fjerner sin finger fra knappen.
// ******* Udfør sekvens med forsinkelse **** ////// mens (RB1 == 0) {PORTD = 0b00000001 <
Den næste blok træder i kraft, hvis der trykkes på knap to. Da brugeren allerede har defineret den krævede tidsforsinkelse ved hjælp af knap en, og den er gemt i variablen get_scnds. Vi bruger en variabel kaldet hscnd, denne variabel styres af ISR (Interrupt service rutine).
Den interrupt service rutine er en Interrupt, der vil blive kaldt hver gang Timer0 er overløb. Lad os se, hvordan den styres af ISR i den næste blok, som om vi vil øge tidsforsinkelsen med et halvt sekund (0,5 sek.) For hvert tryk på en knap, så skal vi forøge variabel hscnd for hvert halve sekund. Som vi har programmeret vores timeren til over flow for hver 0.0019968s (~ 2ms), så at tælle halvt sekund tæller variabel skal være 250, fordi 250 * 2 ms = 0,5 sekund. Så når optælling får 250 (250 * 2ms = 0,5 sekund), betyder det, at det har været et halvt sekund, så vi forøger hscnd med 1 og initialiserer antallet til nul.
ugyldig interrupt timer_isr () {hvis (TMR0IF == 1) // Timer-flag er udløst på grund af timeroverløb {TMR0 = 100; // Indlæs timeren Værdi TMR0IF = 0; // Ryd timer afbryde flagantal ++; } hvis (count == 250) {hscnd + = 1; // hscnd forøges for hvert halve sekundstælling = 0; }}
Så vi bruger denne værdi og sammenligner den med vores hscnd og skifter vores LED baseret på den brugerdefinerede tid. Det ligner også meget sidste tutorial.
Det er det, vi har vores program forstået og fungerer.
Circuit Diagram og Proteus Simulation:
Som sædvanlig kan vi kontrollere output ved hjælp af Proteus først, jeg har linket de skematiske filer til Proteus her.
Tilføj en knap til vores tidligere LED-kort, og vores hardware er klar til brug. Det skal se sådan ud:
Når forbindelsen er gennemført, skal du uploade koden og kontrollere output. Hvis du har problemer, skal du bruge kommentarfeltet. Tjek også videoen nedenfor for at forstå hele processen.