Práce s I/O porty v jazyku symbolických adres (Assembly language )

Seznámení se základními příkazy jazyka assembler. Pomoci těchto příkazů ovládat periferie, na kterých je připojen modul LED diod a  tlačítek.

Řešené příklady :
•    Po zmáčknutí tlačítka rozsviť všechny LED
•    Po zmačknutí tlačítka zablikej se všemi LED (nutná práce s časem – vytvoření přesné časové smyčky)
•    Vytvoř posuvné světlo – student má k dispozici 8 LED ( práce s časem a adresováním výstupního portu)

Zadání :

Příklad 1 :
Rozsviť LED dle zmáčknutých tlačítek.

Příklad 2
Pokud je zmáčknuto tlačítko 1,tak svítí všechny LED.

Příklad 3 :
Pokud je zmáčknuto tlačítko 1, tak všechny LED blikají v intervalu cca 0,1s.

Příklad 4.:
Vytvořte postupně rotující světlo (vždy svítí jen 1 cca 0,1s)


Nápověda:


Elektrické zapojení LED a tlačítek:
zapojeni_LED_a_tlac.png

Princip práce s LED a tlačítkem

LED dioda je zapojena přes předřadný odpor na + 5V. 
Pokud nastavíme na pin (PA7) logickou 1 - LED neprochází proud a nesvítí.
Pokud nastavíme na pin (PA7) logickou 0 - LED prochází proud směrem do procesoru a svítí.

Tlačítko je zapojeno na GND. Na pin (PA0) je nutné trvale nastavit vnitřní pullup odpor pomocí registru PORTx.
Pokud je tlačítko rozepnuto, tak díky vnitřnímu pullup odporu čteme na pinu (PA0) logickou 0.
Pokud je tlačítko sepnuto, tak se potenciál GND dostane na pin (PA0) a čteme logickou 1.

Prázdný program v asm:
;***************************************************************
;*  Definice procesoru *
;*************************************************
.DEVICE atmega128  ; neni nutne, ale je vhodne (kontrola spravnosti rozsahu pameti atd atd)
;*********************************************************************
; Definice portu a registru  (pomoci direktiv) Adresy dle datasheetu str. 362
.EQU PIND =$10       ; PORT D VSTUP - Tlacitka
.EQU DDRD =$11       ; PORT D SMER
.EQU PORTD =$12      ; PORT D
.EQU PINB =$16       ; PORT B
.EQU DDRB =$17       ; PORT B SMER
.EQU PORTB =$18      ; PORT B VYSTUP - LEDky
;************************************************************
; Definice promenych  (volne registry 16-31 - viz dataheet str 13.)
.def DATA=r25    ;definice promene "DATA" do registru R25 (prirazeni jmena registu)
;************************************************************
;************************************************************
; inicializace portu    (prikazy dle intrukcní sady datasheet str. 365)
init: 
; Zacatek programu :
start:  
        rjmp start


Použité registry:
DDRx – Data Direction Registr – směr toku dat. Určuje zda bude pin vstupní nebo výstupní.
PINx – načtení hodnoty na vstupu
PORTx- nastavení hodnot na výstupu

Použité instrukce (seznam všech instrukcí je v datasheetu použitého procesoru – u ATmega128 str. 365) :

LDI – uložení konstanty do registru (proměnné)
OUT – zápis dat z registru (proměnné) do I/O prostoru
IN – načtení dat z I/O prostoru do registru (proměnné)
RJMP – relativní skok na adresu (část programu, atd. )
SBRC – Testování bitu v registru, zda je vynulován (clear), pokud ano přeskakuje následující instrukci
SBRS – Testování bitu v registru, zda je nastaven (set), pokud ano přeskakuje následující instrukci
SBIC – Testování bitu v I/O prostoru, zda je vynulován (clear), pokud ano přeskakuje následující instrukci
SBIS – Testování bitu v I/O prostoru, zda je nastaven (set), pokud ano přeskakuje následující instrukci
RCALL – relativní volání podprogramu. Návratová hodnota je uložena v zásobníku (stackpointer)
RET – návrat z podprogramu
INC / DEC – inkrementuje / dekrementuje obsah registru (proměnné)
BRNE – pokud je předešlá instrukce nenulová, provede se relativní skok na zvolenou část programu
ROR – rotace bitu vpravo
ROL – rotace bitu vlevo


Řešení :

Příklad 1:

;**************************************************************
;*  Definice procesoru *
;*************************************************
.DEVICE atmega128  ; neni nutne, ale je vhodne (kontrola spravnosti rozsahu pameti atd atd)
;*********************************************************************
; Definice portu a registru  (pomoci direktiv) Adresy dle datasheetu str. 362
.EQU PIND =$10       ; PORT D VSTUP 
.EQU DDRD =$11       ; PORT D SMER
.EQU PORTD =$12      ; PORT D
.EQU PINB =$16       ; PORT B
.EQU DDRB =$17       ; PORT B SMER
.EQU PORTB =$18      ; PORT B VYSTUP
;************************************************************
; Definice promenych  (volne registry 16-31 - viz dataheet str 13.)
.def DATA=r25    ;definice promene "DATA" do registru R25 (prirazeni jmena registu)
;************************************************************
; inicializace portu    (prikazy dle intrukcní sady datasheet str. 365)
init:    ldi DATA,$ff     ;(LDI-ulozi konstantu do registru)
    out ddrb,DATA    ;(OUT-presun dat do I/O portu) - DDRx-smer toku 1 je vstup, 0 je vystup
    ldi DATA,$00
    out ddrd,DATA
; Zacatek programu :
start:   
    in DATA,pind     ; (IN -nacteni dat s I/O do registru)
    out portb,DATA   
    rjmp start
 

Příklad 2:

;***************************************************************
;*  Definice procesoru *
;*************************************************
.DEVICE atmega128  ; neni nutne, ale je vhodne (kontrola spravnosti rozsahu pameti atd atd)
;*********************************************************************
; Definice portu a registru  (pomoci direktiv) Adresy dle datasheetu str. 362
.EQU PIND =$10       ; PORT D VSTUP 
.EQU DDRD =$11       ; PORT D SMER
.EQU PORTD =$12      ; PORT D
.EQU PINB =$16       ; PORT B
.EQU DDRB =$17       ; PORT B SMER
.EQU PORTB =$18      ; PORT B VYSTUP
.EQU SPL = $3D  ; Stackpointer lowbyte
.EQU SPH = $3E ; Stackpointer highbyte
;************************************************************
; Definice promenych  (volne registry 16-31 - viz dataheet str 13.)
.def DATA=r25    ;definice promene "DATA" do registru R25 (prirazeni jmena registu)
;************************************************************
; inicializace portu    (prikazy dle intrukcní sady datasheet str. 365)
init:    ldi DATA,$ff      ;(LDI-ulozi konstantu do registru)
    out ddrb,DATA     ;(OUT-presun dat do I/O portu) - DDRx-smer toku 0 je vstup, 1 je vystup
    ldi DATA,$00
    out ddrd,DATA
;**************************************************************
;Nastaveni STACK Pointeru (ma byt konec v pameti)
;konec SRAM dle datassheetu pro ATmega 128 str 20. je $10FF
ldi DATA,$ff
out SPL,DATA ;nastavení SPL (SP lowbit)
ldi DATA,$10
out SPH,DATA ;nastavení SPH (SP hightbit)
;**************************************************************
; Zacatek programu :
;****************************************************************
start:   
          sbic pind,0    ; jestli splnena podminka tak nasledujici instrukce,jinak ta dalsi
        rjmp nesviti
        rjmp sviti
;****************************************************************           
;Podprogramy
;****************************************************************
sviti:   
        ldi DATA,0
        out portb,DATA
        rjmp start
;****************************************************************
nesviti:
        ldi DATA,255
        out portb,DATA
        rjmp start
 


Příklad 3:


Viz příklad 2, přidat:
.def ta =r17 ;register pro časování
.def tb =r18 ;register pro časování
.def tc =r19 ;register pro časování

Podprogram sviti upravit pro blikání:
;**************************************************
sviti:    ;(blika)

        ldi DATA,0
        out portb,DATA
        rcall cekej
        ldi DATA,255
        out portb,DATA
        rcall cekej
        rjmp start

vytvořit podprogram „cekej“ :
;* Podprogram CEKEJ
;***************************************************************************************
cekej:     ldi ta,10
    ldi tb,0
    ldi tc,0
cekam:     dec tc
    brne cekam ;první smyčka
    dec tb
    brne cekam ;druhá smyčka
    dec ta
    brne cekam ;třetí smyčka
    ret

;******************************************************************************************
;* čas cekej je daný třemi vnořenýmí cykly; jeden cyklus trvá 3 periody
;* a podle vstupního obsahu příslušného registru proběhne až 256 x
;* (zde první a druhá smyčka); zde 10 * 256 * 256 * 3 * perioda;
;* perioda T = 1/f, zde při f=14MHz je0,125 us,
;* takže je generováno zpoždění 0,14s
;*****************************************************************************************


Příklad 4:


Viz přiklad 3 hlavní program upravit :

; Zacatek programu :

ldi DATA,0b11111111 ; 0 - sviti , 1 - nesviti

start:   
       
       
        out portb,DATA
        ror DATA           ;(ROR - rotate right, presunuje se priznak C,ROL - rot.left)
        rcall cekej
        rjmp start         ; skok na zacatek