;****** 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;
}
|