- Bakit Timer kung mayroon tayong Pagkaantala ()?
- Mga timer ng PIC microcontroller:
- Programming at Paggawa ng Paliwanag:
- Circuit Diagram at Proteus Simulation:
Ito ang magiging pang-limang tutorial sa aming PIC Tutorial Series, na makakatulong sa iyo upang malaman at gamitin ang Mga Timer sa PIC16F877A. Sa aming nakaraang mga tutorial, nagsimula kami sa Panimula sa PIC at MPLABX IDE, pagkatapos ay isinulat namin ang aming unang programa ng PIC upang pumikit ang LED gamit ang PIC at pagkatapos ay gumawa ng isang LED Blinking Sequence sa pamamagitan ng paggamit ng pagka-antala sa PIC Microcontroller. Ngayon ay gamitin natin ang parehong pagkakasunud-sunod ng LED Blinking na ginamit namin sa nakaraang tutorial hardware at dito matututunan namin Paano gamitin ang Mga Timer sa aming PIC MCU. Nagdagdag lamang kami ng isa pang pindutan sa LED board para sa tutorial na ito. Dumaan sa tutorial upang matuto nang higit pa.
Ang timer ay isa sa mahahalagang workhorses para sa isang naka-embed na programmer. Ang bawat application na ididisenyo namin ay magsasangkot kahit papaano sa isang application ng tiyempo, tulad ng pag-ON o pag-OFF ng isang bagay pagkatapos ng isang tinukoy na agwat ng oras. Okay, ngunit bakit kailangan natin ng mga timer kung mayroon na tayong mga macros (__delay_ms ()) na ginagawa ang parehong bagay !!
Bakit Timer kung mayroon tayong Pagkaantala ()?
Ang isang Pag-antala ng macro ay tinatawag na isang pagkaantala ng “dump”. Dahil sa panahon ng pagpapatupad ng pagka-antala ng MCU ay nakaupo ang dump sa pamamagitan lamang ng paglikha ng isang pagkaantala. Sa panahon ng prosesong ito, hindi makikinig ang MCU sa mga halagang ADC o mabasa ang anuman mula sa Mga Rehistro nito. Samakatuwid hindi maipapayo na gamitin ang Mga pagpapaandar na pagkaantala maliban sa mga application tulad ng LED na kumikislap kung saan ang pagkaantala ng Oras ay hindi kailangang maging tumpak o mahaba.
Ang mga pagkaantala ng macros ay mayroon ding mga sumusunod na maikling pagdating,
- Ang halaga ng pagkaantala ay dapat na isang pare-pareho para sa mga pagkaantala ng macros; hindi ito mababago habang isinasagawa ang programa. Samakatuwid ito ay nananatili ay tinukoy ng programmer.
- Ang pagkaantala ay hindi magiging tumpak kumpara sa paggamit ng Mga Timer.
- Ang mga mas malalaking halaga ng pagkaantala ay hindi malilikha gamit ang macros, halimbawa ang pagkaantala ng kalahating oras ay hindi malilikha ng mga macros ng pagkaantala. Ang maximum na pagkaantala na maaaring magamit ay batay sa ginamit na Crystal oscillator.
Mga timer ng PIC microcontroller:
Sa pisikal, ang timer ay isang rehistro na ang halaga ay patuloy na tumataas sa 255, at pagkatapos ay nagsisimula itong muli: 0, 1, 2, 3, 4… 255…. 0, 1, 2, 3……bp.
Ang PIC16F877A PIC MCU ay may tatlong Timer Modules. Ang mga ito ay mga pangalan bilang Timer0, Timer1 at Timer2. Ang Timer 0 at Timer 2 ay 8-bit Timer at ang Timer 1 ay isang 16-bit Timer. Sa tutorial na ito gagamitin namin ang Timer 0 para sa aming aplikasyon. Kapag naintindihan namin ang Timer 0 madali itong magtrabaho sa Timer 1 at Timer 2 din.
Ang timer / counter ng module ng Timer0 ay may mga sumusunod na tampok:
- 8-bit timer / counter
- Nababasa at nasusulat
- 8-bit na programmable prescaler na napaprograma
- Panloob o panlabas na orasan pumili
- Makagambala sa pag-apaw mula sa FFh hanggang 00h
- Piliin ang gilid para sa panlabas na orasan
Upang simulang gumamit ng isang timer dapat nating maunawaan ang ilan sa mga magarbong termino tulad ng 8-bit / 16-bit timer, Prescaler, Timer interrupts at Foc. Ngayon, tingnan natin kung ano talaga ang ibig sabihin ng bawat isa. Tulad ng sinabi nang mas maaga mayroong parehong 8-bit at 16-bit Timer sa aming PIC MCU, ang pangunahing pagkakaiba sa pagitan nila ay ang 16-bit Timer na may mas mahusay na Resolution na ang 8-bit Timer.
Ang Prescaler ay isang pangalan para sa bahagi ng isang microcontroller na hinahati ang orasan ng oscillator bago ito maabot ang lohika na nagdaragdag ng katayuan ng timer. Ang saklaw ng prescaler id ay mula 1 hanggang 256 at ang halaga ng Prescaler ay maaaring itakda gamit ang OPTION Register (Ang parehong ginamit namin para sa pull up resistors). Halimbawa kung ang halaga ng prescaler ay 64, pagkatapos para sa bawat ika- 64 na pulso ang Timer ay madaragdagan ng 1.
Tulad ng pagdagdag ng timer at kapag umabot ito sa maximum na halagang 255, mag-uudyok ito ng isang makagambala at ipasimulan muli ang sarili nito upang 0 bumalik muli. Ang pagkakagambala na ito ay tinatawag na Timer Interrupt. Ang pagkagambala na ito ay nagpapaalam sa MCU na ang partikular na oras na ito ay lapped.
Ang Fosc ay nangangahulugang Frequency ng Oscillator, ito ang dalas ng ginamit na Crystal. Ang oras na ginugol para sa Timer register ay nakasalalay sa halaga ng Prescaler at ang halaga ng Fosc.
Programming at Paggawa ng Paliwanag:
Sa tutorial na ito magtatakda kami ng dalawang mga pindutan bilang dalawang mga input at 8 LED bilang 8 output. Gagamitin ang unang pindutan upang maitakda ang pagkaantala ng oras (500ms para sa bawat push) at ang pangalawang pindutan ay gagamitin upang simulan ang pagkakasunud-sunod ng timer na kumikislap. Halimbawa Suriin ang Video ng Demonstrasyon sa pagtatapos ng Tutorial na ito.
Ngayon, naisip ang mga pangunahing kaalaman na ito ay tingnan natin ang aming program na ibinigay sa dulo ng seksyon ng Code.
Mas okay kung hindi mo nakuha ang programa, ngunit kung nakuha mo !! Bigyan ang iyong sarili ng isang cookie at itapon ang programa upang masiyahan sa iyong output. Para sa iba ay sisirain ko ang programa sa mga makabuluhang bahagi at ipaliwanag sa iyo kung ano ang nangyayari sa bawat bloke.
Tulad ng lagi ang mga unang ilang linya ng code ay ang mga setting ng Configuration at mga file ng header, hindi ko ito ipapaliwanag dahil nagawa ko na ito sa aking nakaraang mga tutorial.
Susunod, laktawan natin ang lahat ng mga linya at tumalon nang diretso sa walang bisa na pangunahing pag-andar, sa loob nito mayroon kaming pagsasaayos ng PORT para sa Timer0.
void main () {/ ***** Konfigurasi ng Port para sa Timer ****** / OPTION_REG = 0b00000101; // Timer0 na may panlabas na freq at 64 bilang prescalar // Pinapagana din ang Pull UPs TMR0 = 100; // Load ang halaga ng oras para sa 0.0019968s; ang delayValue ay maaaring nasa pagitan ng 0-256 lamang TMR0IE = 1; // Paganahin ang timer makagambala nang kaunti sa PIE1 rehistro GIE = 1; // Enable Global Interrupt PEIE = 1; // Paganahin ang Peripheral Interrupt / *********** ______ **** ***** /
Upang maunawaan ito kailangan nating tingnan ang Pagparehistro ng OPSYON sa aming datasheet ng PIC.
Tulad ng tinalakay sa nakaraang tutorial ang bit 7 ay ginagamit upang paganahin ang mahinang pull up Resistor para sa PORTB. Tingnan ang nasa itaas na pigura, ang bit 3 ay ginawang 0 upang turuan ang MCU na ang sumusunod na prescaler na itinatakda ay dapat gamitin para sa Timer at hindi para sa WatchDogTimer (WDT). Napili ang mode ng timer sa pamamagitan ng pag-clear sa bit 5 T0CS
(OPTION_REG <5>)
Ngayon, ang bits2-0 ay ginagamit upang itakda ang prescaler na halaga para sa timer. Tulad ng ipinakita sa talahanayan sa itaas upang magtakda ng isang prescaler na halaga ng 64, ang mga piraso ay dapat itakda bilang 101.
Susunod, tingnan natin ang Mga Rehistro na nauugnay sa Timer0
Ang Timer ay magsisimulang magdagdag ng isang beses na itinakda at overflow pagkatapos maabot ang isang halaga ng 256, upang paganahin ang Timer makagambala sa puntong ito ang rehistro TMR0IE ay dapat na itakda mataas. Dahil ang Timer 0 mismo ay isang peripheral kailangan naming paganahin ang Peripheral Interrupt sa pamamagitan ng paggawa ng PEIE = 1. Sa wakas kailangan naming paganahin ang Global Interrupt upang maabisuhan ang MCU tungkol sa Makagambala sa anumang operasyon, ginagawa ito sa pamamagitan ng paggawa ng GIE = 1.
Pagkaantala = ((256-REG_val) * (Prescal * 4)) / Fosc
Ginagamit ang formula sa itaas upang makalkula ang halaga ng pagkaantala.
Kung saan
REG_val = 100;
Prescal = 64
Fosc = 20000000
Ito ay sa pagkalkula ay nagbibigay, Pagkaantala = 0.0019968s
Ang susunod na hanay ng mga linya ay upang itakda ang I / O Ports.
/ ***** Configure ng Port para sa I / O ****** / TRISB0 = 1; // Instruct the MCU that the PORTB pin 0 is used as input for button 1. TRISB1 = 1; // Instruct the MCU that the PORTB pin 1 is used as input for button 1. TRISD = 0x00; // Turuan ang MCU na ang lahat ng mga pin sa PORT D ay output PORTD = 0x00; // Ipasimula ang lahat ng mga pin sa 0 / ********* ** ______ ********* /
Ito ay katulad ng dati naming tutorial dahil gumagamit kami ng parehong hardware. Maliban na nagdagdag kami ng isa pang pindutan bilang input. Ginagawa ito ng linya na TRISB1 = 1.
Susunod, sa loob ng walang hanggan habang loop mayroon kaming dalawang mga bloke ng code. Ang isa ay ginagamit upang makuha ang input ng timer mula sa gumagamit at ang iba pa upang maisagawa ang pagkakasunud-sunod ng pagkaantala sa mga LED. Ipinaliwanag ko ang mga ito sa pamamagitan ng paggamit ng mga komento laban sa bawat linya.
habang (1) {count = 0; // Huwag patakbuhin ang timer habang nasa pangunahing loop // ******* Kunin ang pagkaantala ng numero mula sa gumagamit **** ////// if (RB0 == 0 && flag == 0) // Kailan ibinigay na input ang {get_scnds + = 1; // get_scnds = get_scnds + http: // Increment variable flag = 1; } kung (RB0 == 1) // Upang maiwasan ang tuluy-tuloy na pagtaas ng bandila = 0; / **** ***** ______ ********** /
Ang isang variable na tinatawag na get_scnds ay incremented sa bawat oras na ang mga gumagamit presses ang pindutan ng 1. Ang isang bandila (software na tinukoy) variable ay ginagamit upang i-hold ang incrementing proseso hanggang nag-aalis ng user ang kanyang daliri mula sa pindutan.
// ***** Isagawa ang pagkakasunud-sunod na may pagkaantala **** ////// habang (RB1 == 0) {PORTD = 0b00000001 <
Kumilos ang susunod na bloke kung ang pindutang dalawa ay pinindot. Dahil natukoy na ng gumagamit ang kinakailangang pagkaantala ng oras gamit ang isang butones at nai-save ito sa variable na get_scnds. Gumagamit kami ng isang variable na tinatawag na hscnd, ang variable na ito ay kinokontrol ng ISR (Interrupt service routine).
Ang gumagambala na gawain sa serbisyo ay isang Nakagambala na tatawagin sa tuwing umaapaw ang Timer0. Tingnan natin kung paano ito kinokontrol ng ISR sa susunod na bloke, tulad ng nais naming dagdagan ang pagkaantala ng oras ng kalahating segundo (0.5s) sa bawat pindutin ang pindutan pagkatapos ay kailangan nating dagdagan ang variable na hscnd para sa bawat kalahating segundo. Tulad ng na-program namin ang aming timer sa higit na daloy para sa bawat 0.0019968s (~ 2ms), kaya't upang mabilang ang kalahating segundo na bilang ng variable ay dapat na 250 dahil 250 * 2ms = 0.5 segundo. Kaya't kapag ang bilang ay nakakakuha ng 250 (250 * 2ms = 0.5 segundo), nangangahulugan na kalahating segundo ito kaya nadagdagan namin ang hscnd ng 1 at pinasimulan ang bilang sa zero.
void interrupt timer_isr () {if (TMR0IF == 1) // Timer flag has been trigered dahil sa timer overflow {TMR0 = 100; // Load the timer Halaga TMR0IF = 0; // Clear timer makagambala bilang ng flag ++; } kung (count == 250) {hscnd + = 1; // hscnd ay makakakuha ng dagdagan para sa bawat kalahating segundo na bilang = 0; }}
Kaya ginagamit namin ang halagang ito at ihinahambing ito sa aming hscnd at ilipat ang aming LED batay sa oras na tinukoy ng gumagamit. Ito rin ay halos kapareho sa huling tutorial.
Iyon ay mayroon kaming naiintindihan at gumagana ang aming programa.
Circuit Diagram at Proteus Simulation:
Tulad ng dati ay hinahayaan na i- verify muna ang output gamit ang Proteus, na-link ko rito ang mga eskematiko na file ng Proteus.
Magdagdag ng isang pindutan sa aming nakaraang LED board at handa nang puntahan ang aming hardware. Dapat itong magmukhang ganito:
Matapos ang koneksyon ay tapos na, I-upload ang code at i-verify ang output. Kung mayroon kang anumang problema mangyaring gamitin ang seksyon ng mga komento. Suriin din ang Video sa ibaba upang maunawaan ang buong proseso.