;************************************************************************************ ;* Universal Count-Down Timer * ;* ---------------------------- * ;* * ;* Hardware: * ;* Portview-Modul mit AT-Mega8/48 http://www.avr-projekte.de/portview.htm * ;* 5V Summer mit GND an PD2 * ;* evtl. Relais + NPN Treiber und/oder LED an PD3 * ;* Drehgeber mit Taster an PC3/PC4, Taster an PC0 oder ... * ;* 3 Taster an PC0..3. (Enter) PC0, (-) PC1, (+) PC2 * ;* Dezimalpunkt über 120R an PC5 * ;* * ;* Version vom 03.08.2011 * ;* * ;* Autor: J.Woetzel / juergen@avr-projekte.de * ;************************************************************************************ ;.list ;******************************************************************************************************* ;Parameter ;------------------------ #define mega48 ;Einen der beiden AVRs auskommentieren ;#define mega8 ;--------------------------------------------------------------------------------------------------- ;Der CountmS Wert bestimmt wieviele Millisekunden gezählt werden, bis eine Zeiteinheit um ist. ;Beispiele: 1000 = 1 Sekunde Auflösung = max. "9.59" Min. oder "999" Sekunden ;60000 = 1 Minute Auflösung = max. "9.59" Std. ;100 = 0,1 Sek. Auflösung = max. "99.9" Sekunden | 10 = 0,01 Sek. Auflösung = max. "9.99" Sekunden .equ countms = 1000 ;Zeit in Millisekunden. ;--------------------------------------------------------------------------------------------------- .equ overf = 60 ;60 bei "9:59" Minuten oder Stunden. 100 bei "99.9" oder "999" Sekunden .equ korrektur = 0 ;Macht die Uhr ca. Wert*1mS pro Sekunde langsamer, negativ=schneller .equ premin = 0 ;Preset Minuten. Bei Power on .equ presek = 0 ;Preset Sekunden. Dito .equ buzztime = 5 ;Summer: Dauer in 1/2 Sekunden (*512mS) .equ rep_kurz = 25 ;Tastenwiederholung, Verzögerung *2 Millisekunden .set encoder = 0 ;Geschwindigkeit Drehimpulsgeber 0=1/4 (langsam), 1=1/2(mittel), 2=(schnell) .set scroll = 1 ;Spielerei bei Count Down Ende. 0/1 = Aus/Ein ;******************************************************************************************************* #if defined mega48 #include "m48def.inc" #endif ;------------------------------------------------------------------------------------------------------- #if defined mega8 #include "m8def.inc" #endif ;------------------------------------------------------------------------------------------------------- ;Register .def icnt = r0 ;ISR-Zähler für div. Timings .def taste1 = r1 ;Taster .def taste2 = r2 .def taste3 = r3 .def richtung= r4 ;Variable für Drehimpulsgeber .def tick = r5 ;ISR-Zähler für Sekunden .def repeat = r6 ;Zähler für Tastenrepeatfunktion .def sekl = r7 ;16-Bit ISR-Zähler für Millisekunden .def sekh = r8 .def buzz = r9 ;Summer/Zeit .def null = r10 ;Konstanten .def eins = r11 .def sechzig = r12 .def s = r15 ;S-Register .def temp1 = r16 ;Trash .def temp2 = r17 .def enc = r19 ;Drehimpulsgeber .def sek = r20 ;Sekunden .def min = r21 ;Minuten .def seg0 = r22 ;7Seg. Digits, Hunderter .def seg1 = r23 ;Zehner .def seg2 = r24 ;Einer ;R18, X und Y sind (noch) unbenutzt ;---------------------- .def flags = r25 ;Programmflags ;---------------------- ;Die einzelnen Bits .equ enter = 7 ;Tasten (Flanken) .equ up = 6 .equ down = 5 .equ Relais = 3 ;Relais Ein/Aus .equ buzzer = 2 ;Summer Ein/Aus .equ isrx = 1 ;ISR-Flag. 1= Multiplexen / 0= Tasten abfragen ;----------------------- ;************************************************************************************************* ;AVR Sprungvektoren ;************************************************************************************************* .org 0 rjmp reset .org OC1Aaddr rjmp isr ;************************************************************************************************* ;* Presettabelle. ;* -------------- ;* Minuten, Sekunden. Beliebig erweiterbar. ;* Bei Doppelclick auf Start (oder Drehgeberbutton) können die ;* Zeiten mit Up/Down oder Drehgeber rechts/links ausgewählt werden. ;************************************************************************************************* ;Beispiel PreTab: .db 0,50,\ 0,35,\ 2,20,\ 3,15,\ 5,00,\ 0, 0 ;************************************************************************************************* ;ISR, alle 1mS ;************************************************************************************************* ISR:in s,sreg push temp1 ldi temp1,1< ;--------------------- lsr temp1 ;PinC0 (Enter-Taste) ins Carry und in Taste1 schieben rol taste1 ;Ist Taste1=0, war der Taster die letzten 8 ISRs gedrückt. brcc db1 ;Ist eine 1 (nicht gedrückt) im Carry und eine 0 (= 8* gedrückt) brne db1 ;in Taste1, wird das Flankenbit gesetzt. sbr flags,1< mit Repeat ;-------------------- db1:lsr temp1 ;PinC1 (Minus-Taste) ins Carry rol taste2 ;und in Taste schieben brne db2 ;Taste ist 0 wenn die letzten 8 Durchläufe gedrückt war dec repeat ;Repeatzähler-1 brne rp0 ;Wenn Repeatzeit noch nicht abgelaufen, auf neuen Tastendruck testen mov repeat,sechzig ;Repeatwert (kurz) neu laden sec ;Tastenflag durch Repeat setzen rp0:brcc db2 ;Das Carry setzt das Tastenflag durch Repeat oder ersten Tastendruck sbr flags,1< mit Repeat ;-------------------- db2:lsr temp1 ;PinC2 (Plus-Taste) ins Carry ..... rol taste3 ;wie oben brne db3 dec repeat brne rp1 mov repeat,sechzig sec rp1:brcc db3 sbr flags,1<0 cpi enc,0b0100 ;Wird nur assembliert wenn oben encoder auf 1 oder 2 gesetzt wird breq links .endif .if encoder >1 ;dito bei 2 cpi enc,0b1101 breq links cpi enc,0b0010 breq links .endif ;----------------- cpi enc,0b0001 ;rechts breq rechts .if encoder >0 cpi enc,0b0111 breq rechts .endif .if encoder >1 cpi enc,0b1110 breq rechts cpi enc,0b1000 breq rechts .endif rjmp enc1 ;bei allen anderen Kominationen wurde nicht gedreht, rechts: inc richtung rjmp enc1 links: dec richtung ;------------------------------------------------------------------------------------------------- ;Ab hier wieder alle 1 mS ;------------------------------------------------------------------------------------------------- ;---------------------------------- ;Bei "0:00", Relais aus ;---------------------------------- enc1:cp sek,null cpc min,null brne sms cbr flags,1< Variable lpm sek,z cp min,null ;0 = Tabellenende cpc sek,null brne prt4 dec temp2 ;Wenn letzter Tabeintrag, Index-1 rjmp prt1 prt4: push temp2 rcall printtime ;Variable auf Display pop temp2 ;------------------------------ ;Tasten und Drehgeber auswerten ;und entspr. verzweigen ;------------------------------ prt2: sbrc flags,enter rjmp rpm1 ;Bei Enter, Sprung zur Main sbrc flags,up rjmp prt3 ;Nächster Tabeintrag sbrc flags,down rjmp prt5 ;Vorhergehender Tabeintrag tst richtung breq prt2 ;Nix passiert, neue Runde brpl prt3 prt5: dec temp2 ;Index -1 brpl prt1 prt3: inc temp2 ;Index +1 rjmp prt1 rpm1: rcall beep rjmp pm1 ;--------------------------------------------------------------------------------- ;Minuten separat stellen ;--------------------------------------------------------------------------------- m36:cbr flags,1<