/*---------------------------------------------*/ /* Jan Dvořák (dvoraj19) ÚT 11:00 (7.12.2008) */ /*---------------------------------------------*/ .include "m169def.inc" .cseg .org 0x0000 jmp start .org 0x000A jmp int_T2 .org 0x0100 .dseg sekundy: .byte 1 ;proměnná pro čítač /pole velikosti 1 .cseg start: .include "znaky.inc" ; soubor se znaky ACII ;vynulování čítače ldi r16, 0 sts sekundy, r16 ;inicializace zasobniku ldi r16, 0x00 out SPL, r16 ldi r16, 0x04 out SPH, r16 ;inicializace displaye call init_disp call smaz_disp ;inicializace čítače cli ; globální zakázání přerušení ldi r16, 0b00001000 sts ASSR, r16 ; vyber hodiny od oscilátoru 32768 Hz ldi r16, 0b00000001 sts TIMSK2, r16 ; povolení přerušení od časovače 2 ldi r16, 0b00000101 sts TCCR2A, r16 ; spuštění čítače s dělícím poměrem 128 (1 s) sei ; povolení přerušení (globální) /*----------------------------------*/ /* Uloha 10 týden */ /*----------------------------------*/ ldi r18, 1 smycka: lds r16, sekundy ;porovnáme jestli na dispplay je stejná hodnota jako v v sekundy cp r18, r16 breq smycka ;skok na začátek, zapisovali bychom stejný udaj mov r18, r16; akuální hodnota call zobraz_cislo jmp smycka end: rjmp end /*----------------------------------*/ /* Obsluha přerušení */ /*----------------------------------*/ int_T2: push r16 in r16, SREG push r16 lds r16, sekundy inc r16 ;vynulování pro větší než 9 cpi r16,10 brlo pres ldi r16, 0 pres: ; sts sekundy, r16 pop r16 out SREG, r16 pop r16 reti /*----------------------------------*/ /* Inicializuj display */ /*----------------------------------*/ init_disp: ldi r16, 0xB7 sts LCDCRB, r16 ldi r16, 0x10 sts LCDFRR, r16 ldi r16, 0x0F sts LCDCCR, r16 ldi r16, 0x80 sts LCDCRA, r16 ret /*----------------------------------*/ /* Smazat display */ /*----------------------------------*/ smaz_disp: push r16 ldi r16,0 ;pozice 1 2 sts LCDDR0, r16 sts LCDDR0 + 5, r16 sts LCDDR0 + 10, r16 sts LCDDR0 + 15, r16 ;pozice 3 4 sts LCDDR1, r16 sts LCDDR1 + 5, r16 sts LCDDR1 + 10, r16 sts LCDDR1 + 15, r16 ;pozice 5 6 sts LCDDR2, r16 sts LCDDR2 + 5, r16 sts LCDDR2 + 10, r16 sts LCDDR2 + 15, r16 ;ostatni segmenty sts LCDDR3, r16 sts LCDDR3 + 5, r16 sts LCDDR3 + 10, r16 sts LCDDR3 + 15, r16 pop r16 ret /*----------------------------------*/ /* Zobrazit znak ASCII */ /*----------------------------------*/ zobraz_znak: ;používám R16-R21, R0,1 R26 R27(X) R30 R31(Z) ;zobrazení znaku: r16 znak; r17 pozice ;pomocné proměné - zachování pvodních v zásobíku push r0 ;operátor mul push r1 push r16 push r17 push r18 push r19 push r20 push r21 push r26 ;X push r27 push r30 ;Z push r31 ;výpočet znaku (4*ASC()-42) subi r16, 42 lsl r16 lsl r16 ;výpočet pozice ;odečteme 1, vydělíme 2 - display po 2 znacích, zjistíme levou - pravou pozici ldi r19,0 ;R19 : levost pravost uložení informace dec r17 lsr r17 ;určení vlevo - v pravo-carry bit při dělení dvěma - liché číslo; brcc preskoc ldi r19, 1 ; informace o pozici segmentu preskoc: ;adresa na display ldi r26,LCDDR0; X registr clr r27 ; jen tak pro jistotu add r26,r17 ;pozice ;načtení znaků - registr Z ldi r30, low(znaky<<1) ldi r31, high(znaky<<1) add r30, r16; přesun na pozici znaku ;provedeme cyklus ve kterém načteme data z druhého segmentu ;a přidáme data nová, posuneme se na další řádek ldi r21, 4; cyklus: ;LCDR ld r18, X; načteme aktuální stav a vynulujeme příslušné byty - horní nebo dolní lpm r20, Z+ ; načteme z registru Z, zvětšíme o 1 - posun na další čtveřici v souboru subi r19, 0; kontrola R19 - jestli byl carry bit v dělení - pravost levost breq neposun posun: ;posun o 4 bity - levý segment lsl r20 lsl r20 lsl r20 lsl r20 ;vynulujem horní byty andi r18, 0b00001111 jmp pokracuj neposun: andi r18, 0b11110000 ;nulujeme spodní byty pokracuj: add r18, r20 mov r0, r18 st X, r0 adiw r26,5 ; posun v registru dec r21 ;správa cyklu brne cyklus; pokračuejem v cyklu dokud r21 není nula ;navrácení hodnot do záobníku registrům pop r31 pop r30 pop r27 pop r26 pop r21 pop r20 pop r19 pop r18 pop r17 pop r16 pop r1 pop r0 ret /*----------------------------------*/ /* Zobraz číslo */ /*----------------------------------*/ zobraz_cislo: ;číslo z regitru R16; další používané R17, R18, R19 ;rozdělíme výpočet na výpočet stovek, desítek a jednotek, pak pomocí ;zobraz znak zobazíme na display (zobrazujeme zprava) push r16 push r17; uchování registrů push r18 push r19 ldi r19, 48 ;posun čísla na hodnotu v tabulce ASCII ASC'0'=48 ;stovky ldi r17, 100 call vydel_cisla ; výsledek v R16, zbytek R17 mov r18, r17 ; uchování zbytku ;mod nezobrazuj nuly, pokud zapoznámkujeme řádky s hvězdičkama, zobrazíme nuly brne mod2a ;*********************** ldi r16, '@' ;*********************** jmp mod2b ;*********************** mod2a: ;*********************** add r16, r19 ; výpočet hodnoty pro zobrazznak (ASCII) mod2b: ;*********************** ldi r17, 4 call zobraz_znak ;desítky ldi r17, 10 mov r16, r18 call vydel_cisla mov r18, r17 ;mod nezobrazuj nuly brne mod2aa ;*********************** ldi r16, '@' ;*********************** jmp mod2ab ;*********************** mod2aa: ;*********************** add r16, r19 ; výpočet hodnoty pro zobrazznak (ASCII) mod2ab: ;*********************** ldi r17, 5 call zobraz_znak ;jednotky mov r16, r18; přesun zbytku po delení 10 ldi r17, 6 add r16, r19 ; výpočet hodnoty pro zobrazznak (ASCII) call zobraz_znak ;navrácení registrům pvodní hodnoty pop r19 pop r18 pop r17 pop r16 ; ret /*----------------------------------*/ /* Vyděl čísla */ /*----------------------------------*/ vydel_cisla: ;číslo z registru 16 čílem z registru 17 ;výsledek: r16, zbytek R17 ;používané registry: R18, R19 push r18 ; uchování v zásobníku push r19; zbytek po deleni ldi r18, 8; 8 bitová čísla - režije cyklu ldi r19, 0 lsl r16 ; posun o byt - vynásobení 2 cyklus_del: rol r19 cp r19, r17 brlo del_preskoc sub r19, r17 del_preskoc: rol r16 dec r18 brne cyklus_del com r16 mov r17, r19 ;promenné ze zásobníku pop r19 pop r18 ; ret