Zorbing icon

[TGI] Timer + Segmentanzeige

Zorbing | PRO | 06/21/13 01:50:13 AM UTC | 0 ⭐ | 284 👁️ | Never ⏰ | []
ASM (NASM) |

0 B

|

None

|

0 👍

/

0 👎

.include "m16def.inc"
; =============================================================================
; Interrupt-Vektor-Tabelle
; =============================================================================
.cseg
.org    0x000
    jmp     main
; =============================================================================
; ; Loesung zu 11.2 c ii)
; =============================================================================
.org    0x008
;   jmp     clock_isr               ; im Sekundentakt: Ueberlauf von Timer2
 
; =============================================================================
; Tabelle mit Ziffernansteuerung
; Loesung zu 11.2 a i)
; =============================================================================
; =============================================================================
.org    0x02a
digittab:                           ; Tabelle mit den Ansteuerungsbitmustern:
    .db     0x3f,0x06               ; 0, 1
    .db     0x5b,0x4f               ; 2, 3
    .db     0x66,0x6d               ; 4, 5
    .db     0x7d,0x07               ; 6, 7
    .db     0x7f,0x6f               ; 8, 9
 
; =============================================================================
; Reservierter Speicher fuer Zeitwerte
; =============================================================================
.dseg
.org    0x0100
    seconds:        .byte   1
    minutes:        .byte   1
    hours:          .byte   1
 
; =============================================================================
; Beginn Programmcode
; =============================================================================
.cseg
.org    0x034
 
; =============================================================================
; Loesung zu 11.2 a ii)
; =============================================================================
digitout:
    push    R16
    ldi     ZL,low(digittab*2)      ; lade den
    ldi     ZH,high(digittab*2)     ; entsprechenden
    add     ZL,R17                  ; Tabelleneintrag
    lpm     R17, Z                  ; in R17
    ser     R16                     ; Maske = 0b11111111
    out     DDRA, R16               ; PORTA in Schreibmodus setzen
    out     PORTA, R17              ; R17 auf PORTA ausgeben
    pop     R16
    ret
 
; *****************************************************************************
; *****************************************************************************
; Vorgegebene Unterprogramme
; *****************************************************************************
; *****************************************************************************
 
; INC_SEC
; -------
inc_sec:
    push    R16                     ;Register retten.
    lds     R16,seconds             ;Sekundenwert holen.
    cpi     R16,$59                 ;Bereits $59?
    breq    inc_sec_59              ;Dann Sonderbehandlung.
    inc     R16
    sts     seconds,R16             ;abspeichern.
    jmp     inc_sec_end             ;Das war's.
inc_sec_59:
    clr     R16                     ;Sekunden auf $00
    sts     seconds,R16             ;setzen.
inc_sec_end:
    pop     R16                     ;Register wiederherstellen
    ret
 
; INC_MIN
; -------
inc_min:
    push    R16                     ;Register retten.
    lds     R16,minutes             ;Minutenwert holen.
    cpi     R16,$59                 ;Bereits $59?
    breq    inc_min_59              ;Dann Sonderbehandlung.
    inc     R16
    sts     minutes,R16             ;abspeichern.
    jmp     inc_min_end             ;Das war's.
inc_min_59:
    clr     R16                     ;Minuten auf $00
    sts     minutes,R16             ;setzen.
inc_min_end:
    pop     R16                     ;Register wiederherstellen
    ret
 
; INC_HOURS
; -------
inc_hours:
    push    R16                     ;Register retten.
    lds     R16,hours               ;Stundenwert holen.
    cpi     R16,$23                 ;Bereits $23?
    breq    inc_hours_23            ;Dann Sonderbehandlung.
    inc     R16
    sts     hours,R16               ;abspeichern.
    jmp     inc_hours_end           ;Das war's.
inc_hours_23:
    clr     R16                     ;Stunden auf $00
    sts     hours,R16               ;setzen.
inc_hours_end:
    pop     R16                     ;Register wiederherstellen
    ret
 
; CLOCK_UPDATE
; -------
clock_update:
    push R16                        ;Register retten.
    call inc_sec                    ;Sekunden weiterzaehlen.
    tst R16                         ;Ueberlauf (59 -> 00)?
    brne clock_update_end           ;Nein, dann fertig.
    call inc_min                    ;Sonst Minuten weiterzaehlen.
    tst R16                         ;Ueberlauf (59 -> 00)?
    brne clock_update_end           ;Nein, dann fertig.
    call inc_hours                  ;Sonst Stunden weiterzaehlen.
clock_update_end:
    pop R16                         ;Register wiederherstellen.
    ret
 
; DIV_8U
; -------
div8u:  push    R18
        clr     r15         ;clear remainder and carry
        ldi     r18,9       ;init loop counter
d8u_1:  rol     r16         ;shift left dividend
        dec     r18         ;decrement counter
        brne    d8u_2       ;if done
        pop     R18
        ret                 ;return
d8u_2:  rol     r15         ;shift dividend into remainder
        sub     r15,r17     ;remainder = remainder - divisor
        brcc    d8u_3       ;if result negative
        add     r15,r17     ;restore remainder
        clc                 ;clear carry to be shifted into result
        rjmp    d8u_1       ;else
d8u_3:  sec                 ;set carry to be shifted into result
        rjmp    d8u_1
; *****************************************************************************
; *****************************************************************************
 
; =============================================================================
; Initialisierung
; Loesung zu 11.2 b i)
; =============================================================================
main:
    ldi     R16,low(RAMEND)         ; Stack-
    out     SPL,R16                 ; pointer-
    ldi     R17,high(RAMEND)        ; initiali-
    out     SPH,R17                 ; sierung
    ser     R16                     ; R21 <- 0xFF
    out     DDRB,R16                ; PORTA in Schreibemodus setzen
 
; =============================================================================
; ; Loesung zu 11.2 c i)
; =============================================================================
    ldi     R16,(1<<CS22)|(1<<CS20) ; CLK/128 (Prescale)
    out     TCCR2,R16               ; Modus setzen
    ldi     R16,(1<<TCN2UB)         ; Bit 3 des Asynchronous Status
    out     ASSR, R16               ; Registers setzen (32768Hz-Takt)
    ldi     R16,(1<<TOIE2)          ; Interrupt
    out     TIMSK,R16               ; enablen
 
; =============================================================================
; Initialisierung
; Loesung zu 11.2 b ii)
; =============================================================================
loop:
    lds     R16,seconds             ; Dividend = Sekunden
    ldi     R17,2                   ; Divisor = 2
    call    div8u                   ; Unterprogramm aufrufen und dividieren
    ldi     R18,(1<<PINB0)          ; 0. Anzeigenelement
    
 
    ldi     R18,(1<<PINB4)          ; Anzeigenelement (Doppelpunkt)
    clr     R19                     ; Segmentwert
    cpi     R17,0                   ; bei geraden Sekunden...
    breq    weiter                  ; ... Doppelpunkt nicht aktivieren
    ldi     R19,1                   ; Doppelpunkt an
weiter:
    out     PORTB,R18               ; Doppelpunkt setzen
    out     PORTA,R19               ; ... auf den entsprechenden Wert
;   ... hier jetzt alle einzelnen Anzeigenelemente durchlaufen
;   und auf den jeweiligen Segmentwert setzen...
    rjmp    loop                    ; Schloop
 
; =============================================================================
; Initialisierung
; Loesung zu 11.2 c iii)
; =============================================================================
clock_isr:                          ; jede Sekunde:
    call    clock_update            ; Uhr updaten

Comments