Mikrokontroler PIC16f628a in 7-segmentni LED prikazovalnik

7-segmentni LED-prikazovalnik:

Slika 1: 7-segmentni LED prikazovalnik

7-segmentni prikazovalnik priključimo na mikrokontroler tako, da vsak segment povežemo z lastnim pinom mikrokontrolerja preko zaščitnega upora. Za vklapljanje posameznih segmentov prikazovalnika z logično 1 uporabljamo take s skupno katodo, za vklapljanje z logično 0 pa prikazovalnike s skupno anodo.

Slika 2: Priključitev elementov na mikrokontroler

Zaradi enostavnosti vezja, npr. konstruiranja tiskanega vezja v okolju Eagle, bomo priključili segmente prikazovalnika na pine mikrokontrolerja PIC16f628a, kot je prikazano v tabeli 1. Ne smemo pozabiti na zaščitne upore, vsak segment prikazovalnika povežemo z lastnim pinom mikrokontrolerja preko upora 330 Ω.

Tabela 1: Priključitev 7-segmentnega LED-prikazovalnika na mikrokontroler

Poglejmo si program v assemblerju, ki na prikazovalniku s skupno katodo prikazuje štetje od 0 do 9 v intervalih 1 s:

 ;-------------------------------------------------------------------------------------

 ;PIC mikrokontroler in 7-segmentni prikazovalnik s skupno katodo

 ;Okolje MPLAB IDE v8.92, prevajalnik MPASM Assembler V5.51, oscilator 4 MHz.

 ;Avtor: Milan Ivič, dec 2017

 ;-------------------------------------------------------------------------------------

    list p=16f628a                   ;Tip mikrokontrolerja

    #include <p16f628a.inc>          ;Vključi v program datoteko p16f628a.inc.

    __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _LVP_OFF & _XT_OSC

Stevilo    equ 0x20                     ;Število za izpis

Stevec    equ 0x30                    ;Števec za zakasnitev

    org 0x000                           ;Ponastavitveni vektor

    goto Glavni                         ;Nadaljuj na naslovu Glavni

    org 0x004                           ;Prekinitveni vektor

 ;********************* Glavni program *********************

Glavni

    bcf    STATUS,5                 ;Banka 0

    movlw b'00000111'

    movwf CMCON                     ;Omogočimo vhodno-izhodne pine na PORTA

    bsf    STATUS,RP0               ;Banka 1

    clrf    TRISB                       ;Vsi pini PORTB so izhodni

    movlw b'10000011'

    movwf OPTION_REG           ;Preddelilnik dodeljen časovniku TMR0, preddelitev 1 : 16

    bcf    STATUS,5                     ;Banka 0

    clrf    PORTB                       ;Inicializacija PORTB

    clrf    INTCON                      ;Onemogočimo odzivanje na prekinitve

    clrf    Stevilo                     ;Inicializacija, Stevilo = 0

Prikazuj

    call    Izpisi                      ;Izpiši število na 7-segmentni prikazovalnik

    call    Cakaj                       ;Zakasnitev 1 s

    incf    Stevilo,f                   ;Povečaj Stevilo za 1

    movlw .10

    subwf    Stevilo,w

    btfsc     STATUS,Z                 ;Ali smo že prišli do številke 9?

    clrf    Stevilo                     ;Da, postavi Stevilo na 0

    goto    Prikazuj                    ;Ne, prikaži naslednjo številko

 ;********************* Podprogram za zakasnitev 1 s *********************

Cakaj

    clrf    Stevec                   ;Stevec = 0

    clrf    TMR0                     ;TMR0 = 0

Se

    btfss    INTCON,T0IF             ;Ali je preteklo 4,1 ms? Ali je TMR0 prekoračil svojo vrednost?

    goto    Se                       ;Ne

    clrf    INTCON                   ;Da, postavi zastavico T0IF na 0

    incf    Stevec,f                 ;Povečaj Stevec za 1

    movlw .244                       ;Vrednost delovnega registra je 244

    subwf Stevec,w                   ;Vrednost delovnega registra odštej od vrednosti Stevec

    btfss    STATUS,Z                ;Z = 1? Ali je pretekla 1 sekunda? (4,1 ms x 244 ~ 1 s)

    goto    Se                       ;Ne še

    return                           ;Da

 ;********************* Tabela znakov za prikazovalnik *********************

Znaki    addwf PCL,f

    DT    0xB7,  0x82,  0xE5,  0xE3,  0xD2,  0x73,  0x77,  0xA2,  0xF7,  0xF3

 ;********* Podprogram za izpis znaka na 7-segmentni prikazovalnik *********

Izpisi

    movf    Stevilo,w                ;Kopiraj vrednost registra Stevilo v delovni register

    call    Znaki                    ;V tabeli izberi ustrezni znak

    movwf PORTB                      ;Izpiši število na 7-segmentni prikazovalnik

    return

    end

V glavnem programu nastavimo časovnik TMR0 tako, da deluje kot števec časa s preddelilnikom 1 : 16. Časovnik smo uporabili zato, da z njim odmerimo približno 1 sekundo za zakasnitev med spreminjanjem vrednosti na 7-segmentnem prikazovalniku. Časovnik je nastavljen tako, da povečuje svojo vrednost od 0 do 255 v 4,1 ms pri 4 MHz oscilatorju. Podprogram Cakaj se izvaja toliko časa, dokler časovnik 244-krat ne prekorači svoje vrednosti (overflow). V ta namen preverjamo zastavico T0IF v registru INTCON, ki se ob prekoračitvi na časovniku postavi na 1.

Za preverjanje števila prekoračitev časovnikovega registra smo uporabili novo instrukcijo subwf (vrednost registra Work odšteje od vrednosti registra f, ki je v našem primeru Stevec). Pred to instrukcijo smo delovnemu registru določili vrednost 244, ker želimo 244 ponovitev. Spremenljivka Stevec se povečuje za 1 vsakokrat, ko časovnik prekorači svojo vrednost. Ko časovnik 244-krat prekorači svojo vrednost, je vrednost spremenljivke Stevec enaka 244. Ker je rezultat odštevanja 244 – 244 = 0, se zastavica Z v registru STATUS (njegov tretji bit) postavi na 1, kar je pogoj, da se iz podprograma za zakasnitev vrnemo v glavni program. Enako v glavnem programu preverjamo, ali smo že prešteli do 9.

V zanki v glavnem programu povečujemo vrednost spremenljivke Stevec in njeno vrednost vsakič spremenimo v kodo znaka, ki ga želimo prikazati na prikazovalniku. Pretvorbo napravimo s tabelo v programskem pomnilniku. Če želimo na primer na 7-segmentni prikazovalnik izpisati številko 7, shranimo v delovni register vrednost 7 in nato pokličemo tabelo, ki ima na osmem mestu (šteje se od mesta 0 naprej) kodo znaka 7 (0xA2). To kodo pošljemo na PORTB, kamor je priključen 7-segmentni prikazovalnik s skupno katodo. Če kodo 0xA2 pretvorimo v dvojiški številski sistem, dobimo b'10100010', kar pomeni, da bo na priključkih RB1, RB5 in RB7 napetost 5 V. Ker so na te priključke povezani segmenti c, a in b 7-segmentnega prikazovalnika, bo prikazoval številko 7.

Za shranjevanje vrednosti spremenljivke Stevilo v delovni register smo uporabili novo instrukcijo movf. Ta kopira vrednost prvega parametra, ki je v našem primeru Stevilo, na mesto, določeno z drugim parametrom, v našem primeru w.

Tabele podatkov:

Programski pomnilnik mikrokontrolerja pogosto uporabljamo za shranjevanje podatkov, napisanih v obliki tabele. Ta ima obliko podprograma. Preden tabelo pokličemo z instrukcijo call, moramo v delovni register vpisati zaporedno številko (odmik) podatka, ki ga želimo dobiti iz tabele. Prvi element tabele ima odmik 0. Ko se tabela izvrši, dobimo v delovnem registru vrednost izbranega podatka v tabeli. Tak način pridobivanja podatkov iz tabele nam omogoči direktiva DT (define table – definiraj tabelo).Ta direktiva nadomesti vsak 8-bitni podatek za njo od leve proti desni. Podatek je lahko številka, znak ali beseda:

DT .12, 0xA2, 'K', "Mikrokontroler".

Podatke ločimo z vejico. Paziti moramo, da pri klicu ne prekoračimo konca tabele. Tako lahko v tabelo zapišemo največ 256 8-bitnih podatkov, saj je PCL 8-bitni register.

Mikrokontroler vsebuje poseben register, imenovan programski števec. V njem se vedno nahaja naslov naslednje instrukcije, ki se mora v programu izvesti. Pri mikrokontroleju PIC16f628a je ta register 13-biten, kar zadošča za 8 k besed programskega pomnilnika. Ker ima PIC16f628a na voljo le 2 k programskega pomnilnika Flash, ostaneta zgornja dva bita programskega števca neuporabna. Tako nam ostane 11-biten programski števec, ki lahko naslovi 2 k (2048) besed pomnilnika. Programski števec je dosegljiv preko dveh registrov SFR: PCLATH in PCL, ki se nahajata v vseh štirih bankah. Register PCL vsebuje spodnjih 8 bitov programskega števca in ga lahko poljubno beremo ali pa vanj vpisujemo. Zgornjih 5 bitov programskega števca pa se nahaja v registru PCLATH, ki ni direktno dosegljiv.

Poglejmo primer tabele iz prejšnje vaje, ko je 7-segmentni prikazovalnik izpisoval številke od 0 do 9:

;********************* Tabela znakov za prikazovalnik *********************

Znaki    addwf PCL,f

    DT    0xB7,  0x82,  0xE5,  0xE3,  0xD2,  0x73,  0x77,  0xA2,  0xF7,  0xF3

Preden smo z instrukcijo call Znaki poklicali tabelo, smo delovnemu registru določili odmik podatka, ki smo ga želeli dobiti iz tabele. Prva instrukcija tabele addwf PCL,f prišteje registru PCL vrednost delovnega registra w. To pomeni, da se bo izvršila instrukcija, ki je na novem naslovu programskega pomnilnika. Če damo v delovni register w vrednost 0 in pokličemo tabelo, bomo po vrnitvi iz tabele dobili v delovnem registru w vrednost prvega podatka (od leve proti desni) tabele (0xB7). Če damo v register w vrednost 5 in pokličemo tabelo, bomo po vrnitvi iz tabele dobili v delovnem registru w vrednost šestega podatka tabele (0x73), saj se šteje od mesta 0 naprej. V prejšnjem programu se je vrednost delovnega registra w povečevala po vrsti od 0 do 9.

Povzetek:

Programski pomnilnik mikrokontrolerja PIC je v prvi vrsti namenjen shranjevanju programa. Pogosto pa ga uporabljamo za shranjevanje podatkov v tabelah, ki jih v programski pomnilnik vpišemo skupaj s programom. Tabele definiramo z direktivo DT. V tabele lahko zapisujemo podatke v obliki znakov, besed ali števil v različnih številskih sistemih, zapišemo pa lahko največ 256 8-bitnih podatkov. Za vrnitev iz tabele s pravim podatkom poskrbi programski števec, v katerem se vedno nahaja naslov naslednje instrukcije, ki se mora v programu izvesti.

Na mikrokontroler smo priključili 7-segmentni prikazovalnik s skupno katodo. Za zaščito segmentov prikazovalnika smo vsakega posebej preko 330-ohmskih uporov povezali z ustreznim priključkom mikrokontrolerja, skupne katode vseh segmentov pa z maso.

V programu smo časovnik TMR0 uporabili kot števec časa. Z dodelitvijo in nastavitvijo preddelilnika smo mu določili čas, v katerem doseže svojo maksimalno vrednost 255. Število želenih prekoračitev časovnika smo preverjali z zastavico registra STATUS, ki se postavi na vrednost 1, ko je rezultat zadnje operacije enak 0.