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.
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.

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).
.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.

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:
Alles was zwischen den beiden Tags [register] und [/register] eingetragen wird, ist nur für registrierte (und eingeloggte) User sichtbar.
[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