Code:
.include "TN15def.inc" ; Prozessor ATtiny15
.cseg ; Kennung für Programmcode
.def TMP = R0 ; Allgemeine Variable für Rückgabewerte
.def TMP1 = R16 ; Allgemeine Variable
.def Status = R20 ; Statusregister für Betriebszustände
.def Helligkeit = R21 ; Wert für PWM Regelung
.def KeyOld = R26 ; Taster die gedrückt waren
.def KeyNew = R27 ; Taster die gedrückt sind
.def KeyEnter = R28 ; Taster die neu gedrückt wurden
.def KeyExit = R29 ; Taster die neu losgelassen wurden
.def ZL = R30 ; 16-Bit Variable L-Byte
.def ZH = R31 ; 16-Bit Variable H-Byte
; Status 7 6 5 4 3 2 1 0
; ^- 0=Lampe aus, 1=Lampe an
.org 0x0000 ; Programm Startadresse $0000
rjmp Init ; Einsprung ins Hauptprogramm
.org 0x0001 ; Interrupt Pin 7 (INT0)
rjmp Test ; Sprung zur Testroutine
Init:
; *******************************************************
; * Internen Oszillator kalibrieren *
; *******************************************************
ldi ZL, low (2*Kalibrierung) ; Low-Byte Endadresse Flashspeicher lesen
ldi ZH, high(2*Kalibrierung) ; High-Byte Endadresse Flashspeicher lesen
lpm ; Kalibrierungsbyte auslesen
ser ZL ; $FF in ZL setzen für Vergleich
cpse TMP, ZL ; Kalibrierungsbyte gültig? (Nein, wenn $FF)
out OSCCAL, TMP ; Ja, dann Chip kalibrieren und danach
clr ZL ; den Vergleich löschen.
mov Status, ZL ; Statusregister löschen.
in TMP1, MCUCR ; Controllregister des Prozessors einlesen
sbr TMP1, 1<<ISC00 ; PowerDown-Modus freischalten
out MCUCR, TMP1 ; und speicehrn.
; *******************************************************
; * Ports des ATtiny15 einstellen *
; *******************************************************
ldi TMP1, 1<<DDB4 | 1<<DDB3 | 1<<DDB1 ; Pin 2, 3, 6 auf Ausgabe schalten.
out DDRB, TMP1 ; schalten und entsprechende
com TMP1
out PORTB, TMP1 ; PullUp-Widerstände einschalten.
in TMP1, PORTB ; Aktuellen Portinhalt einlesen und
ori TMP1, 0b011000 ; grüne + rote LED ausschalten
out PORTB, TMP1 ; neuen Zustand ausgeben.
; *******************************************************
; * Interrupts freigeben *
; *******************************************************
in TMP1, GIMSK ; Interrupt an INT0 (Taster Aus/Ein) freigeben
sbr TMP1, 1<<INT0
out GIMSK, TMP1 ; und speichern.
sei ; Interrupts freigeben.
in TMP1, MCUCR
sbr TMP1, 1<<SE | 1<<SM1
out MCUCR, TMP1
; sleep
; >>>>>>> Hauptprogramm Anfang <<<<<<<
Start:
rcall KeyCheck ; Tasten abfragen
cpi KeyExit, 0x04 ; Taste "Ein/Aus" gedrückt $04
brne Weiter1 ; Nein, dann weiter, sonst
rcall PinInt0 ; Sprung nach Ein- Ausschaltroutine
Weiter1:
rjmp Start
; >>>>>>>> Hauptprogramm Ende <<<<<<<<
; >>>>>>>> INTERRUPTPROGRAMME <<<<<<<<
; *******************************************************
; * Testinterrupt um PowerDown-Mode zu beenden *
; *******************************************************
Test:
nop
reti
PinInt0:
; *******************************************************
; * Ein- / Ausschalter $04 an INT0 *
; *******************************************************
cpi Status, 0x00 ; Lampe ausgeschaltet?
breq LampeEin ; Dann Lampe einschalten
cbr Status, 1 ; Ist die Lampe an? Dann Lampe aus und
in TMP1, PORTB
sbr TMP1, 0b001000
out PORTB, TMP1
; in TMP1, MCUCR ; Prozessorcontrollregister auslesen um
; sbr TMP1, 1<<SE | 1<<SM1 ; PowerDown-Mode zu aktivieren
; out MCUCR, TMP1 ; Speichern.
; sleep ; Prozessor in PowerDown-Mode versetzen.
reti ; Rücksprung.
LampeEin:
sbr Status, 1 ; Kennung für Lampe an setzen
; --------- TEST -----------
in TMP1, PORTB
cbr TMP1, 0b001000
out PORTB, TMP1
reti
; >>>>>>>>>> UNTERPROGRAMME <<<<<<<<<<
; *******************************************************
; * Tasterabfrage mit Entprellung *
; *******************************************************
; * Keyenter (R28) = Rückgabe neu gedrückte Taste *
; * Keyexit (R29) = Rückgabe der losgelassenen Taste *
; * Taste an PB0 (Hell/Dunkel) = 01 *
; * Taste an PB2 (Ein/Aus) = 04 *
; *******************************************************
KeyCheck: ; Unterprogramm zur Tastaturabfrage
ldi KeyEnter, 0
ldi KeyExit, 0
in KeyNew, PINB ; Lade PB
com KeyNew ; invertieren
andi KeyNew, 0b000101 ; Maskieren der nicht verwendeten Pins
cpse KeyOld, KeyNew ; Test ob Veränderung
rjmp KeyAction ; Veränderung
ret
; alles gleich
KeyAction:
rcall Wait12ms ; etwas warten
in ZL, PINB ; nochmal einlesen
com ZL ; invertieren bei neg. Logik
andi ZL, 0b000101 ; maskieren der nicht verwendeten Pins
cpse KeyNew, ZL ; ist es stabil
ret ; war nix, da nicht stabil
mov KeyEnter, KeyOld
com KeyEnter ; invertieren
and KeyEnter, KeyNew ; steigende Flanken, !alt & neu
mov KeyExit, KeyNew
com KeyExit ; invertieren
and KeyExit, KeyOld ; fallende Flanken, alt & !neu
mov KeyOld, KeyNew ; alt := neu
ret ; Interrupt verlassen
; *******************************************************
; * Warteschleife mit ca. 12ms *
; *******************************************************
Wait12ms:
ldi ZL, low (2500) ; 16-Bit Zähler mit Startwert laden
ldi ZH, high(2500) ; für Taktfrequenz 1.6MHz
WaitMs1:
dec ZL ; Low-Byte des Zählers erniedrigen
brne WaitMs1 ; wenn 0, dann
dec ZH ; High-Byte des Zählers erniedrigen
brne WaitMs1 ; wenn auch0, dann Warteschleife
ret ; verlassen.
Kalibrierung: .db 0x79 ; Kalibrierungswert für int. Oszillator
.exit
Lesezeichen