;Funkuhr-Filter für "spinnende" Funkuhren, hier:
;Modell: Funkwecker Lexor
;Serie: 5436/III/09/05
;Hersteller: NIKA USV GmbH, D-63667 Nidda
;filtert die Wetterdaten aus den Bits 0..15, kürzt diese Impulse auf 100 ms
;070512 Start, Inbetriebnahme, Einbau
;***************************************************************************
;Hardware:
; PB0 (5) = Leitung zum Haupt-Controller (High-aktiv)
; PB1 (6) = Standby-Steuerleitung (High = Standby) = INT0
; PB2 (7) = Leitung vom Funkempfänger (High-aktiv)
; PB3 (2) = Takt 32,768 kHz vom Uhrenquarz (XTAL1)
; PB4 (3) = ungenutzt
; PB5 (1) = Reset, ungenutzt
;Abgesehen von den Konfigurationsbits lief die Firmware auf Anhieb:-)
;Gemessene Ströme:
;Funkuhr selbst: 11 µA (Funkmodul Standby, keine Leuchtfolien-Beleuchtung)
;ATtiny: aktiv: 6,1 µA, Standby-Modus: 0,1 µA
.nolist
.include "tn12def.inc"
.list
.listmac
.def Sekunde = r18 ;Sekundenzähler
.def LastB = r19 ;letzter Zustand von PortB zur Pegelwechsel-Erkennung
.equ CPUCLK = 32768 ;externer Uhrenquarz
.equ T0CLK = CPUCLK/256 ;128 Hz (Timer0-Takt nach Vorteiler 256),
;Überlauf (spätestens) aller 2 s
.cseg
;Für minimale Stromaufnahme läuft das gesamte Programm in ISRs
;********************************************************************
;* Interrupttabelle
;********************************************************************
.org 0 ;Reset-Adresse
rjmp startup
.org INT0addr ;Interrupt wenn INT0 = Low
rjmp ISR_Wake
.org PCI0addr ;Pegelwechsel-Interrupt
rjmp ISR_Funk
.org OVF0Addr ;Interrupt bei Timer0-Überlauf
rjmp ISR_Ovl
.org INT_VECTORS_SIZE ;übrige Vektoren frei halten
.dw (__YEAR__+20)*512+__MONTH__*32+__DAY__ ;FAT-Datum
;********************************************************************
;* ISR Low-Pegel auf INT0 (Aufwecken vom Power-Down)
;********************************************************************
ISR_Wake:
;Retten von SREG und Registern nicht nötig! Hauptprogramm braucht nichts.
ldi r16,0b00100000
out MCUCR,r16 ;Power-Down-Bit löschen
out GIMSK,r16 ;INT0 fortan sperren
in LastB,PinB ;Tatsächlichen Pin-Zustand laden
reti
;********************************************************************
;* ISR Pegelwechsel (Funkuhr-Signal?)
;********************************************************************
ISR_Funk:
in r16,PinB ;Zustand einlesen
eor r16,LastB ;Änderungen?
eor LastB,r16 ;jetzt: LastB = PinB, r16 = Änderungen
sbrs r16,2 ;interessierende Leitung?
reti ;nein, nichts tun!
sbrc LastB,2
rjmp IsHigh
cbi PortB,0 ;Low-Pegel zum Hauptcontroller
reti ;das war's
IsHigh:
sbi PortB,0 ;High-Pegel zum Hauptcontroller
inc Sekunde ;Sekunde mitzählen (Sekunde 0 = 1)
brne Sek_OK
dec Sekunde ;auf 255 begrenzen
Sek_OK: cpi Sekunde,16
brcs PrepShort
;hier: Timer0 programmieren zur Lückenerkennung
ldi r16,-T0CLK*1500/1000 ;-192 = Überlauf nach 1,5 s
out TCNT0,r16
reti
PrepShort: ;hier: Timer0 programmieren zur Impulsverkürzung
ldi r16,-T0CLK*100/1000 ;-12 = Überlauf nach 100 ms
out TCNT0,r16 ;Timer starten
reti
;********************************************************************
;* ISR Timer0-Überlauf (Minuten-Lücke erkennen ODER Impuls verkürzen)
;********************************************************************
ISR_Ovl:
cpi Sekunde,16
brcs MakeShort
clr Sekunde ;Sekundenzähler rücksetzen
reti
MakeShort: ;Zweck des Timers: Pulsverkürzung
cbi PortB,0
reti
;********************************************************************
;* Mikrocontroller-Programmstart
;********************************************************************
startup:
sbi DDRB,0 ;Datenport: Ausgabe für PB0=MOSI, zum Haupt-IC
sbi PortB,3 ;Pull-Up für ungenutzte Anschlüsse
sbi PortB,4 ;(hier unnötig)
ldi r16,0b00000100 ;Timer0-Vorteiler 256, starten
out TCCR0,r16
ldi r16,0b00000010 ;Timer0-Überlauf-Interrupt freigeben
out TIMSK,r16
ldi r16,0b10000000 ;kein Analogvergleicher (Strom sparen)
out ACSR,r16
sei
;********************************************************************
;* Hauptschleife
;********************************************************************
PowerDown:
ldi r17,0b00110000
out MCUCR,r17 ;Power-Down-Bit (für's nächste SLEEP) setzen
ldi r17,0b01000000
out GIMSK,r17 ;INT0 freigeben (einzige Aufweckmöglichkeit)
MainLoop:
sleep ;CPU (oder alles)
sbic PinB,1 ;Standby-Leitung High? (nach Interrupt)
rjmp PowerDown
rjmp MainLoop
Detected encoding: ANSI (CP1252) | 4
|
|