Reputation: 1
The following code outputs a timer to a seven segment display. Everything works great except that I can't stop the timer. An interrupt service routine complements the variable RUN which sets the increment function in motion. However, when I press RB0 to call the interrupt after the first time, the clock just keeps ticking.
;******************************************************
;PIC Configuration for PIC16F887
#include "p16F887.inc"
; CONFIG1
; __config 0x2032
__CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_ON & _CPD_ON & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
; CONFIG2
; __config 0x3FFF
__CONFIG _CONFIG2, _BOR4V_BOR40V & _WRT_OFF
;******************************************************
ORG 000H
GOTO INITIALIZE
ORG 04H
GOTO ISROUTINE
ORG 008H
GOTO MAIN
;*******************************************************
INITIALIZE
DCOUNT EQU 20H
CNT_100th EQU 21H ; counter for 0.01s
CNT_10th EQU 22H ; counter for 0.1s
CNT_sec EQU 23H ; counter for seconds
CNT_10sec EQU 24H ; counter for tens of seconds
CNT_min EQU 25H ; counter for minutes
CNT_10min EQU 26H ; counter for tens of minutes
RUN EQU 70H ;the run variable that does stuff to things
OCOUNT EQU 28H
ICOUNT EQU 29H
BSF STATUS,RP1 ;change to bank 3
BSF STATUS,RP0
CLRF ANSEL ;Using all digital mode, turns off analog
CLRF ANSELH ;Make all analog ports digital
BCF STATUS,RP1 ;change to correct bank to configure TRIS registers
;MAKE RA0 OUTPUT, RB0 INPUT, PORTC AND PORTD ALL OUTPUTS
CLRF TRISA
CLRF TRISB
COMF TRISB,1
CLRF TRISD
MOVLW 090H
MOVWF INTCON
MOVLW 040H
MOVWF OPTION_REG
BCF STATUS,RP0
CLRF CNT_100th
CLRF CNT_10th
CLRF CNT_sec
CLRF CNT_10sec
CLRF CNT_min
CLRF CNT_10min
CLRF RUN
GOTO MAIN
MAIN
MOVF CNT_100th,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,5 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,5
MOVF CNT_10th,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,4 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,4
MOVF CNT_sec,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,3 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,3
MOVF CNT_10sec,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,2 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,2
MOVF CNT_min,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,1 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,1
MOVF CNT_10min,0 ; Put count of 1/100ths of second in W
CALL TABLE ; Get value to write out to PORTD from table
MOVWF PORTD ; Put value out to PORTD
BCF PORTA,0 ; Turn on and off display to show digit
CALL DELAY
BSF PORTA,0
CALL WAIT
BTFSC RUN,0
CALL INCCNT
GOTO MAIN
WAIT
MOVLW 08H
MOVWF OCOUNT
MOVLW 0FFH
MOVWF ICOUNT
OLOOP
ILOOP
DECFSZ ICOUNT,1
GOTO ILOOP
DECFSZ OCOUNT,1
GOTO OLOOP
RETURN
ISROUTINE
COMF RUN,1
BCF INTCON,1
RETFIE
INCCNT
INCF CNT_100th,1 ; increment 0.01s counter storing back in counter
MOVLW 0X0A ; check to see if equal to 10
XORWF CNT_100th,0
BTFSC STATUS,Z
GOTO OVER_100th ; if it is 10, goto OVER100th
RETURN ; if no overflow, return
OVER_100th INCF CNT_10th,1 ;there was overflow from previous digit, increment next dig
CLRF CNT_100th ;clear previous digit
MOVLW 0X0A ;check if this results in overflow
XORWF CNT_10th,0
BTFSC STATUS,Z
GOTO OVER_10th ;there was another overflow
RETURN ;no overflow, go back
OVER_10th INCF CNT_sec,1
CLRF CNT_10th
MOVLW 0X0A
XORWF CNT_sec,0
BTFSC STATUS,Z
GOTO OVER_sec
RETURN
OVER_sec INCF CNT_10sec,1
CLRF CNT_sec
MOVLW 0x06
XORWF CNT_10sec,0
BTFSC STATUS,Z
GOTO OVER_10sec
RETURN
OVER_10sec INCF CNT_min,1
CLRF CNT_10sec
MOVLW 0x0A
XORWF CNT_min,0
BTFSC STATUS,Z
GOTO OVER_min
RETURN
OVER_min INCF CNT_10min,1
CLRF CNT_min
MOVLW 0x06
XORWF CNT_10min,0
BTFSC STATUS,Z
GOTO OVER_10min
RETURN
OVER_10min CLRF CNT_100th
CLRF CNT_10th
CLRF CNT_sec
CLRF CNT_10sec
CLRF CNT_min
CLRF CNT_10min
RETURN
DELAY
MOVLW 0FFH
MOVWF DCOUNT
DLOOP DECFSZ DCOUNT
GOTO DLOOP
RETURN
TABLE
ADDWF PCL,1 ;instruction register add excursion address
RETLW 0C0H ;the code for 0( the common LED is anode)
RETLW 0F9H ;the code for 1
RETLW 0A4H ;the code for 2
RETLW 0B0H ;the code for 3
RETLW 99H ;the code for 4
RETLW 92H ;the code for 5
RETLW 82H ;the code for 6
RETLW 0F8H ;the code for 7
RETLW 80H ;the code for 8
RETLW 90H ;the code for 9
END
What did I forget?
Upvotes: 0
Views: 223
Reputation: 700
The interrupt flag RBIF (bit 0) is not being cleared. In ISROUTINE add the line BCF INTCON,0
Upvotes: 1