Pfad: Home =>
AVR-Übersicht =>
Anwendungen =>
Würfel mit ATtiny13 => Software Assembler
Software für den Würfel mit ATtiny13
;
; **********************************************
; * Animierter Wuerfel mit einem ATtiny13 *
; * Version 1.0 vom Februar 2012 *
; * (C)2012 by http://www.avr-asm-tutorial.net *
; **********************************************
;
.nolist
.include "tn13def.inc"
.list
;
; ================
; Programmablauf
; ================
;
; Timer 0: Prescaler = 64
; Prozessortakt = 1,2 MHz
; CTC-Wert = 6
; OC0A-Interrupt: 3125 Hz, 320 us
; 16-Bit-Counter-Ueberlauf: 21 s
; 8-Bit-Counter-Ueberlauf: 82 ms
; 16-Bit-Counter-High fuer 2 Sekunden: 24
;
; ==========
; Hardware
; ==========
; _____ ______
; /1 \/ 8|
; RESET O--|RES VCC|--O VCC +3V
; | AT |
; L2/L6 O--|PB3 PB2|--O L3/L5
; | tiny |
; Taste O--|PB4 PB1|--O L1/L7
; | 13 |
; GND O--|GND PB0|--O L4
; |______________|
;
; ________________
; | |
; | L1 L5 |
; | |
; | |
; | L2 L4 L6 |
; | |
; | |
; | L3 L7 |
; |________________|
;
; ==================
; Bit-Definitionen
; ==================
;
.equ bL17 = 1<<PortB1 ; Led 1 und 7
.equ bL26 = 1<<PortB3 ; Led 2 und 6
.equ bL35 = 1<<PortB2 ; Led 3 und 5
.equ bL4 = 1<<PortB0 ; Led 4
;
; ============
; Konstanten
; ============
;
; Festkonstanten und Rechenwerte
;
.equ clock = 1200000
.equ cPresc = 64
.equ cCtcA = 5
;
; ==========
; Register
; ==========
;
.def rSreg = R15 ; SREG-Zwischenspeicher
.def rmp = R16 ; Multipurpose Register ausserhalb Int
.def rFlag = R17 ; Flaggenregister
.equ bInp = 0 ; Input Signal gesetzt
.equ bTmb = 1 ; Taumeln aktiv
.equ bTOW = 2 ; warten auf Timeout
.equ bTO = 3 ; Time-Out ist aktiviert
.equ bTmbEn = 4 ; Taumeln ermoeglicht
.equ bRpt = 5 ; Wiederholter Tastendruck
.def rTmb = R18 ; Anzahl Taumler
.def rCnt = R19 ; letzter Wuerfel
.def rCtrL = R24 ; Zaehler fuer Zeiten, LSB
.def rCtrH = R25 ; dto., MSB
;
; ==================
; Interrupttabelle
; ==================
;
Start:
rjmp Main
reti ; INT0
rjmp PinChg ; PCINT0
reti ; TIM0_OVF
reti ; EE_RDY
reti ; ANA_COMP
rjmp Tc0CmpA ; TIM0_COMPA
reti ; TIM0_COMPB
reti ; WDT
reti ; ADC
;
; ============================
; Interrupt Service Routinen
; ============================
;
; Pin Change
;
PinChg:
in rSreg,SREG ; sichere Status-Register
sbic PinB,PinB4 ; check absteigende Flanke
rjmp PinChgRet
sbr rFlag,1<<bInp ; setze Flagge
PinChgRet:
out SREG,rSreg ; stelle Status wieder her
reti
;
; Timer 0 Compare A
;
Tc0CmpA:
in rSreg,SREG ; sichere Status-Register
adiw rCtrL,1 ; aufwaerts zaehlen
brne Tc0CmpARet
sbr rFlag,1<<bTO ; aktiviere Timeout
Tc0CmpARet:
out SREG,rSreg ; stelle Status wieder her
reti
;
; ===========================
; Hauptprogramm Initiierung
; ===========================
;
Main:
ldi rmp, LOW(RAMEND) ; Setze Stapelzeiger
out SPL,rmp
; Init port
ldi rmp,0x0F ; untere Portpins als Ausgang
out DDRB,rmp
ldi rmp,0x10 ; Setze PB4 high, alle LED an
out PORTB,rmp
; init Taster beim Einschalten
ldi rmp,8 ; 3 Sekunden Verzoegerung
Main0:
ldi rCtrH,High(0) ; 65536 Takte Verzoegerung
ldi rCtrL,Low(0)
Main1:
sbiw rCtrL,1 ; herabzaehlen
brne Main1 ; weiter verzoegern
dec rmp
brne Main0
in rFlag,PINB ; setze Flaggen auf Null
cbr rFlag,0xEF ; loesche alles ausser Bit 4
ldi rmp,0x1F ; loesche Lampen
out PORTB,rmp
Main2:
sbis PINB,4 ; warte bis Taste losgelassen
rjmp Main2
; Init external interrupt
ldi rmp,1<<PCINT4 ; external ints an PB4
out PCMSK,rmp
ldi rmp,1<<PCIE ; enable externe ints
out GIMSK,rmp
; Init Timer
ldi rmp,5 ; Timer 0 CTC A auf 6
out OCR0A,rmp
ldi rmp,1<<WGM01 ; CTC OCR0A
out TCCR0A,rmp
ldi rmp,(1<<CS01)|(1<<CS00) ; Prescaler = 64, start timer
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Compare match interrupt
out TIMSK0,rmp
; Sleep mode
ldi rmp,1<<SE
out MCUCR,rmp
sei
;
; ========================
; Hauptprogramm Schleife
; ========================
Loop:
sleep
nop
sbrc rFlag,bTO
rcall TimeOut
sbrc rFlag,bTmb
rjmp Tumble
sbrc rFlag,bInp
rcall Input
rjmp Loop
;
; .equ bInp = 0 ; Input Signal gesetzt
; .equ bTmb = 1 ; Taumeln aktiv
; .equ bTOW = 2 ; warten auf Timeout
; .equ bTO = 3 ; Time-Out ist aktiviert
; .equ bTOn = 4 ; Taumeln ermoeglicht
;
; ================
; Unterprogramme
; ================
;
; Timeout
;
Timeout:
cbr rFlag,1<<bTO ; loesche Flagge
ldi rmp,0x1F ; alle Lampen aus
out PORTB,rmp
ret
;
; Taumeln aktiviert
;
Tumble:
tst rCtrL
brne TumbleEnd
mov rmp,rCtrH ; kopiere MSB Zaehler
andi rmp,0x03 ; 4 Durchlaeufe
brne TumbleEnd
inc rCnt ; naechster Wuerfel
cpi rCnt,6
brcs TumbleNext
clr rCnt
TumbleNext:
ldi ZH,HIGH(2*Tabelle)
ldi ZL,LOW(2*Tabelle)
add ZL,rCnt ; Addiere Tabellenanfang
ldi rmp,0
adc ZH,rmp ; Addiere Ueberlauf
lpm ; lese Byte aus Tabelle
out PORTB,R0
dec rTmb ; noch ein Taumler?
brne TumbleEnd
cbr rFlag,1<<bTmb ; loesche Flagge
TumbleEnd:
rjmp Loop
;
; Input-Taste aktiviert
;
Input:
cbr rFlag,1<<bInp ; loesche Flagge
sbrs rFlag,bRpt ; Wiederholung blockiert?
rjmp Input1
cpi rCtrH,10 ; abgelaufen?
brcc Input1
ret
Input1:
mov rTmb,ZL ; speichere Taumelzaehler
andi rTmb,0x03 ; maximal vier Taumler
inc rTmb ; auf jeden Fall zwei
inc rTmb
clr rCtrH ; loesche Timer
clr rCtrL
in rmp,TCNT0 ; Lese Timer
mov rCnt,rmp ; kopiere fuer Taumeln
ldi ZH,HIGH(2*Tabelle)
ldi ZL,LOW(2*Tabelle)
add ZL,rmp ; Addiere Tabellenanfang
ldi rmp,0
adc ZH,rmp ; Addiere Ueberlauf
lpm ; lese Byte aus Tabelle
out PORTB,R0
sbr rFlag,1<<bRpt ; setze Wiederholflagge
sbrc rFlag,bTmbEn ; Taumelflagge?
sbr rFlag,1<<bTmb
ret
;
; ======================================
; Tabelle mit den Wuerfelkombinationen
; ======================================
;
; Tabellenwerte
;
.equ cL1 = bL4 ; 0 = Led 4
.equ cL2 = bL17 ; 1 = Led 1 und 7
.equ cL3 = bL17 | bL4 ; 2 = Led 1, 4 und 7
.equ cL4 = bL17 | bL35 ; 3 = Led 1, 3, 5 und 7
.equ cL5 = bL17 | bL35 | bL4 ; 4 = Led 1, 3, 4, 5 und 7
.equ cL6 = bL17 | bL26 | bL35 ; 5 = Led 1, 2, 3, 5, 6 und 7
;
; Wuerfeltabelle
;
Tabelle:
.db 0b11111-cL1,0b11111-cL4
.db 0b11111-cL5,0b11111-cL2
.db 0b11111-cL6,0b11111-cL3
.db 0b10000
;
©2012 by http://www.avr-asm-tutorial.net