Code:
list p=16F876A
; Durch 4 Tasten lässt sich der Countdown einstellen, starten und der controller reseten.
; die zeit wird auf einer 4stelligen sieben segment anzeige angezeigt und runtergezählt.
; in der zeit von Start bis 0 wird ein relais eingeschaltet.
;
;**************************************************************
;* Anzeige : MM:SS
;* Pinbelegung
;* ----------------------------------
;* PORTA: 0 Ziffer1 -----------------------------------------+
;* 1 Ziffer2 -----------------------------+ I
;* 2 Ziffer3 -----------------+ I I
;* 3 Ziffer4 -----+ I I I
;* 4 Eingang I I I I
;* PORTB: 0 Segment B AAAAA AAAAA AAAAA AAAAA
;* 1 Segment F F B F B F B F B
;* 2 Segment A F B F B F B F B
;* 3 Segment G GGGGG GGGGG GGGGG GGGGG
;* 4 Segment H E C E C E C E C
;* 5 Segment C E C E C E C E C
;* 6 Segment E DDDDD HH DDDDD HH DDDDD HH DDDDD HH
;* 7 Segment D
;*
;
; RC0 = Taster (Minuten)
; RC1 = Taster (Sekunden)
; RC2 = Taster (Start)
; RC3 = Ausgang für das Relais
include "P16F876A.inc"
__CONFIG _WDT_OFF & _XT_OSC & _PWRTE_ON
ERRORLEVEL -302 ;SUPPRESS BANK SELECTION MESSAGES
;Variablen und Konstanten werden vereinbart.
W_TEMP equ 0x20 ;rettung beim interrupt
STATUS_TEMP equ 0x21 ;rettung beim interrupt
PCLATH_TEMP equ 0x22 ;rettung beim interrupt
MinZehner equ 0x23
MinEiner equ 0x24
SekZehner equ 0x25
SekEiner equ 0x26
Digit equ 0x27 ;bei welcher ziffer sind wir?
help equ 0x28
Startsignal equ 0x29 ;steht hier eine 1, ist das das startsignal
Timer equ 0x30 ;zählt bis 50 um den takt von 50hz auf 1hz zu verringern
#define MinTaste PORTC, 0
#define SekTaste PORTC, 1
#define StartTaste PORTC, 2
#define Relais PORTC, 3
org 0x00 ;Startadresse nach Reset ist 0 hier startet der PIC
goto main ;Sprung zum Hauptprogramm
org 0x04 ;Interruptvector ist 0x04,
intvec
bcf INTCON, GIE ;interrupts nicht erlaubt
movwf W_TEMP ;w, status und pclath retten.
swapf STATUS,W
clrf STATUS
movwf STATUS_TEMP
movfw PCLATH
movwf PCLATH_TEMP
movlw D'131'
movwf TMR0
int_service
bcf TRISA,0 ;Schaltet Ziffer1 aus
bcf TRISA,1 ;Schaltet Ziffer2 aus
bcf TRISA,2 ;Schaltet Ziffer3 aus
bcf TRISA,3 ;Schaltat Ziffer4 aus
decf Digit,f
bz int_0
movfw Digit
movwf help
decf help,f
bz int_1
decf help,f
bz int_2
decf help,f
bz int_3
goto int_4
int_0
movlw D'5'
movwf Digit
btfss Startsignal, 0
goto int_end
bsf Relais
decf Timer,f ;ist es der 50ste durchgang diese sekunde?
btfss STATUS,Z
goto int_end
movlw D'50' ;dann füll Timer wieder auf 50 auf
movwf Timer
decf SekEiner,f ;reduziere SekEiner um eine Sekunde
movlw D'255' ;überprüfe ob die zelle unter null springt
subwf SekEiner,w
bnz int_end ;wenn nicht, dann gehts normal weiter
movlw D'9' ;wenn doch, schreib 9 in die SekEiner
movwf SekEiner
decf SekZehner,f ;und verringer Sekzehner
movlw D'255' ;es wird geprüft ob 255 in SekZehner steht
subwf SekZehner,w
bnz int_end ;wenn SekZehner nicht 255, gehts weiter, sonst
movlw D'5' ;wird SekZehner auf 5 gesetzt
movwf SekZehner
decf MinEiner,f ;und MinEiner um 1 reduziert
movlw D'255' ;es wird geprüft ob 255 in MinEiner steht
subwf MinEiner,w
bnz int_end ;wenn nicht geht es weiter, sonst
movlw D'9' ;wird MinEiner auf 9 gesetzt
movwf MinEiner
decf MinZehner,f ;und MinZehner um einen gesengt
goto int_end ;weiter gehts
int_1
movfw SekEiner
call Segmente
movwf PORTB
bsf PORTA, 0
goto int_end
int_2
movfw SekZehner
call Segmente
movwf PORTB
bsf PORTA, 1
goto int_end
int_3
movfw MinEiner
call Segmente
movwf PORTB
bsf PORTA, 2
goto int_end
int_4
movfw MinZehner
call Segmente
movwf PORTB
bsf PORTA,3
goto int_end
; 7-Segment-Tabelle
Segmente
addwf PCL, f
retlw B'00011000' ; 0
retlw B'11011110' ; 1
retlw B'00110010' ; 2
retlw B'01010010' ; 3
retlw B'11010100' ; 4
retlw B'01010001' ; 5
retlw B'00010001' ; 6
retlw B'11011010' ; 7
retlw B'00010000' ; 8
retlw B'01010000' ; 9
int_end
movfw SekEiner ;hier wird überprüft, ob der Zählerstand auf null ist.
iorwf SekZehner, 0
iorwf MinEiner, 0
iorwf MinZehner, 0
btfss STATUS,Z ; wenn ja, dann
goto int_end
bcf Relais ;wird das relais abgeschaltet
bcf Startsignal, 0 ;und das Startsignal gelöscht
movfw PCLATH_TEMP
movwf PCLATH
swapf STATUS_TEMP,W
movwf STATUS
swapf W_TEMP,F
swapf W_TEMP,W
bcf INTCON,T0IF
bsf INTCON, GIE
retfie
;hier muß die Interruptbehandlungsroutine stehen,
;falls Interrupts genutzt werden sollen
;die Grundeinstellungen werden vorgenommen
main
bsf STATUS, RP0
movlw B'110'
movwf ADCON1 ;PortA von Analog auf digital
clrf TRISA ;PortA ist Ausgang
clrf TRISB ;PortB ist Ausgang
movlw B'11110111' ;RC3 ist Ausgang, rest Eingang
movwf TRISC
movlw B'10010100' ;Timer0 bekommt den Vorteiler 32
movwf OPTION_REG
bcf STATUS, RP0
movlw D'131'
movwf TMR0
bsf INTCON, T0IE
bsf INTCON, GIE
; Zeit 0 einstellen
clrf SekEiner
clrf SekZehner
clrf MinEiner
clrf MinZehner
movlw 5
movwf Digit ; Ziffernzähler einstellen
movlw 50
movwf Timer
Einstellen
btfss MinTaste ;Minutentaste gedrückt?
call MinPlus ;dann geh nach MinPlus
btfss SekTaste ;Sekundentaste gedrückt?
call SekPlus ;dann geh nach Sekplus
btfss StartTaste ;StartTaste gedrückt?
call Start ;dann geh nach Start
goto Einstellen ;nichts gedrückt? dann frag nochmal ab.
SekPlus
incf SekEiner,f ;erhöhe SekEiner
movlw D'10' ;Subtrahiere 10 von SekEiner
subwf SekEiner, 0
bz SekEinerVoll ;wenn also SekEiner =10 geh nach SekEinerVoll
return
SekEinerVoll
clrf SekEiner ;setze SekEiner auf 0
incf SekZehner,f ;erhöhe SekZehner
movlw D'6' ;subtrahiere 6 von SekZehner
subwf SekZehner, 0
bz SekMinVerschieben ;wenn SekZehner = 6 geh nach SekMinVerschieben
return
SekMinVerschieben
clrf SekZehner ;setze SekZehner auf 0
incf MinEiner,f ;erhöhe MinEiner um 1
return
MinPlus
incf MinEiner,f ;erhöhe MinEiner
movlw D'10' ;subtrahiere 10 von MinEiner
subwf MinEiner, 0
bz MinEinerVoll ;wenn MinEiner = 10 geh nach MinEinerVoll
return
MinEinerVoll
clrf MinEiner ;setze MinEiner auf 0
incf MinZehner,f ;erhöhe MinZehner um 1
return
Start
bsf Startsignal, 0
return
end ;das Ende des Programms
Lesezeichen