Ugrás a kezdőlapra

Š Mohos Pál

ATMEGA 128 assembly programozása

Utolsó módosítás: 2014. október 30. csütörtök   16:35

1.      Assembly labor

1.1        Gyakori problémák:

ˇ         Ékezetes projektneveket nem szereti. Fatal Errort szokott kiírni.

ˇ         Az installálás nem a leírt módon történt. (FTDI-t is kell.)

1.      Két példányban van elindítva az AVR stúdió. (nem tud csatlakozni a HW )

ˇ         HW csatlakoztatás hiba (programozó, vagy debuggoló nem megy). Lásd: Tartalom 6. pont

1.2        Gyakran nem tudott részletek:

ˇ         Az atmega 128-nak mekkora a beépített RAM-ja?

ˇ         1k, azaz 2^10-en hexadecimálisan mennyi?

ˇ         64k hány biten címezhető?

ˇ         0x1000-1=?

ˇ         16 bit hány byte?

ˇ         4k hexadecimálisan mennyi, s hogyan jön ez ki?

ˇ         A STACK memória fizikailag melyik memóriában van? (FLASH, PROGRAM, RAM, EEPROM)

ˇ         A Program memória milyen technológiájú?

ˇ         Az atmega 128 program memóriája mekkora?

ˇ         Az atmega 128 program memóriája hány biten címezhető? (és hány bájt felhasználásával?)

ˇ         Az atmega 128 program memóriája 1 címen hány bit széles?

ˇ         Az 1k-t 1k-nak, vagy 1K-nak kell írni a számítástechnikában?

ˇ         Hogyan lehet egy STACK memóriát megvalósítani?

ˇ         Mi a makro és a szubrutin között a különbség?

ˇ         Mikor célszerű makrót, s mikor szubrutint alkalmazni? (A makró nevet leírom. A szubrutint meghívom)

 

2.      Assembly labor

2.1        AVR studio használata:

ˇ         Csak Internet explorerrel látható: Panelünk USB Driver telepítése.

ˇ         Csak Internet explorerrel látható: Assemby program készítése, letöltése.

2.2        Példa: Regiszter inkrementálás:

ˇ         Nézzétek a .org direktíva használatát. HW RESET után a 0. címről kezd a program futni.

ˇ        

ˇ         Mert a RESET a panel feszültség alá helyezése a programszámlálót (PC) 0 értékre állítja. Tehát az első utasítást a 0. címről fogja kiolvasni a processzor.

ˇ         Gépeljük be a programot.

ˇ         Értsük meg minden sorát.

ˇ         Fordítsuk le.

ˇ         Futtassuk soronként, figyelve az r20-as regiszter és a programszámláló tartalmát.

2.3        Példa: Számok összege:

ˇ         R20-ba képezzük az 1+2+…10 értékét!

ˇ        

2.3.1          A fenti program C-ben:

ˇ        

2.4        Aritmetikai – Logikai utasítások:

ˇ         Lásd a weblapomon az "utasításkészletből.

ˇ         Programíráskor használd az AVR stúdió HELP-jét

2.4.1          Példák:

 

2.5        Ugró utasítások:

2.5.1          SREG státus regiszter:

bit

SREG (státus regiszter) bitjei

Bit 7 - I:

 Global megszakítás engedélyezése 

I=1 a SEI és a RETI utasítással 

I=0 a CLI  utasítással és az IT érvényre jutásakor.

Bit 6 - T:

 Általános célú 1 bitnyi tároló

Bit 5 - H:

 Fél Carry Flag  3.-ról 4 bitre van átvitel. BCD aritmetikánál kell.
( Binárisan Kódolt Decimális számok.  Tehát 4 biten 0..9 közti érték lehet csak. )

Bit 4 - S:

 Előjel Bit, S =     N Exor V

Bit 3 - V:

 Kettes komplemens Overflow Flag

Bit 2 - N:

 Negatív Flag = R7 bittel

Bit 1 - Z:

 Zero Flag=1 ha mind a 8 bit=0

Bit 0 - C:

 Carry Flag ( a 9. bit aritmetikánál.

2db 8 bites szám összege lehet 9 bites. Vagy 3+(-4)=-1.

ˇ         A SREG bitjei (a ritkábban használatos) bit állító utasításokra, de jellemzően az aritmetikai-logikai, utasításokra, azok eredménye alapján változnak

ˇ         Minden utasításhoz meg kell nézni, melyik bit, s hogyan változik, de gyakorlattal ki is következtethető

ˇ         Kezdő szinten mi a Cés a Z ritkábban az N flag értéke alapján fogunk ugrásokat csinálni.

2.5.2          Feltételes ugrás:

ˇ         Lásd a weblapomon az "utasításkészletből.

2.5.3          Feltétel nélküli ugrás:

ˇ         Lásd a weblapomon az "utasításkészletből.

2.6        Adatmozgató utasítások:

2.6.1          Általános célú regiszterekre:

 

2.6.2          Portokra 0x0…0x3F portcímig (0x20…0x5F SRAMcímig):

 

2.6.3          Memória regiszterekre:

 

 

3.      Assembly labor

3.1        LED használat:

ˇ         Gyújtsuk ki először a LED 7..4 minden LED-jét, majd a LED 3..0 minden LED -jét.

ˇ         A programot soronként lépegetve a szimulátorral futtassuk

ˇ         A programot a HW-en futtassuk le.

3.1.1          Algoritmus:

3.1.1.1       A felhasznált HW infó:

ˇ         LED 3..0 = PORTB 7..4

ˇ         LED 7..4 = PORTD 7..4

3.1.1.2       Feladatok:

ˇ         PORTB és PORTD irányregiszterek kifelé állítása. DDRB=0xF0; DDRD=0xF0;

ˇ         Tökéletesebb, ha csak a felső 4 bitet módosítjuk.  Az alsó 4 bitet változatlan hagyva. Hf ezen gondolkodni. (A DDRB kiolvasott értékét bitenkénti VAGY kapcsolatba hozom 0xF0-al)

ˇ         PORTD=0xF0   ;a felső 4 LED kigyújtása.

ˇ         PORTB=0xF0

ˇ         Stop (ami nálunk végtelen ciklus lesz.

3.1.2          Assembly utasítások korlátai:

ˇ         Port regiszterbe konstans nem írható, csak az általános célú r16…r31-be.

ˇ         R16=0xF0;   Port…=r16;

3.1.3          Program:

ˇ        

3.2        Futtatás a HW -en is!

3.2.1          A Projekt JTAG ICE legyen:

vagy:

3.2.2          Szimulátoros projekt esetén:

ˇ         A letöltés előtt:   
DEBUG / SELECT PLATFORM… / JTAG ICE  ..Amtega 128

ˇ         A letöltés képekkel:        

3.3        HW csatlakoztatási probléma megoldás:

ˇ         A laborban, ha nem működik a programozó csatlakoztatása, akkor gyakran a programozó port kiosztásával van a baj.

ˇ         A programozó portnak COM4, vagy az alattinak kell lennie.

3.3.1          Programozó Soros Portátállítás lépései:

ˇ         Start / Vezérlőpult / Felügyeleti eszközök / Számítógép kezelés / Eszközkezelő         
vagy a Start / Vezérlőpult / Rendszer / Hardwer / Eszközkezelő

ˇ         Portok. (látszanak az üzemelő COM portok)

ˇ         Húzzuk ki a JTAG portját! (bal alul) Eltűnik a displayn a hozzá tartozó port. 
(Ha a mási csatlakozóhoz van rendelve a COM4, vagy alatti, akkor cseréljük fel a két USB csatlakozót! Kezdjük előröl a csatlakoztatást.)

ˇ         Dugjuk vissza a JTAG USB-jét. Megjelenik a displayn a hozzá tartozó port.

ˇ         JobbEgér / Port beállítása / Speciális / COM port száma.

ˇ         Itt egy szabad COM1…COM4 portot válasszunk ki. Mindent zárjunk le.

ˇ         Indítsuk újra a gépet!

3.3.2          Debuggoló soros port állítás

ˇ         A debuggoláskor a JTAG ICE  és az Atmega 128 választandó. (projekt indításkor, vagy a Debug / Select Platform…)

ˇ         Ha nem működik húzzuk ki az USB csatlakozót a panelből. (jobb oldalt), majd dugjuk vissza. (Ezáltal táp Resetet kap a panel. Az alapbeállítások jutnak érvényre.)

3.4        Makró használat:

ˇ         Az előző programot írhatjuk egyszerűbben is:   
LED_INIC           ;Ez egy makró hívás 
ldi LED,0x55       ;LED=0x55 
LEDOUT             ;Ez egy makró hívás

ˇ         A makró jelen esetben egy szövegszerkesztő keres - cserél funkció.    
Még fordítás előtt (az előfeldolgozó) a makrónevek ASCII kódsorozatát kicseréli a makróban definiált utasítások ASCII kódsorozatára. (Lásd később a Makró bemenő paramétereket! )

3.4.1          Program:

ˇ        

3.5        DELAY Időzítés- várakozás:

3.5.1          Feladat:

ˇ         A program ne menjen tovább egy ideig.

3.5.2          Lehetőségek:

ˇ         HW -el:számláló felprogramozás --> Interrupt kezelés 
időzítés alatt futhat más program, vagy 
az időzítés alatt kis energia felvételre (alvó módba) kapcsolhatom a processzort

ˇ         SW el: Egy, vagy több egymásba ágyazott regiszter értéket számlálgatok. (pl csökkentem 0-ig)       
Egy csökkentési ciklus utasításainak végrehajtási idejéből ( 2 órajel) és a számlálás (256 alkalom) szorzatából megkapom az időzítés (várakozás) óraperiódusainak számát, s az órajel alapján (8 vagy 16 Mhz nálatok) az 1 byteon végigszámlálás idejét.

3.5.3          Sw időzítő 1 regiszterrel:

3.5.3.1       Algoritmus:

ˇ         Reg=0;   reg=reg-1, amíg az eredmény nem 0.

ˇ         A feltételt az első decrement után figyelem, tehát, mikor a reg értéke 0xFF lett.       
Ezáltal 256-ot számlálhatok 1 db 8 bites regiszterrel.

3.5.3.2       Program:

ˇ        

3.5.4          SW időzítő 3 regiszterrel:

ˇ         3 regiszter egymásba ágyazásával 2^24 *2 ciklusig időzíthetek

ˇ         Programunkat szimulátor léptetésével ellenőrizzük.      
A regiszterekbe ezért kis értékeket, pl. 2-ket írjunk át a léptetés során. (Hogy ne számoljunk 255*255-öt. )     
A kezdőérték r1, r2 esetén 0

ˇ         A legnagyobb helyi értékű regiszter a TMP változó, ami a programunkban egy konstanssal írható regiszter. Tehát az r16…r31 közül valamelyik.

ˇ        

ˇ         Az eor r1,r1 minden bit kizáró vagy kapcsolatakor az azonos értékek miatt minden bitre 0-t ad.

ˇ         S1, s2 címke felesleges. Helyettük az s0-ra is ugorhatok. (Megértés miatt, hogy 0-val kezdek, írtam eredetileg a 3 címkét.)

3.5.5          HW időzítő Timer0-val futófény léptetése:

ˇ        

ˇ        

3.6        LED számláló makró időzítővel:

3.6.1          Feladat:

ˇ         Léptessük a Led –eket bináris számlálóként, látható módon. Tehát a léptetés 200msec…2 sec között legyen.

3.6.2          A felhasznált makrók:

ˇ        

3.6.3          A program:

ˇ        

ˇ         A makrókat a programmal közös fájlba tettem.

ˇ         A makrókat egy másik fájlba is tehetjük. Ilyenkor egy include –val kapcsolhatjuk a főprogramunkhoz.

3.7        STACK Elmélet:

3.7.1          STACK használat:

3.7.1.1       Hogyan lehet egy STACK memóriát megvalósítani?

ˇ         Stack pointert (memóriacímet tároló regiszter) beállítjuk, ahova írható az első adat. (A RAM vége jellemzően). Ügyelni kell, hogy a Stack mutató az adatok területét sose érje el.

ˇ         PUSH utasítás beír a STACK pointer által meghatározott memória címre, majd növeli a STACK pointer értékét.

ˇ         POP utasítás csökkenti a STACK pointer értékét és kiolvassa a memóriából az adatot egy regiszterbe.

ˇ         CALL utasítás 2, vagy 3 PUSH -t is tartalmaz.

ˇ         RET    utasítás 2, vagy 3 POP   -ot is tartalmaz.

3.7.1.2       Szubrutin használat:

ˇ         A stackpointer kezdő értékét az aktuálisan kiépített RAM terület végére állítjuk.

ˇ         A stackpointer SP 16 bites, (hogy a RAM bármely regiszterét megcímezhesse), ezért 2 db regiszterből áll az SPH és az SPL-ből. Ezek az IO címterületen vannak, tehát az out utasítással is írhatunk bele értéket.

ˇ         RAMEND egy előre definiált konstans az aktuális RAM terület utolsó címét jelenti.

ˇ         Az assembler elő feldolgozóban van a low(K) függvény, ami a K 16 bites konstans alsó bájtját adja.

ˇ         Ezután használhatjuk a CALL vagy az RCALL utasításokat subrutin hívásra.

ˇ        

ˇ         A (STACK) <-- PC+1 jelentése: A stack tárba kerül a következő utasítás címe. Tehát          
RCALL esetén a PC+2, 
CALL    esetén a PC+3 érték.

3.8        LED számláló szubrutin időzítővel:

Hiba esetén kérem, szóljatok a Fórumban

.include "m128def.inc"  ;include fájl a használt processzorhoz

     .def LED=r17

     .def TMP=r16

     .org 0

     rjmp RESET         ;ugrás a RESET címkére

     .org 70            ;program kezdete a 0x46-as címtől    

;***********************************************************************

RESET:

     ldi TMP,low(RAMEND)     ;StacPointer értéke a RAM vége.

     out SPL,TMP

     ldi TMP,high(RAMEND)

     out SPH,TMP

    

     call LED_INIC

;**************************************************************************

MAIN:                       ;main címke

     ldi LED,0

 

ok:  inc LED

     rcall LEDOUT

     rcall DELAY

    rjmp ok

 

     ;***********************************************************************    

;SUBRUTINOK***********************************************************

DELAY:

    ldi tmp,2      ;r0=0 szlo 24-17 bitje

     clr r1        ;ldi r1,0 -nak felel meg. r1=0 szló 16- 8 bitje

     clr r2        ;ldi r1,0 -nak felel meg. r2=0 szlo  7- 0 bitje

s0:  dec  r2

     brne s0

     dec  r1

     brne s0

     dec  tmp

     brne s0

     ret

;************************************************************************

LED_INIC:

     ldi TMP,0xF0      ;PORTB PORTD irányregisztereibe adat

     out  DDRB,TMP

     out  DDRD,TMP    ;LED-hez kifelé kell irányítani a portok7-4 bitjét

     ret

;*************************************************************************

LEDOUT:

     out  PORTD,LED ;PORTD7-4 =LED7-4 

                        ;PORTD3-0 bitje közömbös, nincs bekötve

     swap LED           ;LED7-4 és a LED 3-0 csere

     out  PORTB,LED ;LED3-0 kigyújtása POTB7-4-tre írással

     ;(a PORD3-0 és a PORTB3-0 értékei nem látszanak a LED-en)

     swap LED           ;LED változót eredetire vissza állítottuk

     ret

;*************************************************************************

3.8.1          Házi feladatok:

3.8.1.1       Időzítés:

Alábbi feladatokat

ˇ         makrós számláló

ˇ         Szubrutinhívásos számláló és

ˇ         Interruptos időzítéssel is meg kell tudni oldani.

3.8.1.2       Futófény jobbra :

ˇ         1 led fénye egy irányban fusson végig

ˇ         fenti feladat ismétlődön

3.8.1.3       Futófény balra :

ˇ         1 led fénye egy irányban fusson végig

ˇ         fenti feladat ismétlődön

3.8.1.4       Futófény jobbra-balra :

ˇ         1 led fénye egy irányban fusson oda.vissza

ˇ         fenti feladat ismétlődön

ˇ          

3.8.1.5       BCD LED számláló:

ˇ         BCD kódban, tehát 0…99-ig jelezzük ki a számokat a 8 LED-en.

ˇ         A TMP-t inkrementáljuk. Ha a 9-et növelem, akkor 16 azaz 0x10 legyen a következő szám. (a felső 4 bit esetében is)

4.      Assembly labor

4.1        Gombok használata:

4.1.1          HW ismeretek: link

ˇ         Gomb 4-0 a PORTG 4-0 lábon van.

ˇ         PING beolvasása:

ˇ         LDS r0, PING  ; Mivel PING, PORTG, DDRG, csak memória utasításokkal érhető el.

4.1.2          Gombnyomásra LED felgyújtás:

4.1.2.1       Fotóként a program:

ˇ        

4.1.2.2       Karakteresen a program:

Hiba esetén kérem, szóljatok a Fórumban

.include "m128def.inc"  ;include fájl a használt processzorhoz

.def LED=r17

.def TMP=r16

 

.org  0

      rjmp    main         ;ugrás a main címkére

.org  70               ;program kezdete a 0x46-as címtől

main:

;LED INIC

      ldi           TMP,0xF0     ;PORTB PORTD irányregisztereibe adat

      out     DDRB,TMP

      out     DDRD,TMP    ;LED-hez kifelé kell irányítani a portok7-4 bitjét

      ldi     TMP,0         ;G port bemenet

      sts     DDRG,TMP ;memória címtartományban van

 

;Gombállapot beolvasása ;A lenyomott gomb 1-et ad a felengedett 0-t

be:   lds     LED,PING ;r16-ba a PING memóriacímről olvasol be adatot

      out     PORTD,LED ;G4 kiírása

      swap    LED           ;G3-0 a LED változó 7-4 bitjére kerül

      out     PORTB,LED ;G3-0 kiirása PORTB7-4-re, tehát LED 3-0 -ra

      rjmp    be            ;Ismétlem a beolvasásokat

 

4.2        LED számláló G0 lenyomásaira:

ˇ         Tanulmányozzuk a LED számláló makró időzítővel: fejezetet.

ˇ         Az inkrementálások közti DELAY makrót cseréljük fel a G0_var makróra.

ˇ         A G0_var makró: a G0 billentyű lenyomását (az élt) figyelje.  
Először várok, amíg fel engedik a billentyűt. (előző lenyomás vége)   
Utána a prell miatt 5-10 msec-ot várok. 
Várok, míg le nem nyomjuk a billentyűt.           
Utána a prell miatt 5-10 msec-ot várok. 
Kész. Megörtént G0 lenyomása, léphet a számláló.

4.2.1          Lenyomást figyelő makró:

G0 lenyomásra megy tovább a program

.macro G0_var              ;vár míg a PING0 (amíg le van nyomva)

 

        ;Ne legyen lenyomva G0. Tehát ha PING0=0, csak akkor megyek tovább

G01:    lds    r0,PING     ;Ha a 0. bit=1, akkor ismételt beolvasás legyen   

        sbrc    r0,0       ;Ha PING0=0, akkor a következő utasítás átugrása. G0 felengedve.       

        rjmp    G01        ;Ha PING0=1, akkor újra beolvas

        PRELL

       

        ;G0 lenyomásra várunk:

G02:    lds    r0,PING     ;Ha a 0. bit 0, akkor ismétlünk, mert G0 nincs lenyomva.

        sbrs    r0,0   

        rjmp    G02

        PRELL

.endmacro

 

 

 

Prell mentesítő makró

.macro PRELL            ;Delay

        ldi  tmp,100    ;r0=0 szlo 15..8 bitje

        eor  r2,r2      ;r2=0 szlo 7..0 bitje

p0:     dec  r2

        brne p0

        dec  tmp

        brne p0         ;r2 már 0. Nem kell nullázni.

.endmacro

 

 

4.2.2          Teljes program:

G0 lenyomás számláló

.include "m128def.inc"      ;include fájl a használt processzorhoz

.def LED=r17

.def TMP=r16

;**********************************************************************

.macro G0_var           ;vár míg a PING0 (amíg le van nyomva)

      ;Ne legyen lenyomva G0. Tehát ha PING0=0, csak akkor megyek tovább

G01:  lds   r0,PING     ;Ha a 0. bit=1, akkor ismételt beolvasás legyen     

      sbrc  r0,0        ;G0 a 0. bitre van kötve           

      rjmp  G01         ;ha 0, akkor PRELL, ha 1, akkor újra beolvas

      PRELL

 

      ;G0 lenyomásra várunk:

G02:  lds   r0,PING     ;Ha a 0. bit 0, akkor ismétlünk

      sbrs  r0,0     

      rjmp  G02

      PRELL

.endmacro;************************************************

 

.macro PRELL

      ldi tmp,100       ;tmp=100 szlo 15-8 bitje

      eor r2,r2         ; r2=  0 szlo  7-0 bitje

p0:   dec  r2           ; r2=0xff

      brne p0

      dec  tmp

      brne p0

.endmacro;************************************************

 

.macro DELAY            ;akkor kell, ha G0-ra indul, G1-re leáll

      ldi tmp,15        ;r0=0 szlo 24-17 bitje

      eor r1,r1         ;r1=0 szló 16- 8 bitje

      eor r2,r2         ;r2=0  szlo 7- 0 bitje

s0:   dec  r2

      brne s0

      dec  r1

      brne s0

      dec  tmp

      brne s0

.endmacro;************************************************

 

.macro LED_Gomb_INIC

      ldi   TMP,0xF0    ;PORTB PORTD irányregisztereibe adat

      out   DDRB,TMP

      out   DDRD,TMP    ;LED-hez kifelé kell irányítani a portok7-4 bitjét

      ldi   TMP,0       ;G prot bemenet

      sts   DDRG,TMP

.endmacro;************************************************

 

.macro LEDOUT

      out   PORTD,LED   ;PORTD7-4 =LED7-4     

                        ;PORTD3-0 bitje közömbös, nincs bekötve

      swap  LED   ;LED7-4 és a LED 3-0 csere

      out   PORTB,LED   ;LED3-0 kigyújtása POTB7-4-tre írással

                        ;(a PORD3-0 és a PORTB3-0 értékei nem látszanak a LED-en)

      swap  LED         ;LED változót eredetire vissza állítottuk

.endmacro;************************************************

 

;RESET****************************************************

      .CSEG

      .org  0

      rjmp  INIC        ;ugrás a INIC címkére

      .org  70          ;program kezdete a 0x46-as címtől     

 

INIC: ;******************************************************

      LED_Gomb_INIC

 

main: ;main címke *****************************************      

      ldi LED,0

ok:   inc LED

      G0_var

      LEDOUT     

      rjmp ok

 

 

 

4.3        Makrók include fájlként használva:

Az előző program átszerkesztve így is kinézhet:

4.3.1          Áttekinthetőség javítása:

ˇ         A makrókat, és a minden programban ismétlődő sorokat tegyük egy külön fájlba.     
A fő programunkban include-val hivatkozzunk rá

ˇ         Célszerű a „makrok2.asm”-et  a projekteket tartalmazó mappába (1-el feljebb, mint a projekt) betenni.

4.3.1.1       Fő program:

ˇ        

ˇ          

4.3.1.2       Makrok2.asm:

ˇ        

ˇ        

4.4        Házi feladatokf:

4.4.1          Időzítéssel megvalósítandó:

ˇ         Futófény 2 LED-el Két szélről befelé indulva

ˇ         Minden LED világít felerősödve-gyengülve.    
Megoldás: változó időkitöltéssel a LED be-ki kapcsolásakor.

4.4.2          G0-G4 –el LED Vezérlése:

ˇ         G0-G3 lenyomásra a gombsorszámnak megfelelő LED világítson, míg le van nyomva

ˇ         G0-G3 lenyomásra a gombsorszámnak megfelelő LED aludon ki, míg le van nyomva

ˇ         G0 lenyomási élre 1-el nő a szlo

ˇ         G0-ra indul a szlo, G4-re megáll.

4.4.3          MENÜ G0-G4-el:

ˇ         G0-G4 lenyomásra gombhoz rendelt program induljon.

4.5        7 szegmenses kijelző használata:

4.5.1          Egy szám kijelzése:

ˇ         Íjuk ki az 1-es 7szegmenses kijelzőre a 3 értéket

4.5.1.1       Algoritmus:

ˇ         DDRA =0xFF (minden bit kifelé)

ˇ         PORTA=0b1 001 0011=1<<7+1<<4+3

4.5.1.2       Program:

A 7 szegmenses 1-es kijelzőre 3 kiírása. (kijelzők 0..3)

      .include "m128def.inc"     

      .def TMP=r16

      .equ SZEGMENS =   1   ;3..0

      .equ BEKAPCS  =   1   ;128 vagy 0x80; 0b_1000_0000 lesz belőle

      .equ ERTEK    =   3

     

;*********************************************************     

      .org  0

main:

      ldi tmp, 0xff       ;PORTA ki                 

      out DDRA,TMP

 

      ldi TMP, ((BEKAPCS<<7)+(SZEGMENS<<4)+(ERTEK))

      out PORTA,TMP

     

ki2:  rjmp ki2

 

 

4.5.2          Időosztásosan a 4321 kijelzése:

ˇ         Írjuk ki a 7 szegmenses kijelzőre az 4321 értéket, mely folyamatosan látható legyen.

4.5.2.1       HW ismeretek : itt

Portbekötés

Funkció

 

PORTA 3…0 bit

Kijelzett érték  0…9

Bináris kód

PORTA 6…4 bit

Kijelző címe 0…3

Kettőspont címe 4

0 a leg jobboldali kijelző

 

PORTA 7 bit

Kigyújtás engedélyezése

1 esetén az 5…4 biten címzett kijelző a 3..0 biten adott értéket jelzi ki, és engedélyezi a kettőspont meghajtását.

ˇ         A 4 kijelzőből csak 1-et tudunk kigyújtani egyszerre. Ha 50 Hz-nél (20 msec) gyorsabb periódusidővel gyújtogatjuk egymás után a kijelzőket, akkor azt szemünk már villogásmentesen folyamatosan látja.

4.5.2.2       SW algoritmus:

ˇ         Végtelen ciklusban ismételve:

ˇ         Ha kb. 4 msec várakozást akarok, akkor 4 Mhz CPU frekvenciánál 1000 periódus kell          .
Ha 1T ciklus=3 óraperiódus, akkor 1000/3=333-at kell leszámolni.     
Ezért a 256 is jó lesz, tehát 1 regiszterrel megoldható az időzítés.       
Ennek a módszernek a hátránya, hogy a processzort az időzítés 100%-ban leköti, s az energiafogyasztás sem takarékos.

 

 

0. címre 1 érték kijelezve

PORTA=1<<7+0<<4+1

delay

 

1. címre 2 érték kijelezve

PORTA=1<<7+1<<4+2

delay

 

2. címre 3 érték kijelezve

PORTA=1<<7+2<<4+3

delay

 

3. címre 4 érték kijelezve

PORTA=1<<7+3<<4+4

delay

 

4. címre a kettőspont

delay

PORTA=1<<7+4<<4

4.5.2.3           Program:

43:21 kiiratása

      .include "m128def.inc"

      .def LED=r17

      .def TMP=r16

     

;**********************************************************

.macro T_256

      eor r2,r2     

p0:   dec  r2

      brne p0

.endmacro;*************************************************

 

.macro PORTA_KI

      ldi            TMP,0xFF            ;G port bemenet

      out            DDRA,TMP

.endmacro;*************************************************

 

;PROGRAM****************************************************

      .org  0

main:                       

      PORTA_KI

ki:   ldi TMP,((1<<7)+(0<<4)+1)

      out PORTA,TMP

      T_256

     

      ldi TMP,((1<<7)+(1<<4)+2)

      out PORTA,TMP

      T_256

     

      ldi TMP,((1<<7)+(2<<4)+3)

      out PORTA,TMP

      T_256

     

      ldi TMP,((1<<7)+(3<<4)+4)

      out PORTA,TMP

      T_256

 

      ldi TMP,((1<<7)+(4<<4)+0)      ;Kettőspont kigyújtása

      out PORTA,TMP

      T_256

      rjmp ki

4.5.3          Paraméterátadással 1234 kijelzése

4.5.3.1       Paraméteres makróval:

Kijelzőre fix érték (1234) paraméteres makróval

      .include "m128def.inc"

      .def TMP=r16

     

;**********************************************************

.macro T_256

      eor  r2,r2      

p0:   dec  r2

      brne p0

.endmacro;*************************************************

 

.macro KIJ

      ldi TMP,low( (1<<7) +(low(@0)<<4)+low(@1))

      out PORTA,TMP

      T_256

.endmacro;*************************************************

 

;RESET, inic **********************************************   

      .org  0

      ldi   TMP,0xFF    ;G prot bemenet

      out   DDRA,TMP

     

;PROGRAM****************************************************

main: KIJ 0,4           ;Ciklusba nem tehető mert MAKRO

      KIJ 1,3

      KIJ 2,2

      KIJ 3,1  

      rjmp main

 

4.5.3.2       Paraméteres szubrutinnal:

ˇ         Ez házi feladat.

5.       Assembly labor

5.1        Hallgatói kérés:

Beszéljek majd erről.

ˇ         A flegek keletkezése. Mi mit jelent.

ˇ         Melyik ugró utasítás mit figyel meg.

ˇ         Az ugrásnál a k+1-nél miért van a +1

5.1.1          Válasz:

ˇ         (helyben a táblánál, de a többi csoport miatt is)

ˇ         Az első labor anyagához bővítettem a kért adatokat

ˇ         Segédfilmet fogok még készítreni hozzá. (2013-10-20)

5.2        Stack-szubrutin:

ˇ         Feladat: SC változóban levő szegmenscímre

ˇ         S_ERTEK változóban levő értéket subrutinnal tegyünk ki.

 

.include "m128def.inc"  ;include fájl a használt processzorhoz

      .def SC=r17      ;Kijelző sorszáma (Segment Counter). 3..0

      .def S_ERTEK=r18 ;7 szegmensen kijelzett érték

      .def TMP=r16

      .org  0

      rjmp  RESET       ;ugrás a RESET címkére

      .org  70          ;program kezdete a 0x46-as címtől 

RESET:;*************************************************

      ldi TMP,low(RAMEND)     ;StacPointer értéke a RAM vége.

      out SPL,TMP

      ldi TMP,high(RAMEND)

      out SPH,TMP

      call SZEGMINIC

MAIN: ;*************************************************

      ldi   sc,3          ;szegmens szló counter

      ldi   S_ERTEK,9     ;szegmens kijelzési érték

      call  SZEGM7

      rjmp  MAIN 

;SUBRUTINOK*********************************************

SZEGMINIC:

        ldi TMP, 255

        out DDRA,TMP      ;Minden bit kifelé

        ret

;*******************************************************

SZEGM7: ldi  TMP,0b_1000_0000      ;eng

        swap SC

        add  TMP,SC        ;Szegmens cím

        swap SC

        add  TMP,S_ERTEK   ;kijelzett érték

        out  PORTA,TMP

        ret

 

5.3        HF:

ˇ         Írjon subrutint 7 szegmensen kijelzésre!

ˇ         Bemenő paraméter 1 regiszter (pl. R0) értéke. 0..255

Segítség a megoldáshoz:

;r0 értékét osszuk el 100-al.

;eredmény s_2 változóban

;maradék az r16 regiszterben legyen

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

;r16=r0, s_2=0;

;while(r16>=100) {s_2++; r16-=100}

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

 

.include "m128def.inc"

.org 0

.def    s_2=r17

        clr s_2

        mov  r16,r0  ;ha nem konstans az osztandó

       ;ldi  r16,223 ;ha konstans az osztandó.

 

BINBCD: cpi  r16,100 ;itt osztó lesz a 100

        brcs TIZES   ;ugrás a Carry flagre, ha set azaz 1-es.

        inc  s_2     ;s_2=egészosztás értéke

        subi r16,100 ;r16=osztás maradéka

        rjmp BINBCD

 

;Házi feladat a BINÁRIS-BCD átalakító folytatása. s_1 a tízesek számát s_0 az egyesek számát tartalmazza!

TIZES:  rjmp TIZES

 

5.4        Memória tömb feltöltése programmal:

5.4.1          Feladat:

ˇ         Foglaljunk le a RAM.ban 10 bájtot a TOMB nevű címkétől.

ˇ         Töltsük fel a tömböt 0…9 értékkel.

5.4.2          SW algoritmusa:

 

Algoritmus

Assemby megvalósítás

1.

RAM foglalás tomb címtől

.DSEG

tomb: .BYTE 10

2. inic

TMP=0

.CSEG

ldi TMP,0

 

Z=tomb   (RAM cím)
(r30, r31 regiszter beállítása)

ldi ZL, low(tomb)
ldi ZH, high(tomb)

3.

(Z+)=TMP

CIKL: st  Z+,TMP

4.

Inc TMP

inc TMP

5.

Ha TMP<10 akkor 3 . -ra.

cpi TMP,10 ;ha TMP=10 akkor Z=1
brne CIKL

6.

Vége. (Ellenőrzés a debuggerrel.)

vege rjmp vege

 

5.4.3          Program:

ˇ        

5.4.4          Futtatás után:

ˇ        

5.5        Memória tömb kiolvasása, kijelzése a 7 szegmenses kijelzőn.kijelzőn.

5.6        Billentyűzetmátrix kezelése:

5.6.1          Bővítő panel Kapcsolási rajz:

ˇ         részlet a rajzból:

ˇ         Sajna ez a rajz így érthetetlen. Nem látszik azonnal. a végén mi melyik portra van kötve.  Még nézegethetünk hozzá egyéb rajzokat, s dokukat.

ˇ         A doku készítője két független panel dokuját írta le. Jogosan nem gondolt rá (?), hogy ezeket jellemzően egybe szerelve használják, mivel mindkettő univerzális felhasználású.

ˇ         Megjegyzés: erős ipari elektromos zajok környezetében, ipari alkalmazás esetén, a bázisok lebegését egy föld felé kötött ellenállással megszüntetném.

5.6.2          Az alappanel kapcsolási rajza:

ˇ         részlet a rajzból:

ˇ        

ˇ         A két független dokuból ezáltal összerakható a bekötés.

5.6.3          Billentyűmátrix vezérlése:

ˇ         PC6..3 (kifelé) sorokat engedi 1 értékre mert a bill lenyomása ekkor nyitja a tranyót. 0-nál szakadás a tranyó EC-a.

ˇ         PC2..0 (befelé) Lenyomott oszlop=0 (mert kinyit a tranyó

5.6.4          Billentyűmátrix kiolvasó algoritmus:

 

char t[]= {1,2,3,4,5,6,7,8,9,10,0,11};

char sor, x, oszlop, ascii;

 

DDRC= 0x78; //PPORTC6-3 ki 2-0 Be.    0b_0111_1000

 

char getch(void) {

    sor=0;

    while(1) {             //lenyomott bill-t keresünk 0…3 sorokban

        PORTC=(1<<(sor+3));//Aktív sor=1. PORTC6..3 biteken. 0b0xxx_x000 (6-3 bit kifelé)

        _delay_ms(50);     //Fesz. szintek terjedéséhez

        x=(~PINC)&7;       //A lenyomott=0 szintet ad (nyitja a tranyót), ezért negálok ~-el.

        if (x) break;      //Találtam 1 db lenyomott billentyűt

        sor++;

        if (sor==4) sor=0;

    }

    oszlop=0;

    while((x=x>>1)) oszlop++;    //oszlop=0,1,2  x=1,2,4 lehetett.

    ascii=t[3*sor+oszlop];       //Ahol t[] ASCII kódokkal egy tömb.

    return(ascii);

}

 

5.6.5          Bill --> LED kiiró algoritmus:

 

char t[]= {1,2,3,4,5,6,7,8,9,10,0,11};

char sor, x, oszlop, ascii;

char getch(void) {

    sor=0;

    while(1) {             //lenyomott bill-t keresünk 0…3 sorokban

        PORTC=(1<<(sor+3));//Aktív sor=1. PORTC6..3 biteken. 0b0xxx_x000 (6-3 bit kifelé)

        _delay_ms(50);     //Fesz. szintek terjedéséhez

        x=(~PINC)&7;       //A lenyomott=0, ezért negálok ~-el.

        if (x) break;      //Találtam 1 db lenyomott billentyűt

        sor++;

        if (sor==4) sor=0;

    }

    oszlop=0;

    while((x=x>>1)) oszlop++;    //oszlop=0,1,2  x=1,2,4 lehetett.

    ascii=t[3*sor+oszlop];       //Ahol t[] ASCII kódokkal egy tömb.

    return(ascii);

}

void led(unsigned char a) {

    PORTD=a;     //7-4 bitek LED-re

    PORTB=a<<4;  //3-0 bitek LED-re

//_delay_ms(800);

}

void hwinic() {

    DDRB= 0xF0; //LED-es Port irány ki.

    DDRD= 0xF0; //LED-es Port irány ki.

    DDRC= 0x78; //PPORTC6-3 ki 2-0 Be. 0b0111 1000

}

int main() {

    hwinic();

    while(1) led(getch());

}

6.      Assembly labor

6.1        Megszakításkezelés:

6.1.1          Működési elv:

ˇ         Program futása, vagy a processzor sleep (alvó állapota) alatt bekövcetkezett esemény HW úton jelzést ad a processzornak.

ˇ         Ez lehet külső (INT 7-0) vagy belső ok. (Lásd a vektorkiosztást)

ˇ         A HW úgy van kialakítva, a         

Ø      megszakítási (interrupt) októl függő címen (ezt hívjuk IT vektornak) folytatódik a program végrehajtás,

Ø      egy call utasításnak megfelelő módon (tehát a megszakított program következő utasításának címe a STACK-be kerül, hogy majd folytatódhasson )

Ø      a globális IT tiltódik. (tehát egy CLI utasítás hatását is végrehajtja a HW)

ˇ         Az aktuális vektorcímről egy rjmp vagy jmp utasítással ugrunk az IT-t kiszolgáló programra. (Rutinra).

ˇ         Mivel nem tudjuk, mikor kezdődik az IT rutin, ezért az általa használt regisztereket PUSH utasítással mentjük kezdéskor, és a RETI utasítás előtt (fordított sorrendben) a POP utasítással visszaállítjuk.

ˇ         A RETI utasítás újra engedélyezi a globális interruptot.          

6.1.2          Vektor kiosztás

IT sorszám.

Program Address

Kérés oka

Magyarázat

1

$0000

RESET

External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset

2

$0002

INT0

External Interrupt Request 0

3

$0004

INT1

External Interrupt Request 1

4

$0006

INT2

External Interrupt Request 2

5

$0008

INT3

External Interrupt Request 3

6

$000A

INT4

External Interrupt Request 4

7

$000C

INT5

External Interrupt Request 5

8

$000E

INT6

External Interrupt Request 6

9

$0010

INT7

External Interrupt Request 7

10

$0012

TIMER2 COMP

Timer/Counter2 Compare Match

11

$0014

TIMER2 OVF

Timer/Counter2 Overflow

12

$0016

TIMER1 CAPT

Timer/Counter1 Capture Event

13

$0018

TIMER1 COMPA

Timer/Counter1 Compare Match A

14

$001A

TIMER1 COMPB

Timer/Counter1 Compare Match B

15

$001C

TIMER1 OVF

Timer/Counter1 Overflow

16

$001E

TIMER0 COMP

Timer/Counter0 Compare Match

17

$0020

TIMER0 OVF

Timer/Counter0 Overflow

18

$0022

SPI, STC

SPI Serial Transfer Complete

19

$0024

USART0, RX

UASRT0, Rx Complete

20

$0026

USART0, UDRE

USART0 Data Register Empty

21

$0028

USART0, TX

USART0, Tx Complete

22

$002A

ADC

ADC Conversion Complete

23

$002C

EE READY

EEPROM Ready

24

$002E

ANALOG COMP

Analog Comparator

25

$0030

TIMER1 COMPC

Timer/Counter1 Compare Match C

26

$0032

TIMER3 CAPT

Timer/Counter3 Capture Event

27

$0034

TIMER3 COMPA

Timer/Counter3 Compare Match A

28

$0036

TIMER3 COMPB

Timer/Counter3 Compare Match B

29

$0038

TIMER3 COMPC

Timer/Counter3 Compare Match C

30

$003A

TIMER3 OVF

Timer/Counter3 Overflow

31

$003C

USART1, RX

USART1, Rx Complete

32

$003E

USART1, UDRE

USART1 Data Register Empty

33

$0040

USART1, TX

USART1, Tx Complete

34

$0042

TWI

Two-wire Serial Interface

35

$0044

SPM READY

Store Program Memory Ready

6.1.3          Assembly IT címek definiálása az "m128def.inc" -ben:

ATMEGA 128 IT veltorok

; ***** INTERRUPT VECTORS ************************************************

.equ INT0addr = 0x0002 ; External Interrupt Request 0

.equ INT1addr = 0x0004 ; External Interrupt Request 1

.equ INT2addr = 0x0006 ; External Interrupt Request 2

.equ INT3addr = 0x0008 ; External Interrupt Request 3

.equ INT4addr = 0x000a ; External Interrupt Request 4

.equ INT5addr = 0x000c ; External Interrupt Request 5

.equ INT6addr = 0x000e ; External Interrupt Request 6

.equ INT7addr = 0x0010 ; External Interrupt Request 7

.equ OC2addr  = 0x0012 ; Timer/Counter2 Compare Match

.equ OVF2addr = 0x0014 ; Timer/Counter2 Overflow

.equ ICP1addr = 0x0016 ; Timer/Counter1 Capture Event

.equ OC1Aaddr = 0x0018 ; Timer/Counter1 Compare Match A

.equ OC1Baddr = 0x001a ; Timer/Counter Compare Match B

.equ OVF1addr = 0x001c ; Timer/Counter1 Overflow

.equ OC0addr  = 0x001e ; Timer/Counter0 Compare Match

.equ OVF0addr = 0x0020 ; Timer/Counter0 Overflow

.equ SPIaddr  = 0x0022 ; SPI Serial Transfer Complete

.equ URXC0addr = 0x0024 ; USART0, Rx Complete

.equ UDRE0addr = 0x0026 ; USART0 Data Register Empty

.equ UTXC0addr = 0x0028 ; USART0, Tx Complete

.equ ADCCaddr = 0x002a ; ADC Conversion Complete

.equ ERDYaddr = 0x002c ; EEPROM Ready

.equ ACIaddr  = 0x002e ; Analog Comparator

.equ OC1Caddr = 0x0030 ; Timer/Counter1 Compare Match C

.equ ICP3addr = 0x0032 ; Timer/Counter3 Capture Event

.equ OC3Aaddr = 0x0034 ; Timer/Counter3 Compare Match A

.equ OC3Baddr = 0x0036 ; Timer/Counter3 Compare Match B

.equ OC3Caddr = 0x0038 ; Timer/Counter3 Compare Match C

.equ OVF3addr = 0x003a ; Timer/Counter3 Overflow

.equ URXC1addr = 0x003c ; USART1, Rx Complete

.equ UDRE1addr = 0x003e ; USART1, Data Register Empty

.equ UTXC1addr = 0x0040 ; USART1, Tx Complete

.equ TWIaddr  = 0x0042 ; 2-wire Serial Interface

.equ SPMRaddr = 0x0044 ; Store Program Memory Read

 

.equ INT_VECTORS_SIZE   = 70 ; size in words

6.2          Időzítők az atmega 128-ban:

6.2.1          Timer 0:

6.2.1.1       Blokkvázlata:

6.2.1.2       I/O regiszterei:

Hivatkozás

Leírás

TCCR0      

Timer/Counter Control Register

TCNT0

Timer/Counter Register. Ez számlál 0..255-ig, ha nem kap előbb resetet

OCR0         

Output Compare Register

Itt adom meg, hol komparásljon, CTC módnál töröljük a TCTN0 értékét

ASSR        

Asynchronus Status Register. (AS0 bit külső órajelet engedélyez)

TIMSK       

Timer/Counter Interrupt Mask Register

TIFR        

Timer/Counter Interrupt Flag register

SFIOR      

Special Function IO Register

Nem kell mindent fejben tartani.  Az elnevezéseket megtaláljuk a fejlesztőrendszerben az I/O ablakban.

ˇ        

Részletesebben:

ˇ        

6.2.1.3       Lehetőségei:

ˇ         Általános 8 bites egy db időzítő / számláló

ˇ         Impulzusszélesség modulátorként is üzemeltethető, ezáltal egy (lassú) 8 bites D/A konverter is megvalósítható vele.

ˇ         Beépített 10 bites előosztó is van benne,            Programozása a         
TCCR0 port címre az alsó 3 bit beállítással: ha 0=stop; 1-7 értéknél az előosztás: 1, 8, 32, 64, 128, 256, 1024.

ˇ         A 255 féle osztás miatt egy programozható frekvenciagenerátorként is használható. 

TCCR0+=8. A komparáláshoz OCR0 beállítandó!

ˇ         IT-t generálhat a TCNT0 számláló túlcsordulásra TOV0 (timer overflow 0)   
  
Háromszögnél: (TCNT=0…255…0)  TCCR0+=64   azaz 1<<6, tehát a 6. bit=1.     
Fűrésznél:         (TCNT=0..255)          TCCR0+=72  tehát a 3. és 6. bit=1.    
TCCR0 a Timer/Counter Control Registert jelenti

ˇ         IT-t generálhat összehasonlításra OC0, A komparáláshoz OCR0 beállítandó!

ˇ         Saját külső rendszertől független órajellel is tud számolni.

6.2.1.4       "m128def.inc" elnevezései:

m128def.inc  definíciói a TIMER0-hoz

; ***** TIMER_COUNTER_0 **************

; TCCR0 - Timer/Counter Control Register*****************************************************************

.equ  TCCR0       = 0x33 ;I/O regiszter. Működési parancsok beállítása.

     ;TCCR0 bitjei:--------------------------------

     .equ        CS00        = 0        ; Clock Select 0

     .equ        CS01        = 1        ; Clock Select 1

     .equ        CS02        = 2        ; Clock Select 2

     ;TCCR0(2-0)=0, akkor nem számlál         =1, nincs előosztás

     ;TCCR0(2-0)=2, akkor 8;            3-32;4-64;5-128;6-256;7-1024 az előosztás

 

     .equ        WGM01       = 3        ; Waveform Generation Mode 1

     .equ        CTC0        = WGM01    ; For compatibility

     .equ        COM00       = 4        ; Compare match Output Mode 0

     .equ        COM01       = 5        ; Compare Match Output Mode 1

     ;COM01:00=00 akkor OC0 láb PB4 portlábként használható

     ;COM01:00=01 akkor komparáláskor OC0 előjelet vált

     ;COM01:00=10 akkor komparáláskor OC0=0 a szlo (TCNT) 0xff-ig megy, törlésnél OC0=1 és TOV0  call 0x20

     ;COM01:00=11 akkor komparáláskor OC0=1 a szlo (TCNT) 0xff-ig megy, törlésnél OC0=0 és TOV0  call 0x20

     .equ        WGM00       = 6        ; Waveform Generation Mode 0

     ;WGM01:00=00 A szló (TCNT0) 0xFF-ig. FŰRÉSZ

     ;        =01 A szló (TCNT0) 0xFF-ig fel, mej 0.ig le. HÁROMSZOG.

     ;        =10 A szló (TCNT0) OCR0-ig mehet fel. (CTC mód)  FŰRÉSZ

     ;            HA az IT engedélyezett, akkor call 0x1E

     ;        =11 A szló (TCNT0) 0xFF-ig. FŰRÉSZ

 

     .equ        PWM0        = WGM00    ; For compatibility

     .equ        FOC0        = 7        ; Force Output Compare. LEGYEN 0 értékű

 

.equ        TCNT0       = 0x32    ;TCNT0 - Timer/Counter Register ;I/O regiszter. 8 bites számláló

.equ        OCR0        = 0x31     ;OCR0 - Output Compare Register I/O regiszter. Komparálási konstans.

 

 

; ASSR - Asynchronus Status Register*********************************************************************

.equ        ASSR         = 0x30      ;I/O regiszter

      ;ASSR bitjei:--------------------------------

     .equ        TCR0UB        = 0        ; Timer/Counter Control Register 0 Update Busy

     .equ        OCR0UB        = 1        ; Output Compare register 0 Busy

     .equ        TCN0UB        = 2        ; Timer/Counter0 Update Busy

     .equ        AS0           = 3        ; Asynchronus Timer/Counter 0 (külső órajel engedélyezése 1-re)

 

 

;Timer/Counter Interrupt Mask Register***********************************************************************

.equ        TIMSK        = 0x37     ; Timer/Counter Interrupt Mask Register I/O regiszter

      ;TIMSK bitjei:--------------------------------

     .equ        TOIE0         = 0        ; Timer/Counter0 Overflow Interrupt Enable (1-re)

     .equ        OCIE0         = 1        ; Timer/Counter0 Output Compare Match Interrupt (1-re)

 

 

; TIFR - Timer/Counter Interrupt Flag register************************************************************

.equ        TIFR        = 0x36      ;I/O regiszter

      ;TIFR bitjei:--------------------------------

     .equ        TOV0        = 0         ; Timer/Counter0 Overflow Flag 0x0020 címre ugrat OVF0addr

     .equ        OCF0        = 1         ; Output Compare          Flag 0x001E címre ugrat OC0addr

 

 

; SFIOR - Special Function IO Register********************************************************************

.equ        SFIOR       = 0x20     ;I/O regiszter

      ;SFIOR bitjei:--------------------------------

     .equ        PSR0        = 1        ; Prescaler Reset Timer/Counter0

     .equ        TSM         = 7        ; Timer/Counter Synchronization Mode Több szló közös indulása

 

6.2.1.5           Működtetése:

Kérdésem: Mi a minimális IT frekvencia a Timer0-val?

ˇ         Háromszög üzemmódban  (TOV0  megszakítás. (0x20 IT kezeléssel) ekkor 1024*512=524288 az osztás     
16 000 000Hz / 524288=30,517578125 Hz. Tehát 15-os SW osztással majdnem 500 msec időköz jöhet létre.        
ezért

ˇ         TCCR0=0b_0100_0111 (háromszög és 1024 előosztó);   

ˇ         TIMSK=1                        hogy az IT engedbve legyen.

6.2.1.6       LED shiftelés balra IT-vel:

30 HZ-es IT vezérelt 0.5 HZ-es LED mozgás

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org OVF0addr      ;Timer0 túlcsordulás IT cím:0x20

        rjmp IDO           ;

 

        .org 70

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND) 

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

        ;LED 7-0 inic---------------------------------------

        ldi r16,0xf0         

        out DDRD, r16        ;LED 7-4

        out DDRB, r16        ;LED 3-0

        ;Timer0 inic----------------------------------------

        ldi r16,0b_0100_0111 ;Osztás: 2*(háromszög)256*(8 bit szlo)1024(előosztó)

        out TCCR0,r16        ;alsó 3 bit az előosztás. 0=stop; 1-7 előosztása: 1,8, 32, 64, 128, 256, 1024

        ldi r16,1

        out TIMSK,r16        ;engedem a szló=0-ra az IT-t

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

        sei                  ;global IT engedélyezése

 

        ldi r17,1

        ldi r16,1

MAIN:   sleep

        rjmp main

             

;SUBRUTINOK  **********************************

;IT rutinok  **********************************

IDO:    dec  r17         ;Az IT-t sw-el még 15-el osztom

        breq OK

        rjmp VEGE

 

OK:     ldi  r17,15       ;minden 15. IT-re fut le

        out  PORTD, r16

        swap r16

        out  PORTB, r16

        swap r16

        rol r16

VEGE:   reti

 

6.2.2          Timer 1:

6.2.3          Timer 2:

6.2.4          Timer 3:

6.3        Soros port kezelése:

6.3.1          USART 0:

6.3.2          USART 1:

6.4        Felkészülés a ZH-ra:

6.4.1          Mintafeladatok:

ˇ         Sándor Tamás feladatai:

6.4.2          ZH alatt használható segédanyagok:

ˇ         Két A4-es oldalra saját kezűleg bármi, de 3 vagy több soros programrészlet tilos.

ˇ         Utasításkészlet (kinyomtatva, vagy elektronikusan a HELP-ből)

ˇ         Panel adatlap PDF fájl.  (kinyomtatva, vagy elektronikusan a helyi hálóról)

6.4.3          Univerzális alapok

Program sablon

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org OVF0addr      ;Timer0 túlcsordulás IT cím:0x20

        rjmp IDO           ;

 

        .org 70

 

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;Nyomógombok inic--------------------------------------

        clr r16

        sts DDRG,r16          ;G4-0 portjának befelé irányítása

 

        ;LED 7-0 inic---------------------------------------

        ldi r16,0xf0         

        out DDRD, r16        ;LED 7-4

        out DDRB, r16        ;LED 3-0

 

        ;Timer0 inic----------------------------------------

        ldi r16,0b_0100_0111 ;Osztás: 2*(háromszög)256*(8 bit szló)1024(előosztó)

        out TCCR0,r16        ;alsó 3 bit az előosztás. 0=stop; 1-7 előosztása: 1, 8, 32, 64, 128, 256, 1024

        ldi r16,1

        out TIMSK,r16        ;engedem a szló=0-ra az IT-t

 

        ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;0xFF

        out DDRA,r16         ;PORTA Minden bit kifelé

       

        ;Bill mártix------------------------------------------

        ldi r16, 0b_0111_1000;Felső sor 3. bit

        out DDRC, r16        ;Első oszlop a 0. bit

       

        ;RGB LED-------------------------------------------

        sbi DDRC,7           ;Piros(vagy Zöld)FIGYELEM! bill. mátrix akaratlanul a DDRC7-et állította!                       

        sbi DDRE,2           ;Kék

        sbi DDRE,3           ;Zöld (vagy Piros)

 

        ;Global IT----------------------------------------

        sei                  ;global IT engedélyezése

;Fő program***************************************************

MAIN:   sleep

        ;call IDO

        rjmp main

       

       

;SUBRUTINOK  **********************************

;IT rutinok  **********************************

IDO:   ;ide írd az IT progit

       reti

 

 

6.4.4          Menürendszer kialakítása

Menü G4-0-al

;Menü G4..0-val.

;Jelezzük ki a 7 segmenses kijelzőn.

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

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;Nyomógombok inic--------------------------------------

        clr r16

        sts DDRG,r16          ;G4-0 portjának befelé irányítása

 

        ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;

        out DDRA,r16         ;PORTA Minden bit kifelé

       

;*************************************************************

MAIN:   lds   r16,PING       ;G4-0 beolvasása

        sbrc  r16,0          ;Ha clear a 0. bit, akkor skip. (kihagyja a köv. utasítást.)

        call  M0           

        sbrc  r16,1

        call  M1

        sbrc  r16,2

        call  M2

        sbrc  r16,3

        call  M3

        sbrc  r16,4

        call  M4

        rjmp  MAIN

 

;SUBRUTINOK****************************************************       

M0:     ldi  r17,0b_1000_0000  ;Kijelzendő érték és hely

        call KIJELZO

        ret

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

M1:     ldi  r17,0b_1001_0001

        call KIJELZO

        ret

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

M2:     ldi  r17,0b_1010_0010

        call KIJELZO

        ret

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

M3:     ldi  r17,0b_1011_0011

        call KIJELZO

        ret

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

M4:     ldi  r17,0b_1011_0100

        call KIJELZO

        ret

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

KIJELZO:out  PORTA,r17

        clr  r17

KIJ2:   dec  r17       

        brne KIJ2

        ret

6.4.5          Egész és maradék osztás:

 

Egész és maradék osztás

;r0 értékét, vagy a 223-at osszuk el 100-al.

;eredmény s_2 változóban

;maradék az r16 regiszterben legyen

;Algoritmus:------------------------------------

;r16=r0, s_2=0;

;while(r16>=100) {s_2++; r16-=100}

 

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

.include "m128def.inc"

.def    s_2=r17

 

.org 0

MAIN:   clr s_2

        ;mov  r16,r0  ;ha nem konstans az osztandó

        ldi  r16,223 ;ha konstans az osztandó.

 

BINBCD: cpi  r16,100 ;itt osztó lesz a 100

        brcs TIZES   ;ugrás a Carry flagre, ha set azaz 1-es.

       ;brmi TIZES    ugras, ha minus lenne az eredmény. azonos a hatása most, a brcs-el

        inc  s_2     ;s_2=egészosztás értéke

        subi r16,100 ;r16=osztás maradéka

        rjmp BINBCD

 

TIZES:  rjmp TIZES

;Házi feladat a BINÁRIS-BCD átalakító folytatása.

;s_1 a tízesek számát s_0 az egyesek számát tartalmazza!

6.4.6          Billentyűmátrix sor olvasás

Adott sor billentyűinek kijelzése 7 szegmenses kijelzőn

;Bill mátrix 3. sorát figyelve  a 7,8,9-et írja a 7szegm. kijelzőre

 

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

 

INIC:   ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;0xFF

        out DDRA,r16         ;PORTA Minden bit kifelé

       

        ;Bill mártix------------------------------------------

        ldi r16, 0b_0111_1000;Felső sor 3. bit

        out DDRC, r16        ;Első oszlop a 0. bit

       

       

MAIN:   ldi r17,0             ;7 szegm sötét

        ldi r18, 0b_0010_0000 ;3. sor figyelése

        out PORTC,r18

        sbis PINC,0

        ldi r17, 0b_1000_0111

        sbis PINC,1

        ldi r17, 0b_1000_1000

        sbis PINC,2

        ldi r17, 0b_1000_1001

 

        out PORTA,r17

        rjmp MAIN

 

6.4.7          Billentyűmátrix oszlop olvasás:

Adott oszlop billentyűinek kijelzése 7 szegmenses kijelzőn

;Bill mátrix 2. oszlopát figyelve  a 2,5,8,0-t írja a 7 szegm. kijelzőre

 

.macro DELAY

        ;ldi r20,2

        clr r21

        clr r22

c1:     dec r22

        brne c1

        dec r21

        brne c1

        ;dec r20

        ;brne c1

.endmacro

 

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

INIC:   ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;0xFF

        out DDRA,r16         ;PORTA Minden bit kifelé

       

        ;Bill mártix------------------------------------------

        ldi r16, 0b_0111_1000;Felső sor 3. bit

        out DDRC, r16        ;Első oszlop a 0. bit

 

;*******************************************************************              

MAIN:   ldi r17,0             ;7 szegm sötét (ha majd PORTA-ra tesszük.

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

        ldi r18, 0b_0000_1000 ;Első sorra 5V. (1 szint)

        out PORTC,r18         ;A jel beállási idejére várni kell. (DELAY)

        DELAY                 ;Ez nagyon fontos, 16000000HZ/65536=244 Hz

                              ;244 Hz 4 msec (nagyságrendileg)

        sbis PINC,1           ;Ha lenyomtam a 2-est, akkor az 1-es bit=0

        ldi r17, 0b_1000_0010 ;kijelzett érték 2 lezs a 7 szegmensesen.

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

        ldi r18, 0b_0001_0000 ;2. sor figyelése

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_0101 ;5

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

        ldi r18, 0b_0010_0000

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_1000 ;8

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

        ldi r18, 0b_0100_0000

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_0000 ;0      

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

        out PORTA,r17

        rjmp MAIN

 

6.4.8          RGB LED

ˇ         AZ RGB (piros=PORTC7, zöld=PORTE2 és kék=PORTE3) bitek 1-be tételekor világítanak, 0-ra sötétek.

ˇ         Először Lásd az Első ZH kidolgozva fejezetet is. Itt csak be – ki kapcsolni kell az RGB 1-1 színét.

ˇ         Színkeverést eltérő időkitöltések kigyújtásával valósíthatunk meg. Például 0-255 skálán szoktuk megadni 1-1-LED fényerejét. (3*8 =24 bites a színmélység)

ˇ         Az időkitöltést megoldhatjuk egy lefelé számlálót figyelve, s adott értéknél a LED-et bekapcsolva, tele értéknél kikapcsolva. 

ˇ         Az ipari megvalósítás jellemzően IT vezérléses. (az IT adja a 256-os szló léptetését.)

6.4.8.1       RGB színkeverés SW számlálóval

24 bites RGB színkeverés SW számlálóval

;RGB LED 24 bites színkeverés R=250, G=100, B=50

;********************************************************************

.equ    LEDR= 250

.equ    LEDG= 100

.equ    LEDB=  50

 

.include "m128def.inc"

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

INIC: ;RGB LED*******************************************************

        sbi DDRC,7           ;Piros(vagy Zöld)FIGYELEM!

        sbi DDRE,2           ;Kék

        sbi DDRE,3           ;Zöld (vagy Piros)

 

;Időzítő szló (ha elhagyjuk, csak az első periódus hibás)------------

        clr r20         ;delay 15-8 bit

        clr r19         ;delay  7-0 bit

 

;Fő rogram: Színkeverés**********************************************

MAIN:   ldi r16, LEDR

        ldi r17, LEDG

        ldi r18, LEDB

 

CIKL:   cbi PORTC,7     ;RGB ledek kikapcsolása

        cbi PORTE,2

        cbi PORTE,3

       

C1:     dec  r19        ;2*256=512 óraperiódus. 16000000/512=31,25usec

        brne PC -1      ;PC-1 miatt elhagyhatom a cimkét a dec 19 elől

          

        cp   r20,r16    ;R LED bekapcsolása, ha a szló elérte LEDR-t

        brne PC +2      ;következő utáni utasításra ugrik, ha nem=

        sbi  PORTC,7

 

        cp   r20,r17    ;G LED bekapcsolása, ha a szló elérte LEDG-t

        brne PC +2

        sbi  PORTE,2

 

        cp   r20,r18    ;B LED bekapcsolása, ha a szló elérte LEDB-t

        brne PC +2

        sbi  PORTE,3

 

        dec  r20

        brne c1         ;15-8 bit szló csökkenése 1-el

 

        rjmp CIKL       ;256*532=136192 T Tehát 117,5 HZ. (8,5 msec)

        ;1 ciklus=8.5 msec. Ezen belül van az impulzusszélesség változtatás.

6.4.8.2           RGB színkeverés IT-vel (interruptal)

ˇ         Villogáselkerülés, szemkímélés miatt kb. 100Hz legyen az időkitöltéses periódus frekvenciája.

ˇ         3*8=24 bites színmélységhez 8 bites SW számláló kell.           
(Az IT csak az időalapot adja, nem a kitöltést, hogy ne használjunk el 3 számlálót, a 3 színhez)

ˇ         8 bit 256 osztás. 100 Hz*256=25,6 KHz körüli időalap (IT frekvencia) kell.

ˇ         A Timer 0 osztása: 16 000 000 Hz / 25 600 Hz = 625.  Ez 8 előosztással és  kb. 78 belső számlálóval érhető el.

ˇ         Ha az IT rutin kiszolgálás átlag 62,5 óraperiódust igényelne, akkor az a szabad processzorkapacitás 10 %-át köti le.

Tehát az IT (interrupt) rutin egy 8 bites SW lefelé számlálóból állhat. (többféle jó megoldás lehetséges.) Annak értékeit figyelve kapcsoljuk a 3 LED-et be, 0 értéknél pedig ki.

24 bites RGB színkeverés IT számlálóval

 

 

6.4.9          Adatmemória írás

 

 

 

6.4.10      Tömb elemeinek Összeadása adatmemóriából

 

 

 

6.4.11      G4-0 lenyomás helyérték kiíratása

G4-0 lenyomás helyérték kiíratása

;PORTG4..0 lenyomott legkisebb helyértékét (A 4-0 ÉRTÉKET)

;helyezzük el az r17 regiszterbe.

;Jelezzük ki a 7segmenses kijelzőn.

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

.include "m128def.inc"

        .DSEG

        .ORG 0x100

HETSEG: .BYTE 1

 

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

 

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;

        out DDRA,r16         ;PORTA Minden bit kifelé

 

        ;Nyomógombok inic--------------------------------------

        clr r16

        sts DDRG,r16          ;G4-0 portjának befelé irányítása

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

 

MAIN:   lds  r16,PING 

        call HELYERTEK

        rjmp main

       

;SUBRUTIN r16 min. lenyomott helyérték kiírása********************************

     ;Algoritmus:---------------------------------------------

     ;if(nincs lenyomva) sötét legyen a kijelző

     ;while(r16 jobbra shift Carry==0) kijelzendő érték növelése

     ;Kiírás

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

HELYERTEK: ; Ha nem nyomok le, akkor sötét segmens kell.

        clr  r17       ;Sötét kijelzőhöz 0

        andi r16, 0b_0001_1111 ;ha nem nyomtunk G-t, r16=0

        breq KIIR      ;nem nyomtunk gombot, 0 az eredmény, akkor sötét.

 

        ldi  r17, 0b_1000_0000 ;engedélyezem a segmens fényét

KOV:    lsr  r16       ;legjobb oldali bit a C-be  

        brcs KIIR

        inc  r17         ;amíg nincs CarryAddíg inc r17

        rjmp KOV

 

KIIR:   out  PORTA,r17 ;0, sötét kijelző

        ret

 

6.4.12      G4-0 lenyomott érték kijelzése

G4-0 lenyomott érték kijelzése

;PORTG4..0 értéket BCD kódba tegyük le a .dseg HETSEGM címtől 2 bájton

;Jelezzük ki a 7 segmenses kijelzőn.

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

 

.include "m128def.inc"

        .DSEG

        .ORG 0x100

HETSEG: .BYTE 2

 

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;Nyomógombok inic--------------------------------------

        clr r16

        sts DDRG,r16          ;G4-0 portjának befelé irányítása

 

        ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;

        out DDRA,r16         ;PORTA Minden bit kifelé

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

 

MAIN:   lds  r16,PING 

        call BINBCD

        call HSEG

        rjmp main

       

;SUBRUTINOK  BINBCD(u8 r16, u8 *HETSEG)**********************************

;Algoritmus: r16 BIN értékét HETSEG címtől elhelyezett BCD bájtokra alakítja, kijelzi-----      

BINBCD: push r17     ;a subrutin ne változtassa meg r17 híváskori értékét

                     ;Bemenő paraméter r16 amit ki kell jelezni

        ldi  ZL,low (HETSEG);Z-t is push -ni lehetne :-)

        ldi  ZH,high(HETSEG)

 

        clr  r17

TIZ:    cpi  r16,10  ;itt osztó lesz a 10

        brcs TVEG    ;while(r16>=10), ha kisebb, (C=1) megyek az TVEG-re

        inc  r17     ;s_2=egészosztás értéke lesz

        subi r16,10  ;r16=osztás maradéka

        rjmp TIZ

 

TVEG:   st   Z+,r17  ;TIZESEK

        st   Z+,r16  ;EGYESEK

        pop  r17

        ret  

 

;HÉTSZEGM************************************************************************************

;HETSEG címtől 2 byte kijelzése.

HSEG:   push r16

        push r17

        ldi  ZL, low(HETSEG)   ;Adattömb kezdőcíme

        ldi  ZH, high(HETSEG)

       

        ldi  r16,0b_1001_0000   ;Számjegy kijelölés

        call HKI                ;Adattömb első elem kijelzése   

        ldi  r16,0b_1000_0000

        call HKI                ;Adattömb 2. elem kijelzése

        pop  r17

        pop  r16

        ret

;megjegyzés: profiként ezt szebben is megoldhatjuk

;***************************************************

HKI:    ld   r17, Z+   ;Z a RAM címe, ahol a kijelzendő van.

        or   r16,r17   ;r16 bemenő paraméter a helyérték címe, engedélyezése

        out  PORTA,r16

        clr  r16

HKI2:   dec  r16        ;256*2 óraperiódus késkektetés. 512/16 usec= 32 usec

        brne HKI2

        ret

;*****************************************************

 

6.4.13      BIN-BCD átalakítás és kijelzése:

1 bájt BIN-BCD átalakítás, kijelzés

;ADAT értéket BCD kódba tegyük le a .dseg HETSEGM címtől 3 bájton

;HETSEG cimtől 3 byte kijelzése a 7segm.-es kijelzőn, Időosztásos delay-vel

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

.equ    ADAT=234

.include "m128def.inc"

        .DSEG        ;********************************

        .ORG 0x100

HETSEG: .BYTE 3      ;A kijelzendő számok tárolása

 

        .CSEG        ;********************************

        .org 0

        rjmp INIC

 

        .org 70

 

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;7 szegmenses kijelző inicializálás-------------------

        ldi r16,255          ;

        out DDRA,r16         ;PORTA Minden bit kifelé

 

MAIN:   call BINBCD

        call HSEG

        rjmp main

       

;SUBRUTINOK*************************************************           

BINBCD: push r17     ;a subrutin ne változtassa meg r17 és r16 híváskori értékét

        push r16

        ldi  r16,low(ADAT);mov r16,r0, ha r0 az ADAT forrása

        ldi  ZL,low (HETSEG);Z-t is push -ni lehetne :-)

        ldi  ZH,high(HETSEG)

 

        clr  r17

SZAZ:   cpi  r16,100 ;itt osztó lesz a 100

        brcs SZVEG   ;ugrás a Carry flagre, ha set azaz 1-es.

        inc  r17     ;s_2=egészosztás értéke

        subi r16,100 ;r16=osztás maradéka

        rjmp SZAZ

 

SZVEG:  st   Z+,r17  ;előszőr a százasokat rakom le.

        clr  r17

TIZ:    cpi  r16,10  ;itt osztó lesz a 10

        brcs TVEG    ;while(r16>=10), ha kisebb, megyek az EGY-re

        inc  r17     ;s_2=egészosztás értéke

        subi r16,10  ;r16=osztás maradéka

        rjmp TIZ

 

TVEG:   st   Z+,r17  ;TIZESEK

        st   Z+,r16  ;EGYESEK

        pop  r16

        pop  r17

        ret  

;HÉTSZEGM************************************************************************************

;HETSEG címtől 3 byte kijelzése.

HSEG:   push r16

        push r17

        ldi  ZL, low(HETSEG)

        ldi  ZH, high(HETSEG)

       

        ldi  r16,0b_1010_0000

        call HKI

        ldi  r16,0b_1001_0000

        call HKI

        ldi  r16,0b_1000_0000

        call HKI

        pop  r17

        pop  r16

        ret

 

;***************************************************

HKI:    ld   r17, Z+

        or   r16,r17

        out  PORTA,r16

        call DELAY

        ret

;*****************************************************

DELAY:  push r16

        clr  r16

DC1:    dec  r16

        brne DC1

        pop  r16

        ret

;******************************************************

 

6.4.14      Első ZH példa kidolgozva:

 

 Készítsen menüt, amelyben a G0-G4-ig levő gombokkal választhatja a megvalósítandó feladatot:

G0: Töltse fel az r2 regiszter 12-vel, az r12 regisztert 3-mal! Abban az esetben, ha r2-ben levő érték maradék nélkül osztható r12-vel, akkor LED-ekre írjon 3 értéket, különben pedig 4 értéket!

G1: Töltse fel az adatmemória 0x50 db bájtját a 0x200-as címtől kezdődően páros számokkal 0x10-től kezdődően!

G2: Adja össze az előző feladatrészben feltöltött terület első 10 bájtján levő értéket szubrutin segítségével, és az összeget írassa ki a LED-ekre!

G3: Olvassa be a billentyűzet mátrix 2-es billentyűzetet tartalmazó oszlopának billentyűjének bármelyikét, és írja ki a hétszegmenses kijelző 0. digitjére!

G4: A gomb lenyomásának idejére világítson a 3 színű LED-en a piros szín!

 

Kérés (fórumban) esetén tartok konzultációt. (min. 4 fő)

.include "m128def.inc"

 

;Makrók******************************************************

.macro DELAY

        ;ldi r20,2

        clr r21

        clr r22

c1:     dec r22

        brne c1

        dec r21

        brne c1

        ;dec r20

        ;brne c1

.endmacro

 

;Reset*******************************************************

        .CSEG

        .org 0

        rjmp INIC

 

        .org 70

 

INIC:   ;SP-t (A 16 bites stack pointert) a RAM végére állítjuk--

        ldi r16,low(RAMEND)

        out SPL,r16

        ldi r16,high(RAMEND)

        out SPH,r16

 

        ;Nyomógombok inic--------------------------------------

        clr r16

        sts DDRG,r16          ;G4-0 portjának befelé irányítása

 

        ;LED 7-0 inic---------------------------------------

        ldi r16,0xf0         

        out DDRD, r16        ;LED 7-4

        out DDRB, r16        ;LED 3-0

 

        ;7 szegmenses kijelzo inicializálás-------------------

        ldi r16,255          ;0xFF

        out DDRA,r16         ;PORTA Minden bit kifelé

        

        ;Bill mártix------------------------------------------

        ldi r16, 0b_0111_1000;Felso sor 3. bi

        out DDRC, r16        ;Elso oszlop a 0. bit

 

        ;RGB LED-------------------------------------------

        sbi DDRC,7           ;Piros(vagy Zöld)FIGYELEM! bill. mátrix akaratlanul a DDRC7-et állította!

        sbi DDRE,2           ;Kék

        sbi DDRE,3           ;Zöld (vagy Piros)

 

;Fo program***************************************************

MAIN:   lds   r16,PING       ;G4-0 beolvasása

        sbrc  r16,0          ;Ha clear a 0. bit, akkor skip. (kihagyja a köv. utasítást.)

        call  M0           

        sbrc  r16,1

        call  M1

        sbrc  r16,2

        call  M2

        sbrc  r16,3

        call  M3

        sbrc  r16,4

        call  M4

        rjmp  MAIN

 

;SUBRUTINOK****************************************************

M0:     ;r2=12 R12=3  ha r2%r12=0 LED=3 egyébként=4

 

        ldi  r17, 12

        mov   r2,r17

        ldi  r17,  3

        mov  r12,r17

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

M0CIKL: cp  r2,r12     ;r2>=r12, akkor legyen kivonás

        brcs M0KI      ;Ugrás ha r2<r12. Ekkor r2-ben 0 vagy a maradék van.

                       ;ugrik M0KI-re, ha 0<=r2<r12

        sub  r2,r12    ;ismételjük a kivinást, míg r2>=r12-vel

                       ;Az osztás eredménye ciklusonként itt növelhető ha kell

        rjmp M0CIKL

       

M0KI:   ldi  r17,3      ;kiirandó a 3,ha maradék nélkül osztható (r2==0)

        and  r2,r2      ;r2-ben itt a maradék van!

      ;ha r2==0, akkor Z flag=1 (osztható volt) skip, tehát ugrik az M0KESZ-re

        BREQ M0KESZ

        ldi  r17,4      ;Nem volt osztható, ezért: Kiirandó a 4, (volt maradék)

M0KESZ: out  PORTD,r17  ;LED-re kiír (felső 4 LED)

        swap r17

        out  PORTB,r17  ;LED-re kiír (alsó 4 LED)              

        ret

 

;**************************************************************

M1:     ;MEM 0x200-tól 0x50 db szám. 0x10-től 2 növekménnyel kiírni a mem-ba.

 

        ldi  ZL,low (0x0200)

        ldi  ZH,high(0x0200)

        ldi  r17,0x50   ;ciklus szló

        ldi  r18,0x10   ;kiírandó kezdő érték

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

M1WR:   st   Z+, r18

        subi r18,-2     ;kivonok -2t olyan, mintha hozzáadnék +2-t. (adi utasítás nincs)

        dec  r17

        brne M1WR

        ret

 

;****************************************************************

M2:     ;LED-re sum M(0x200)-tól 10 byte alsó byte-ját

      

        ldi  ZL,low (0x0200)

        ldi  ZH,high(0x0200)

        ldi  r17,10   ;ciklus szló dec. 10

        ldi  r18,0    ;Az összeg alsó bájtja. (ha kisebb, mint 255, akkor nem kell az r19)

        ldi  r19,0    ;Az összeg (16 bites) felső bájtja

        eor  r0,r0    ;r0=0

        clc           ;carry flag=0

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

M2RD:   ld   r23,Z+     ;r19=M(z); Z++;

        add  r18,r23    ;r18-ban gyűlik az összeg

        adc  r19,r0     ;Ha r18 túlcsordult (carry=1), akkor r19 1-el növelendő 

        dec  r17        ;ciklus szló -1

        brne M2RD       ;Ismétlés, ha r17<>0

        out  PORTD,r18  ;Összeg alsó bájtját LED-re kiíruk (felső 4 bi)t

        swap r18

        out  PORTB,r18  ;Alsó 4 bit

        ret

 

;**************************************************************

M3:     ;bill matrix 2. oszlop figyelése, kijelzése a 7 szegm. kijelzőre

 

        ldi r17,0             ;7 szegm sötét

 

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

        ldi r18, 0b_0000_1000

        out PORTC,r18         ;Bill mátrix 1. sorra 5V. (1 szint)

       

;A jel beállási idejére, de főleg az egyéb sorokban előzőleg bekapcsolt tranyó lezárására várni kell. (DELAY)

        DELAY                 ;Ez nagyon fontos, 16000000HZ/65536=244 Hz

                              ;244 Hz az 4 msec kb.(A tranyó lassan kapcsol ki)

        sbis PINC,1           ;Ha lenyomtam a 2-est, akkor a PINC1-es bit=0

                              ;Skip, ha nem nyomtam 2-est, tehát, ha PINC1 == 1

        ldi r17, 0b_1000_0010 ;kijelzett érték 2 lesz a 7 szegmensesen.

       

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

        ldi r18, 0b_0001_0000 ;2. sor figyelése (5-ös bill)

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_0101 ;5

       

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

        ldi r18, 0b_0010_0000   ;3. sor figyelése (8-as bill)

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_1000 ;8

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

        ldi r18, 0b_0100_0000

        out PORTC,r18

        DELAY

        sbis PINC,1

        ldi r17, 0b_1000_0000 ;0      

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

        out PORTA,r17

        ret

 

;**************************************************************

M4:     ;piros led (3 SZINŰ) világít, ha M4 fut. (amíg nyomjuk a gombot.

        ;tehát a ret előtt ki kell kapcsolni.

        ;sbi PORTC,7     ;Piros LED bekapcs.

 

        sbi PORTE,3     ;Piros LED bekapcs. (panel függő)

        DELAY           ;Világít

        ;cbi PORTC,7    ;Piros LED kikapcsolás

        cbi PORTE,3

        ret