Code:
;********************************************************************
; Netzteil für Kameras, 3V, 4,3V und 6V
;
; MCU: ATtiny11; interner Takt=1MHz
; Version: 1.2
; Entprellroutine im Timer-Interrupt
;
; - Taster-4,3V an PB2 (Pin7)
; - Taster-6V an PB1 (Pin6)
; - Schaltausgang 3V über PB0 (Pin5)
; - Schaltausgang 4,3V über PB3 (Pin2)
; - Schaltausgang 6V über PB4 (Pin3)
;
; - T-Bit fungiert als Merker für Taste entprellt und Zeitablauf
;********************************************************************
;
.nolist
.include "C:\Programme\AVR Tools\AvrAssembler2\Appnotes\tn11def.inc"
.list
;
; Konstanten
.equ key_port = PINB ; Eingabe
.equ t_43v = PB2 ; Taster-4,3V
.equ t_6v = PB1 ; Taster-6V
.equ t_maske = 0b00000110 ; für Tastenmaskierung
.equ schalt_port = PORTB ; Ausgabe
.equ a_3v = PB0 ; Schaltausgang für 3V
.equ LED_default = PB0 ; zugehörige LED
.equ a_43v = PB3 ; Schaltausgang für 4,3V
.equ a_6v = PB4 ; Schaltausgang für 6V
.equ ext_int = 0b00100000 ; Maskierung für PinChange Interrupt
.equ schlafen = 0b00100000 ; Sleep-Modus erlauben
.equ timerwert = 255-15 ; etwa 15ms
.equ zeitlimit = 3 ; 255 x15ms x3 ca.11sek, Zeit für Spannungswahl
.equ zeit_toggle = 3 ; 3x 15ms=45ms, Blinkintervall der 3V-LED
; leuchtet dauernd, wenn Zeit abgelaufen ist
; Register
.def Save = R2 ; wegen fehlendem Stack
.def key_ct0 = R3
.def key_ct1 = R4
.def key_state = R5
.def key_press = R6
.def mp = R16 ; Arbeitsregister
.def merker_t = R17 ; merken,ob Taste gedrückt wurde
.def zeit_L = R18 ; Gesamtzeit
.def zeit_H = R19
.def Blinker = R20 ; Zähler für Blinkintervall
;
; Interruptvektoren
.cseg
rjmp main ; Programmstart
reti ; externer Interrupt für Flankensteuerung
rjmp taste ; Pin change handler
rjmp timer ; Timer0 overflow handler
reti ; Analog Comparator handler
;
;************ Interrupt-Routinen *********************************
taste:
in Save,SREG ; Stack sichern
in merker_t,key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi merker_t, t_maske ; nur Tasten maskieren
ldi mp,0
out GIMSK,mp ; externe Interrupts abschalten; Neuwahl einer
; Spannung ist nur nach Neueinschalten möglich
out SREG,Save ; Stack wieder zurückschreiben
reti
;
timer:
in Save,SREG ; Stack sichern
tst merker_t ; wurde eine Taste gedrückt?
breq weiter ; nein, Entprellung überspringen
;
in mp, key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi mp, t_maske ; nur die Tasten maskieren
com mp ; low active
eor mp, key_state
and key_ct0, mp ; reset counter
and key_ct1, mp
com key_ct0 ; count
eor key_ct1, key_ct0
and mp, key_ct0 ; input AND last counterstate
and mp, key_ct1
eor key_state, mp ; toggle state
and mp, key_state ; 0-1-transition
or key_press, mp ; store key press detect
tst key_press ; Taste schon festgemacht?
breq weiter ; nein, noch eine Runde
com key_press
zeitende:
out SREG,Save
set ; T-Flag setzen und tschüß
rjmp ende
;
weiter:
dec Blinker ; Blinkzeit runterzählen
brne weiter_ ; wenn runtergezählt ist,
ldi Blinker,zeit_toggle ; dann neuladen und LED umschalten
sbis schalt_port,LED_default ; überspringe,wenn LED aus ist
rjmp led_aus
;
cbi schalt_port,LED_default ; LED einschalten
rjmp weiter_
;
led_aus:
sbi schalt_port,LED_default ; LED ausschalten
;
weiter_:
dec zeit_L ; Zeit runterzählen
brne raus ; wenn Nulldurchlauf,
dec zeit_H ; H-Teil runterzählen
breq zeitende ; Zeit abgelaufen
raus:
out SREG,Save ; Stack wieder zurückschreiben
ende:
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
reti
;
;************** Unterprogramme **************************************
;hier wird die gedrückte Taste ermittelt und die entsprechende Spannung
;eingeschaltet. Interrupts werden abgeschaltet
auswerten:
cli ; Interrupt löschen
ldi mp,0 ; Timer abschalten, wird nicht mehr benötigt
out TIMSK,mp
clt ; T-Flag löschen
clc ; zuerst C-Flag löschen
ror key_press ; Merker zwecks Prüfung 1.Taste 2x rollen
ror key_press
brcc u6v ; Bit1 nicht gesetzt? dann auf 6V testen
cbi schalt_port,a_43v ; 4,3V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok ; ... und raus
;
u6v:
ror key_press ; Merker zwecks Prüfung 2.Taste eins weiter
brcc default ; Bit2 nicht gesetzt? dann 3V einschalten
cbi schalt_port,a_6v ; 6V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok
default:
cbi schalt_port,a_3v ; 3V-LED einschalten; sonst nichts
ok:
rjmp loop ; ... und fertig
;
;************** Hauptprogramm ************************************
main:
; es ist kein Softwarestack vorhanden, daher keine Call-Befehle!!!
; Hardware initialisieren
sbi schalt_port,a_3v ; alle Ausgänge ausschalten
sbi schalt_port,a_43v ; H, da alle Transistoren PNP sind!!!
sbi schalt_port,a_6v
sbi DDRB,a_3v ; Pin2,3 und 5 als Ausgang
sbi DDRB,a_43v
sbi DDRB,a_6v
cbi DDRB,t_43v ; PB1 und PB2 als Tastereingänge setzen
cbi DDRB,t_6v
ldi mp,(1<<CS00)|(1<<CS02) ;Teiler=1024 (entspr.etwa 1kHz=1ms)
out TCCR0,mp
ldi mp,timerwert ;Timer vorladen
out TCNT0,mp
ldi mp,1<<TOIE0 ;Timerinterrupt einschalten
out TIMSK,mp
ldi mp,ext_int
out GIMSK,mp ; externe Interrupts ermöglichen
ldi mp,schlafen ; Schlafmodus und Interrupt
out MCUCR,mp ; und ins Controlregister schreiben
clr key_state ;sämtliche Merker der
clr key_press ;Entprellung löschen
clr key_ct0
dec key_ct0
mov key_ct1, key_ct0
ldi zeit_H,zeitlimit ; Gesamtzeit bis Aktivierung festlegen
cbi schalt_port,0 ; Blink-LED einschalten
ldi Blinker,zeit_toggle ; Togglezeit für LED-Blinken
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
sei ; Interrupt global freigeben
;
loop:
sleep ; CPU schlafen legen
brts auswerten ; eine Taste gedrückt; wenn ja,auswerten
rjmp loop ; ... und wieder schlafen ...
;
.exit ; Programmende
edit:
Lesezeichen