;****** Multiplex7Seg 1.2 (c) Oliver Mezger 15.12.2010
.include "m16def.inc"
;*** Zuordnung zu den Ports ***
.equ SegmentIn = PINA
.equ SegmentOut = PORTA
.equ SegmentDdr = DDRA
.equ TastaturIn = PINB
.equ TastaturOut = PORTB
.equ TastaturDdr = DDRB
.equ StelleIn = PINC
.equ StelleOut = PORTC
.equ StelleDdr = DDRC
.def null = R23 ;Register mit 0
.def tmp = R16 ;tmp-Register zum Arbeiten
.def tmp2 = R17
.def spalte = R18 ;Spalte fuer Darstellung
.def zeichen = R19 ;Index des Zeichens
.def durchlauf = R20;Zaehler fuer Zeichenwechsel
.def itmp = R21 ;tmp-Register fuer Interrupt
.def led = R22 ;RGB-LED animieren
jmp reset ;Einsprung nach Reset
.org OVF0addr ;Einsprung nach Timer0 Ueberlauf
jmp isr_timer ;nach ISR
.org $2a ;folgender Code ab Adresse $2a
isr_timer:
in itmp,SREG ;SREG retten
push itmp
ldi itmp, 150 ;Interrupttimer einstellen
out TCNT0,itmp
cpi spalte,0b00010000 ;wenn nicht Spalte 5
brlo nspalte ;dann naechste Spalte
ldi spalte,1 ;Spalte1 initialisieren
ldi XH, high(anzeige) ;Datenzeiger initialisieren
ldi XL, low(anzeige)
nspalte: ;naechste Spalte
ld itmp,x+ ;lade Wert aus anzeige und erhoehe x
;wandle Wert in 7-Segmentmuster um
ldi ZH, high(bcd_7*2) ;Datenzeiger im Programmspeicher initialisieren
ldi ZL, low(bcd_7*2)
add ZL,itmp ;Addiere Wert um zum Eintrag zu kommen
adc ZH,null
lpm itmp, z ;lade Daten aus Flash-Programmspeicher
out SegmentOut,itmp ;gib 7-Segmentmuster aus
in itmp, StelleOut ;schalte die Stelle ein
andi itmp,0b11110000
or itmp,spalte
out StelleOut,itmp
lsl spalte ;naechste Stelle
pop itmp ;SREG wieder herstellen
out SREG,itmp
reti ;return from Interrupt
reset: ;Hauptprogramm
ldi tmp,high(RAMEND);Oberste RAM-Adresse holen
out SPH, tmp ;Stack-Pointer initialisieren
ldi tmp,low(RAMEND)
out SPL, tmp
ldi tmp,$ff
out SegmentDdr,tmp ;SegmentPort als Ausgang
out StelleDdr,tmp ;StellenPort als Ausgang
ldi tmp,0b11101111 ;Tastatur init
out TastaturOut,tmp
ldi tmp,0b00010000
out TastaturDdr,tmp
ldi tmp,3 ;Systemtakt / 64
out TCCR0,tmp ;Timer setzen
in tmp,TIMSK ;Timerinterrupt einschalten
ori tmp, 1 << TOIE0
out TIMSK,tmp
ldi null,0
ldi XH, high(anzeige) ;Datenzeiger initialisieren
ldi XL, low(anzeige)
st X+,null ;Feld mit 0 initialisieren
st X+,null
st X+,null
st X+,null
sei ;globale Interruptfreigabe
loop: ;Schleife fuer Tastaturabfrage
sbis TastaturIn,0 ;wurde Taste gedrueckt?
rjmp taste
inc led ;Animation der FarbLED
andi led,7 ;nur von 0 bis 7
mov tmp,led
swap tmp ;vertausche Nibble
lsl tmp ;und noch einmal schieben
in tmp2,StelleOut ;schreibe auf StelleOut
andi tmp2,0b00011111
or tmp2,tmp
out StelleOut,tmp2
rcall wait
rjmp loop
taste:
sbis TastaturIn,0 ;Taste immer noch gedrueckt
rjmp taste
rcall zaehle ;wenn losgelassen erhoehe zaehler um 1
rjmp loop
zaehle: ;der Zaehler wird um 1 erhoeht
ldi YH, high(anzeige) ;Datenzeiger initialisieren
ldi YL, low(anzeige)
nextstelle:
ld tmp,y ;lade Stelle
cpi tmp,9 ;ist sie 9?
breq ueberlauf ;Ueberlauf auf naechste Stelle
inc tmp ;sonst erhoehe um 1
st y,tmp
ret
ueberlauf: ;erhoehe naechste Stelle
st y,null
adiw y,1
rjmp nextstelle
wait:
ldi tmp,50 ;aeusseren Zaehler laden 50 ms
wl1:
ldi tmp2,250 ;inneren Zaehler 1ms bei 1Mhz
wl2:
nop
dec tmp2 ;tmp2--
brne wl2 ;Sprung wenn nicht null
dec tmp ;tmp--
brne wl1 ;Sprung wenn nicht null
ret
bcd_7: ;Feld fuer BCD nach 7-Segment Wandlung
.db 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
.dseg; Datenbereich
anzeige: ;Feld fuer die 4 Stellen
.byte 4; Feld mit 4 Byte
|
// Multiplex7seg V 1.0 (c) Oliver Mezger 9.1.2010 #include <avr/io.h> // Definitionen laden #include <util/delay.h> // Delay-Bibliothek laden #include <avr/interrupt.h>
// Zuordnungen zu Ports #define SegmentIn PINA #define SegmentOut PORTA #define SegmentDdr DDRA #define TastaturIn PINB #define TastaturOut PORTB #define TastaturDdr DDRB #define StelleIn PINC #define StelleOut PORTC #define StelleDdr DDRC
const unsigned char bcd_7[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; volatile unsigned char anzeige[4]={0,0,0,0};
ISR(TIMER0_OVF_vect){ static unsigned char spalte=1,dzeiger=0; TCNT0=150; SegmentOut = bcd_7[anzeige[dzeiger++]]; // Segmentmuster ausgeben StelleOut = (StelleOut & 0b11100000) | spalte; // Stelle einschalten spalte *= 2; // naechste Spalte if (dzeiger >3){ spalte = 1; dzeiger = 0; } }
void zaehle(){ // erhoehe Zaehler um 1 unsigned char i; anzeige[0]++; for(i=0;i<3;i++){ if (anzeige[i] > 9){ anzeige[i]=0; anzeige[i+1]++; } } } int main(){ unsigned char led =0; TCCR0 = 3; // Systemtakt / 64 TIMSK |= (1<<TOIE0); // Timerinterrupt frei geben SegmentDdr=0xff; // Ausgang StelleDdr=0xff; // Ausgang TastaturOut = 0b11101111; TastaturDdr = 0b00010000; sei(); // globale Interruptfreigabe while(1){ // Endlosschleife if ((TastaturIn & 1) ==0){ while((TastaturIn & 1) ==0); zaehle(); } led++; led &= 7; StelleOut = (StelleOut & 0b00011111) | (led<<5); _delay_ms(100); // warte 100ms } return 0; }
|