7-Segment-Anzeige mit dem ATmega16

18. November 2011
Einfaches Programm zum Ansprechen einer 7-Segment Anzeige mit dem ATmega16. Es werden in einer Schleife immer die Ziffern 0 - 9 angezeigt. Dabei wird der 8-Bit Timer verwendet. Als Systemtakt habe ich 1MHz eingestellt und das Ganze mit einem Prescale-Wert von 1024 geteilt. Dies sollte ausreichen, um die Darstellung der Ziffern gut verfolgen zu können.
 
.include "m16def.inc"

.def    idx  = r19
.def    zero = r1

.cseg

.org    0x00
        rjmp    start
.org    OVF0addr
        rjmp    isr_timer0


;------------------------------------------------------------------------
; Funktionen
;------------------------------------------------------------------------
init_timer:
    ldi        r16, (1 << CS02) | (1 << CS00) ; Prescale-Wert 1024
    out        TCCR0, r16            ; einstellen

    in         r16, TIFR             ; Hole alle gesetzten Flags
    sbr        r16, 1 << TOV0        ; Timer Overflow Flag auf den
    out        TIFR, r16             ; Wert 1 setzen. Überlauf ...

    in         r16, TIMSK            ; ... soll dann
    ldi        r16, 1 << TOIE0       ; einen Timer Overflow
    out        TIMSK, r16            ; Interrupt auslösen

    sei                              ; Interrupts zulassen

    ret

;------------------------------------------------------------------------
; Hauptprogramm
;------------------------------------------------------------------------
start:
    ldi        r16, LOW(RAMEND)      ; Stack initialisieren
    out        SPL, r16
    ldi        r16, HIGH(RAMEND)
    out        SPH, r16

    in         r16, DDRB
    ori        r16, 0x0F
    out        DDRB, r16

    ldi        r16, 0xFF
    out        DDRC, r16

    out        DDRA, r16

    ldi        r16, 0
    out        PORTC, r16
    out        PORTB, r16

    rcall      init_timer            ; Timer initialisieren

    ldi        idx, 0
    mov        zero, idx

loop:
    nop
    cpi        idx, 10               ; alle digits durchlaufen?
    brne       loop                  ; nein, dann weiter
    ldi        idx, 0                ; ja, dann von vorn anfangen
    rjmp       loop

;------------------------------------------------------------------------
; Interrupt Service Routine
;------------------------------------------------------------------------
isr_timer0:
    push       r16                   ; rette akt. Inhalt von R16 auf Stack
    in         r16, SREG             ; lies akt. Inhalt von SREG ein
    push       r16                   ; und rette diesen auf den Stack

    ldi        ZL, LOW(2 * digits)   ; Indexregister mit der entsprechenden
    ldi        ZH, HIGH(2 * digits)  ; Speicher-Adresse laden

    mov        r16, idx              ; aktuelle digit (Byte) adressieren
    add        r16, idx              ; beachte: wortweise Adressierung

    add        ZL, r16
    adc        ZH, zero

    lpm                              ; Wert an Speicherstelle auslesen

    ldi        r16, 1
    out        PORTB, r16            ; multiplexen (Anzeige 1 ansprechen)
    out        PORTC, r0             ; ... und anzeigen

    out        PORTA, idx            ; LEDS von PortA an

    inc        idx                   ; nächste digit

    pop        r16
    out        SREG, r16
    pop        r16

    reti

;------------------------------------------------------------------------
; Daten im Flash
;------------------------------------------------------------------------
digits:   
    .db 0x3F, 0
    .db 0x06, 0
    .db 0x5B, 0
    .db 0x4F, 0
    .db 0x66, 0
    .db 0x6D, 0
    .db 0x7D, 0
    .db 0x07, 0
    .db 0x7F, 0
    .db 0x6F, 0
 
Mein Development-Board - das EasyAVR5A - wurde von Haus aus schon mit 4 7-Segment Anzeigen ausgeliefert. Es werden die MC-Ports PORTB und PORTC verwendet, um die jeweilige Anzeige (per Time-Multiplexing) anzusprechen. Dabei wird PORTC für das Anzeigen der Ziffer genutzt, während man mittels PORTB die entsprechende 7-Segement Anzeige (aus den 4 Vorhandenen) auswählt.
 
Schema ATmega16 zu 7-Segment Anzeige
 
 
Da ich hier aber nur eine der vorhandenen 7-Segmet Anzeigen nutze, muss aus programmier- technischer Sicht (bzgl. Muliplexen) nichts weiter gemacht werden. Ich verwende im Code die erste 7-Seg.Anz. und schreibe daher den Wert 1 in PORTB. Möglich wären hier auch 2, 4 oder 8 für die 2., 3. bzw. 4. 7-Seg.Anzeige. Dazu soll aber später ein Beispiel folgen.
 
* Die oben gezeigte Abbildung (das Schema) wurde der Dokumentation zum EasyAVR5A entnommen (siehe auch Mikroelektronika).
 
Immer noch kein Kommentar. Jetzt wird's aber mal Zeit!
HILFE
Code-Beispiele werden mit den BBCodes [code][/code] dargestellt. Jedes Tag muss eine Zeile für sich allein haben, d.h der Beispiel-Code muss wirklich ZWISCHEN den Tags stehen. Beispiel:
[code] ACHTUNG! HIER UMBRUCH WICHTIG. TAG [code] MUSS ALLEIN STEHEN
#include <stdio.h>

int main( void ){
    return 0;
} ACHTUNG! HIER UMBRUCH WICHTIG. NACHFOLGENDES TAG [/code] MUSS ALLEIN STEHEN
[/code]

Alles was zwischen den beiden Tags [register] und [/register] eingetragen wird, ist nur für registrierte (und eingeloggte) User sichtbar.
Dein Name *
Deine Email
Deine Website
Vorschau