V prejšnji vadnici smo spoznali utripanje LED z mikrokrmilnikom PIC in zgradili enako vezje na plošči Perf. Nato smo uporabili PICkit 3, ICSP in MPLAB IPE za odlaganje programa na našo ploščo Perf. Zdaj bomo v tej vadnici napredovali do uporabe več nožic na mikrokrmilniku PIC. Uporabili bomo 7 izhodov (LED) in en vhod. Za to vadnico bomo uporabili staro ploščo Perf (prikazano spodaj) in dodali berg palčke, da izvlečemo zahtevane nožice na drugo LED ploščo. Na koncu te vadnice bomo ustvarili zaporedje utripajočih LED z uporabo mikrokrmilnika PIC PIC16F877A in se naučili, kako uporabljati več vhodov in izhodov, nekaj osnov za klic zanke in funkcije.
Plošča LED ni nič drugega kot še ena odbojna plošča, na katero bomo spajali LED-diode s trenutno omejevalnim uporom (prikazano spodaj). Dodali bomo tudi tipko za sprožitev utripanja LED v zaporedju.
Shema vezja:
Mikrokontroler PIC16F877A LED utripajoča zaporedna koda in delovna razlaga:
Spodaj je navedena celotna koda (preverite na koncu), tukaj jo bomo dobili po vrsticah. Ta koda bo začela svetleti LED zaporedno, ko pritisnete gumb. Da bi razumeli zaporedja, si oglejte video na koncu vadnice. Priporočam vam, da primerjate izhod, prikazan v videu, s spodnjo kodo in poskusite razumeti program.
Poglejmo kodo po vrsticah. Prvih nekaj vrstic je za nastavitev konfiguracijskih bitov, ki so bili razloženi v prejšnji vadnici, zato jih za zdaj preskačem. Najboljši način za razumevanje katerega koli programa je, da začnemo z glavno funkcijo ( void main () ), zato naredimo to
TRISB0 = 1; // MCU naročite, da se za vhod gumba uporablja zatič PORTB 0. TRISD = 0x00; // MCU naročite, da so vsi zatiči izhodni PORTD = 0x00; // Inicializiramo vse nožice na 0
Beseda TRIS se uporablja za določanje, ali se zatič uporablja kot vhod / izhod, beseda PORT pa za pripenjanje visoko / nizko. Vrstica TRISB0 = 1 bo kot vhod predstavljala 0. zatič PORTA B. To bo naš gumb. Vrstice TRISD = 0x00; PORTD = 0x00; bo vse zatiče vhoda D postavil kot izhod in tem zatičem dodelil začetno vrednost LOW.
Ker smo rekli, da se B0 uporablja kot vhod, bomo en konec tipke priključili na zatič B0, drugi konec pa na tla. Do takrat, ko pritisnemo gumb, se zatič drži na tleh, kot je prikazano na zgornjem diagramu povezav. Da pa se to lahko zgodi, moramo uporabiti vlečni upor, tako da bo zatič držal visoko, ko gumba ne pritisnemo. Povlečni upor je nekaj takega.
Toda naš PIC MCU ima notranji šibek upor, ki ga lahko aktivira programska oprema in tako prihrani veliko težav (kadar je treba povezati več gumbov).
Kaj je šibek upor?
Obstajata dve vrsti upornih uporov, eden je šibek vlečni gor in drugi močan vlečni gor. Šibki vlečni upori so visoke vrednosti in tako omogočajo pretok šibkega toka, močni vlečni upori pa so nizke vrednosti, kar omogoča močan tok. Vsi MCU večinoma uporabljajo šibke upore. Da bi to aktivirali v našem PIC MCU, moramo poiskati naš podatkovni list za OPTION_REG (register možnosti), kot je prikazano na spodnjem posnetku.
Kot je prikazano, se bit 7 ukvarja s šibkim uporom. Za njegovo aktiviranje mora biti nič. To naredi OPTION_REG <7> = 0 . To posebej obravnava bit 7, ki ostale bite pusti na privzete vrednosti. S tem pridemo v našo zanko while, kjer z uporabo if (RB0 == 0) preveri, ali je gumb pritisnjen . Če je pogoj izpolnjen, pokličemo svojo funkcijo s parametri 1, 3, 7 in 15.
trepalnica (1); // FUNKCIJSKI KLIC 1 s parametrom 1 sblink (3); // FUNKCIJSKI KLIC 3 s parametrom 3 sblink (7); // FUNKCIJSKI KLIC 7 s parametrom 7 sblink (15); // FUNKCIJSKI KLIC 4 s parametrom 15
Zakaj uporabljamo funkcije?
Funkcije se uporabljajo za zmanjšanje števila vrstic v naši kodi. To bi vedela večina od nas. Toda zakaj moramo zmanjšati število vrstic, še posebej, če gre za programiranje MCU. Razlog je omejen prostor v našem spominu programa. Če kode ne optimiziramo pravilno, nam lahko zmanjka prostora v pomnilniku. To bo prišlo prav, ko napišemo dolge strani kod.
Vsaka funkcija bo imela definicijo funkcije (v našem primeru sblink (int get) ) in funkcijo Call (v našem primeru sblink (1) ). Neobvezno je imeti izjavo funkcije, da bi se temu izognil, sem pred klicem funkcije v svojo glavno funkcijo dal definicijo funkcije.
Parametri funkcije so vrednost, ki bo posredovana iz klica funkcije v definicijo funkcije. V našem primeru so celoštevilčne vrednosti (1, 3, 7, 15) parametri, ki se posredujejo iz klica funkcije, spremenljivka "get" pa dobi vrednost parametrov v definicijo funkcije za njihovo obdelavo. Funkcija ima lahko več parametrov.
Ko je funkcija poklicana, se bodo izvedle spodnje vrstice v definiciji funkcije.
za (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED premik Levo zaporedje __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED premik Levo zaporedje __delay_ms (50); }
Zdaj se zdi ta vrstica nenavadna: PORTD = get << i . Pojasnil bom, kaj se tu dejansko dogaja.
"<<" je operater levega premika, ki premakne vse bite v levi položaj. Zdaj, ko prikličemo funkcijo sblink (int get) s parametrom '1' kot sblink (1), bo vrednost 'get' dosegla kot 1, kar je v binarni obliki 0b00000001. Zato bo ta vrstica kot PORTD = 0b00000001 << i .
Vrednost "i" se bo spreminjala od 0 do 7, saj smo uporabili 'for zanko' za (int i = 0; i <= 7 && RB0 == 0; i ++). Vrednost 'i' od 0 do 7 bo rezultat spremenila na naslednji način:
Kot lahko vidite, smo vklopili eno LED naenkrat (od leve proti desni), tako da smo ostale izklopili. Naslednja 'for zanka' za (int i = 7; i> = 0 && RB0 == 0; i--) bo prav tako storila enako, vendar bo tokrat LED zaporedoma vklopljena od desne proti levi, kot smo začeli od 7 in se spustili do 0. Uporabili smo zakasnitev 200 ms, da smo lahko videli, kako se LED vklop in izklop
Zdaj, ko prenesemo vrednost 3 v funkcijo sblink (int get) , bo izvedena funkcija sblink (3), zaradi česar je vrednost "get" 0b00000011, zato bo rezultat na PORTD:
Torej, tokrat se bosta s pomočjo sblink (3) v vsakem trenutku vklopili dve LED . Podobno za sblink (7) in sblink (15) zaporedoma svetijo tri in štiri LED. Ko bo to končano, bomo naredili, da bodo svetleče diode svetile s pomočjo črte PORTD = 0xFF . Oglejte si spodnji video za popolno predstavitev.
Upam, da ste razumeli kodo in se tako naučili, kako uporabljati funkcije zanke 'for' in 'while', da dobite želene rezultate. Zdaj se lahko potegnete po kodi, da dobite drugačno zaporedje utripanja LED. Pojdite naprej, prevedite svojo kodo in jo zložite na svoj MCU in uživajte v rezultatih. Če se kje zataknete, lahko uporabite odsek za komentarje. Sem sem priložil tudi simulacijske in programske datoteke.
Za zdaj bo to v naši naslednji vadnici, kjer bomo izvedeli, kako uporabljati časovnike PIC16F877A, namesto da uporabljamo funkcije zakasnitve. Vse vadnice mikrokrmilnika PIC si lahko ogledate tukaj.