-
ok, hier ist der quellcode meiner finalversion. sollte klappen. die zeit ist gringfügig ungenau, mal sehen obs mit nem oscillator oder quarz besser geht, aber der fehler ist erstmal erträglich
Code:
list p=16f876a
;**************************************************************
;*
;* Pinbelegung
;* ----------------------------------
;* PORTA: 0 Ziffer -----------------------------------------+
;* 1 Ziffer -----------------------------+ I
;* 2 Ziffer -----------------+ I I
;* 3 Ziffer -----+ 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
;* PORTC: 0 MinutenTaster
;* 1 SekundenTaster
;* 2 StartTaster
;* 3 Relais
;**************************************************************
;
; Timer mit Schaltausgang, der aktiviert ist, solange gezählt wird
; Tasten für Minuteneinstellung, Sekundeneinstellung, Start und Reset.
; Timer läuft die eingestellte Zeit von max 99min.59sek rückwärts runter.
; 4Mhz Taktquelle
;
; basierend auf sprut's stoppuhr
;
;
;
;**************************************************************
; Includedatei für den 16F84 einbinden
#include <P16f876a.INC>
; Konstanten
__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF & _LVP_OFF
DP Equ 4 ; Position des Dezimalpunkts in PORTB
; Variablennamen vergeben
w_copy Equ 0x20 ; Backup für Akkuregister
s_copy Equ 0x21 ; Backup für Statusregister
Ziffer1 Equ 0x22 ; Wert des LSD
Ziffer2 Equ 0x23 ; Wert der zweitkleinsten Stelle
Ziffer3 Equ 0x24 ; Wert der zweitgrößten Stelle
Ziffer4 Equ 0x25 ; Wert des MSD
Digit Equ 0x26 ; Ziffernzähler
ar Equ 0x27
Timer2 Equ 0x28 ; Vorteiler von 50 Hz auf 10 Hz
StartSignal Equ 0x29
Wait1 equ 0x30
Wait2 equ 0x31
Zehntel equ 0x32 ;zehntelsekunden, die nicht angezeigt werden
;**************************************************************
; los gehts mit dem Programm
org 0
goto Init
;**************************************************************
; die Interuptserviceroutine
org 4
intvec
bcf INTCON, GIE ; disable Interupt
movwf w_copy ; w retten
swapf STATUS, w ; STATUS retten
movwf s_copy ;
movlw D'131' ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz)
movwf TMR0
; Intrupt servic routine
Int_serv
bcf PORTA, 0 ; Ziffer1 aus
bcf PORTA, 1 ; Ziffer2 aus
bcf PORTA, 2 ; Ziffer3 aus
bcf PORTA, 3 ; Ziffer4 aus
decf Digit,f ; Ziffernzähler verringern
;Digit=4: anzeigen Ziffer 4
;Digit=3: anzeigen Ziffer 3
;Digit=2: anzeigen Ziffer 2
;Digit=1: anzeigen Ziffer 1
;Digit=0: andere Aktionen, keine Anzeige
btfsc STATUS, Z
goto Int_0 ; Z-Flag=1 ergo Digit=0
movfw Digit
movwf ar
decf ar, f
btfsc STATUS, Z
goto Int_1 ; Digit=1
decf ar, f
btfsc STATUS, Z
goto Int_2 ; Digit=2
decf ar, f
btfsc STATUS, Z
goto Int_3 ; Digit=3
goto Int_4 ; Digit=4
Int_0
movlw 5
movwf Digit
btfss StartSignal, 0
goto Int_end ; ist start freigegeben?
bsf PORTC, 3 ;relais aktivieren
decf Timer2, f ; von 5 bis 0 zählen (50 Hz / 5 = 10 Hz)
btfss STATUS, Z
goto Int_end ; Timer2 <> 0
movlw 5
movwf Timer2 ;zähl die Zehntelsekunden
decf Zehntel, f
movlw D'255'
subwf Zehntel, w ;überprüf ob die ziffer überlief
btfss STATUS, Z
goto Int_end
movlw D'9'
movwf Zehntel
decf Ziffer1, f ; Sekunden erhöhen
movlw D'255'
subwf Ziffer1, w
btfss STATUS, Z
goto Int_end ; Sekunden <> 10
movlw D'9'
movwf Ziffer1
decf Ziffer2, f ; ZehnerSekunden erhöhen
movlw D'255'
subwf Ziffer2, w
btfss STATUS, Z
goto Int_end ; Zehner Sekunden <> 10
movlw D'5'
movwf Ziffer2
decf Ziffer3, f ; EinerMinuten erhöhen
movlw D'255'
subwf Ziffer3, w
btfss STATUS, Z
goto Int_end ; EinerMinuten <> 255
movlw D'9'
movwf Ziffer3
decf Ziffer4, f ; 10er Minuten erhöhen
movlw D'255'
subwf Ziffer4, w
btfss STATUS, Z
goto Int_end ; 10er Minuten <> 10
movlw D'9'
movwf Ziffer4
goto Int_end
Int_1
movfw Ziffer1 ; Wert der 1. Ziffer
call Segmente
movwf PORTB ; Segmente einschalten
bsf PORTA, 0 ; 1. Ziffer einschalten
goto Int_end
Int_2
movfw Ziffer2 ; Wert der 2. Ziffer
call Segmente
movwf PORTB ; Segmente einschalten
bsf PORTA, 1 ; 2. Ziffer einschalten
goto Int_end
Int_3
movfw Ziffer3 ; Wert der 3. Ziffer
call Segmente
movwf PORTB ; Segmente einschalten
bcf PORTB, DP ; Dezimalpunkt ein
bsf PORTA, 2 ; 3. Ziffer einschalten
goto Int_end
Int_4
movfw Ziffer4 ; Wert der 4. Ziffer
call Segmente
movwf PORTB ; Segmente einschalten
bsf PORTA, 3 ; 4. Ziffer einschalten
goto Int_end
Int_end
movfw Ziffer1 ;Ziffer 1-4 werden logisch inklusic-or verknüpft
iorwf Ziffer2, w
iorwf Ziffer3, w
iorwf Ziffer4, w
btfsc STATUS, Z ;falls dabei 0 rauskomt, ist der zählerstand 00.00
call Nullzeit
swapf s_copy, w ; STATUS zurück
movwf STATUS
swapf w_copy, f ; w zurück mit flags
swapf w_copy, w
bcf INTCON, T0IF ; Interupt-Flag löschen
bsf INTCON, GIE ; enable Interupt
retfie
Nullzeit
bcf StartSignal, 0 ;Stoppe den Zählvorgang
bcf PORTC, 3 ;Schalte das Relais ab
return
; 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
;**************************************************************
; Port A/B auf Ausgabe stellen
Init
bsf STATUS, RP0 ; auf Bank 1 umschalten
movlw B'11110000' ; PortA RA0-RA3 output
movwf TRISA
movlw B'00000000' ; PortB alle output
movwf TRISB
movlw B'11110111' ;PortC eingang ausser RC3
movwf TRISC
bcf STATUS, RP0 ; auf Bank 0 zurückschalten
movlw 5
movwf Digit ; Ziffernzähler einstellen
; 250 Hz-Timer-Interupt einstellen
bsf STATUS, RP0 ; auf Bank 1 umschalten
movlw B'10000100' ; internen Takt zählen, Vorteiler zum Timer0, 32:1
movwf OPTION_REG
movlw D'131' ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz)
bcf STATUS, RP0 ; auf Bank 0 zurückschalten
movwf TMR0
movlw 5
movwf Timer2 ; 50Hz -> 10 Hz Teiler
;ausgangszustand
clrf StartSignal
clrf Ziffer1
clrf Ziffer2
clrf Ziffer3
clrf Ziffer4
clrf Zehntel
bcf PORTC, 3
bsf INTCON, T0IE ; Timer0 interupt erlauben
bsf INTCON, GIE ; Interupt erlauben
loop
btfss PORTC, 1
call SekundenTaste
btfss PORTC, 0
call MinutenTaste
btfss PORTC, 2
call StartTaste
goto loop ; eine Endlosschleife, die die Tasten abfragt
StartTaste
bsf StartSignal,0 ;setzte das Startsignal
return
SekundenTaste
call Wait
btfss PORTC, 1
goto SekundenTaste
call Wait
btfss PORTC, 1
goto SekundenTaste
call Wait ;entprellen
incf Ziffer1, f ;EinerSekunden erhöhen, falls größer 9 erfolgt ein übertrag auf ziffer 2
movlw D'10'
subwf Ziffer1, w
btfss STATUS, Z
return
clrf Ziffer1
incf Ziffer2, f
movlw D'6'
subwf Ziffer2, w
btfss STATUS, Z
return
clrf Ziffer2
return
MinutenTaste
call Wait
btfss PORTC, 0
goto MinutenTaste
call Wait
btfss PORTC, 0
goto MinutenTaste
call Wait ;entprellen
incf Ziffer3, f ;EinerMinuten erhöhen, falls größer 9 erfolgt übertrag auf ziffer4
movlw D'10'
subwf Ziffer3, w
btfss STATUS, Z
return
clrf Ziffer3
incf Ziffer4, f
movlw D'10'
subwf Ziffer4, w
btfss STATUS, Z
return
clrf Ziffer4
return
;warteroutine für 20ms
Wait
movlw D'131'
movwf Wait1
movlw D'250'
movwf Wait2
loop1
incf Wait1, f
btfss STATUS, Z
goto loop1
incf Wait2, f
btfss STATUS, Z
goto loop1
return
;**********************************************************
end
man, das war der erste große brocken, den ich , wenn auch viel abgeguckt, alleine gemacht hab (natürlich mit hilfestellung)
bin ich stolz O:)
-
Wenn Du für den Interupt das CCP-Modul verwendest, dann bekommst Du die Zeit auch ganz genau eingestellt. Wenn deine Taktquelle nicht genau ist, dann kannst Du das Ganze sehr leicht eichen.
Bei dem Beispiel von Gast wurde das genauso gelöst.
BlackBox