edofbrighton
Member
hello,
I'm trying to use the timer 1 module on the on the PIC16F690 to create an interrupt, but it's not working properly. I can set the interrupt up so it interrupts the program, but it doesn't return correctly. At the moment the code i've written, send the number 15 every second, then after 5 seconds it the timer interrupts the program and it sends the number 20. It should then return from the interrupt and continue sending 15, but it doesn't.
any suggestions would be apprciated.
I'm trying to use the timer 1 module on the on the PIC16F690 to create an interrupt, but it's not working properly. I can set the interrupt up so it interrupts the program, but it doesn't return correctly. At the moment the code i've written, send the number 15 every second, then after 5 seconds it the timer interrupts the program and it sends the number 20. It should then return from the interrupt and continue sending 15, but it doesn't.
any suggestions would be apprciated.
Code:
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT& _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
;----------------------------------------
; DELAY EQUATES
CNT EQU 0X25 ;ADDRESS FOR COUNTER
CNT2 EQU 0X26 ;ADDRESS FOR COUNTER2
CNT3 EQU 0X27 ;ADDRESS FOR COUNTER3
RECEIVEDBYTE EQU 0X28 ;ADDRESS FOR COUNTER4
BREATH_ADC0 EQU 0X29 ;ADDRESS FOR RECEIVED BIT
BREATH_ADC1 EQU 0X2A
NUMBER_OF_BREATHS EQU 0X2B
CNT5 EQU 0X2C
BINARY EQU 0X2D
t1 EQU 0X2E
w2 EQU 0X2F
COUNTER EQU 0X30
TEMP EQU 0X31
D1 EQU 0X32
D0 EQU 0X33
SAMPLEREG EQU 0X34
D2 EQU 0X35
D3 EQU 0X36
SAMPLEOLD EQU 0X37
SAMPLENEW EQU 0X38
D4 EQU 0X39
D5 EQU 0X3A
D6 EQU 0X3B
SAMPLEOLDLOW EQU 0X3C
SAMPLEOLDHIGH EQU 0X3D
SAMPLENEWLOW EQU 0X3E
SAMPLENEWHIGH EQU 0X3F
W_Save EQU 0X40
STATUS_Save EQU 0X41
TOTALBREATHS EQU 0X42
SAMPLE1 EQU 0X43
SAMPLE2 EQU 0X44
SAMPLE3 EQU 0X45
SAMPLE4 EQU 0X46
SAMPLE5 EQU 0X47
SAMPLE6 EQU 0X48
SAMPLE7 EQU 0X49
SAMPLE8 EQU 0X50
SAMPLE9 EQU 0X51
SAMPLE10 EQU 0X52
SAMPLE11 EQU 0X53
SAMPLE12 EQU 0X54
TIMERCOUNTER EQU 0X55
TOTALNOB EQU 0X56
D7 EQU 0X57
D8 EQU 0X58
D9 EQU 0X59
D10 EQU 0X5A
ONES EQU 0X5B
TENS EQU 0X5C
HUNDEREDS EQU 0X5D
D12 EQU 0X5E
D13 EQU 0X60
; LCD EQUATES AND DEFINES
#DEFINE DDRE TRISB,7 ;DATA DIRECTION
#DEFINE DDRRS TRISB,4 ;DATA DIRECTION
#DEFINE E PORTA,2 ;ENABLE LINE ON LCD
#DEFINE RS PORTB,4 ;INSTRUCTION/DATA SELECT
#DEFINE RW PORTB,6
TEMP_LCD EQU 0X3A ;STORAGE FOR LCD
LCD EQU PORTC ;LCD DATA PORT
CLRSCR EQU B'00000001' ;COMMAND FOR CLRSCR
HOME EQU B'00000010' ;SENDS CURSOR TO HOME
ON EQU B'00001100' ;TURNS ON THE DISPLAY
OFF EQU B'00001000' ;TURNS THE DISPLAY OFF
LEFT EQU B'00011000' ;LEFT SHIFT
RIGHT EQU B'00011100' ;RIGHT SHIFT
LIN2 EQU B'11000000' ;SETS TO LINE 2
TIMERCOMP EQU D'4'
;----------------------------------------
; VECTOR FOR NORMAL START UP.
ORG 0
GOTO START
;--------------------------------------------
;INTERRUPT ROUTINE
;--------------------------------------------
NOP
NOP
NOP
ISR:
movwf W_Save ;SAVES STATUS REGISTER
movf STATUS,w
movwf STATUS_Save
BTFSS PIR1,TMR1IF
GOTO $-1
bcf PIR1,TMR1IF
INCF TIMERCOUNTER
MOVFW TIMERCOUNTER ;STORE NEW SAMPLE AND SUBTRACT IT FROM OLD
SUBLW D'10'
BTFSC STATUS,Z
CALL NUMBER
MOVLW B'11011100' ;PRELOADS COUNTER FOR 5 SECOND
MOVWF TMR1L
MOVLW B'00001011'
MOVWF TMR1H
movf STATUS_Save,w
movwf STATUS
swapf W_Save,f
swapf W_Save,w
retfie
;-----------------------------------------------
; MAIN PROGRAM STARTS HERE:
;----------------------------------------------
START:
CLRW ; CLEAR W.
MOVWF PORTA ; ENSURE PORTA IS ZERO BEFORE WE ENABLE IT.
MOVWF PORTB ; ENSURE PORTB IS ZERO BEFORE WE ENABLE IT.
MOVWF PORTC
BSF STATUS,RP1 ;SELECT BANK2
MOVLW H'00'
MOVWF ANSEL
MOVLW B'00000010' ;DIGITAL/ANALOGUE SETS AN9 AS ANANLOGUE
MOVWF ANSELH
BCF STATUS,RP1
BSF STATUS,RP0 ; SELECT BANK 1
;MOVLW B'0000100' ; SETS CLOCK TO BE RUN FROM EXTERNAL OSC. DEFINED IN CONFIG BITS. PAY ATENTION TO BITS 0 AND 3 FOR REPORT
;MOVWF OSCCON
MOVLW H'00' ; ALL PORTA OUTPUTS
MOVWF TRISA ; SET TRISA REGISTER.
MOVLW B'00100000' ; SET B5 RX PIN AS INPUT
MOVWF TRISB ; SET TRISB REGISTER.
MOVLW b'10000000' ;ALL OF PORTC OUTPUTS
MOVWF TRISC
MOVLW b'000100000' ;A2D Clock Fosc/8 4MHz CLOCK
MOVWF ADCON1
BCF STATUS,RP0 ; RESELECT BANK 0.
MOVLW B'00100101' ; ADCON0 . ADCON 0 BIT 7=0 LJ. BIT 6=0 VDD REF. BITS 5-2 1011 SEL AN11. BIT 1 GO/DONE BIT. BIT0=1 ENABLE IT.
MOVWF ADCON0
CALL UART_SETUP
CALL INTERRUPTSETUP
DUMMY:
MOVLW D'15'
CALL SEND
CALL SECOND
GOTO DUMMY
CALL GETBREATHINGRATE
NUMBER:
CLRF TIMERCOUNTER
MOVLW D'20'
CALL SEND
CALL SECOND
RETURN
;-------------------------------------------------------
;GETS BREATHING RATE
;------------------------------------------------------
GETBREATHINGRATE:
CLRF SAMPLEOLD
CLRF SAMPLENEW
CLRF NUMBER_OF_BREATHS
GBRLOOP:
BSF ADCON0,GO ; STARTS ADC CONVERSION
BTFSS ADCON0,GO ; POLLING WHEN TO SEE WHEN ADC HAS BEEN COMPLETE
GOTO $-1
MOVFW ADRESH
MOVWF SAMPLENEW
CALL SAMPLEOLD_GT_SAMPLENEW
BTFSS SAMPLEREG,0
CALL INCFNOB
MOVFW SAMPLENEW
MOVWF SAMPLEOLD
MOVFW NUMBER_OF_BREATHS
CALL SEND
GOTO GBRLOOP
;--------------------------------------------------------
;ENABLES INTERRUPTS FROM TIMER 1
;--------------------------------------------------------
INTERRUPTSETUP:
bsf STATUS,RP0 ;SWITCH TO BANK ONE
bsf PIE1,TMR1IF ;ENABLE TIMER1 INTERRUPT
bcf STATUS,RP0 ;SWITCH TO BANK ZERO
bsf INTCON,7 ;ENABLE GLOBAL INTERRUPTS
BSF INTCON,PEIE ;ENABLE PERIPHERAL INTERRUPTS
CLRF TMR1L ;CLEAR TIMER COUNTER
CLRF TMR1H
MOVLW B'00110000' ;BITS 5-4 GIVES 1:8 PRESCALER. BIT 1=0 USE INTERNAL CLOCK/4.
MOVWF T1CON
BSF T1CON,0 ;ENABLES TIMER
RETURN
RETURN
;----------------------------------------------------
;FINDS ASCII EQUIVILENT FOR VAULE IN W
;----------------------------------------------------
LOOKUP_TABLE:
ANDLW B'00001111' ;STOP VALUE GOING BEYOND TABLE RANGE
ADDWF PCL
RETLW '0'
RETLW '1'
RETLW '2'
RETLW '3'
RETLW '4'
RETLW '5'
RETLW '6'
RETLW '7'
RETLW '8'
RETLW '9'
;---------------------------------------------------
;SEND BREATHING RATE
;---------------------------------------------------
;----------------------------------------------------------------------------------------------
;-INCREAMENTS NUMBER OF BREATHS IF CHANGE OF DIRECTION IN VOLTAGE HAS OCCURRED. CHECK WHICH WAY
;-----------------------------------------------------------------------------------------------
INCFNOB:
BTFSS SAMPLEREG,1 ;SKIPS IF BIT 1 OF SAMPLE REG IS SET. IF IT IS NOT NOB IS INCREMENTED
INCF NUMBER_OF_BREATHS
BSF SAMPLEREG,1 ;SETS BIT 1 OF SAMPLE REG.
RETURN
;----------------------------------------------------------------------------------------------
;8-BIT COMPARE FOR ADC SAMPLES-IF OLD IS 4 GREATER THAN NEW SETS SAMPLE REG,0
;---------------------------------------------------------------------------------------------
SAMPLEOLD_GT_SAMPLENEW:
MOVLW D'3'
ADDWF SAMPLEOLD
MOVFW SAMPLENEW
SUBWF SAMPLEOLD
BTFSS STATUS,C
BCF SAMPLEREG,0 ;IF NEW SAMPLE IS GREATER THAN OLD THIS WILL BE CLEAR
BTFSC STATUS,C
BCF SAMPLEREG,1
BTFSC STATUS,C
BSF SAMPLEREG,0
RETURN
DISPLAYADC0:
MOVLW D'255'
MOVWF SAMPLEOLDLOW
MOVWF SAMPLEOLDHIGH
CLRF NUMBER_OF_BREATHS
DISPLAYADC:
BSF ADCON0,GO ; start conversion
BTFSS ADCON0,GO ; this bit will change to zero when the conversion is complete
GOTO $-1
MOVFW ADRESH
MOVWF SAMPLENEWHIGH
MOVFW ADRESL
MOVWF SAMPLENEWLOW
CALL LARGECOMPAREOLDGTNEW
BTFSC SAMPLEREG,0
CALL INCFNOB
MOVFW NUMBER_OF_BREATHS
CALL DISPLAYBCD
;CALL TENTH_SEC_DELAY
MOVLW CLRSCR ; Clear the screen
CALL COMMAND
MOVFW SAMPLENEWHIGH
MOVWF SAMPLEOLDHIGH
MOVFW SAMPLENEWLOW
MOVWF SAMPLEOLDLOW
GOTO DISPLAYADC
;-------------------------------------------------------------------------------------------------------
;COUNTS THE NUMBER OF BREATHS TAKEN UNTIL IT IS INTERRUPTED. TIMER1 INTERRUPTS PROGRAM EVERY 0.5 SECONDS
;-------------------------------------------------------------------------------------------------------
DISPLAYADC0EDIT:
MOVLW D'255' ;MOVES 255 TO OLD SAMPLE LOW AND HIGH BYTES
MOVWF SAMPLEOLDLOW
MOVWF SAMPLEOLDHIGH
CLRF NUMBER_OF_BREATHS ;CLEARS NUMBER OF BREATHS
CLRF TOTALNOB ;CLEARS TOTAL NUMBER OF BREATHS
DISPLAYADCEDIT:
BSF ADCON0,GO ; STARTS ADC CONVERSION
BTFSS ADCON0,GO ; POLLING WHEN TO SEE WHEN ADC HAS BEEN COMPLETE
GOTO $-1
MOVFW ADRESH ;MOVES HIGH BYTE OF ADC TO SAMPLE HIGH
MOVWF SAMPLENEWHIGH
MOVFW ADRESL ;MOVES LOW BYTE OF ADC TO SAMPLE LOW
MOVWF SAMPLENEWLOW
CALL LARGECOMPAREOLDGTNEW ;COMPARES THE LAST ADC SAMPLE TO NEW ADC SAMPLE. IF THE NEW IS GREATER THAN THE OLD SAMPLEREG BIT 0 IS SET.
BTFSC SAMPLEREG,0 ;IF NEW WAS GREATER INCFNOB IS CALLED. INCFNOB WILL INCREMENT NOB ONLY IF THE RESULT OF THE LAST
CALL INCFNOB
MOVFW SAMPLENEWHIGH ;MOVES NEW SAMPLE TO OLD SAMPLE FOR NEXT LOOP
MOVWF SAMPLEOLDHIGH
MOVFW SAMPLENEWLOW
MOVWF SAMPLEOLDLOW
GOTO DISPLAYADCEDIT ;RETURNS TO GET NEW ADC
RETURN
ADCTRIAL
BSF ADCON0,GO ; start conversion
BTFSS ADCON0,GO ; this bit will change to zero when the conversion is complete
GOTO $-1
MOVFW ADRESH
MOVWF SAMPLENEW
;CALL SAMPLENEW_GT_SAMPLEOLD
BTFSS SAMPLEREG,0
INCF NUMBER_OF_BREATHS
MOVLW CLRSCR ; Clear the screen
MOVFW NUMBER_OF_BREATHS
CALL COMMAND
CALL DISPLAYBCD
;CALL TENTH_SEC_DELAY
GOTO ADCTRIAL
RETURN
;--------------------------------------------------
;DISPLAYS BCD FOR VALUE CONTAINED IN W
;--------------------------------------------------
DISPLAYBCD:
MOVWF BINARY
CALL GETHNDS
CALL LOOKUP_TABLE
CALL DISPLAY
MOVFW BINARY
CALL GETTENS
CALL LOOKUP_TABLE
CALL DISPLAY
MOVFW BINARY
CALL GETONES
CALL LOOKUP_TABLE
CALL DISPLAY
RETURN
; -------------------------------------------
; RECEIVES BYTES
; -------------------------------------------
; This routine does not return until a character is received.
;
RECEIVE:
btfss PIR1,RCIF ; (5) check for received data
goto RECEIVE
movf RCREG,W ; save received data in W
BTFSC STATUS,Z
GOTO RECEIVE
BCF RCSTA,CREN
BSF RCSTA,CREN
return
; -------------------------------------------------------------
; SENDS BYTES
; -------------------------------------------------------------
;
SEND:
movwf TXREG ; send data in W
BCF PIR1,RCIF
BSF STATUS,RP0
WtHere
btfss TXSTA,TRMT ; (1) transmission is complete if hi
goto WtHere
BCF STATUS,RP0
return
;--------------------------------------------------------------
;INITIALISES UART
;--------------------------------------------------------------
UART_SETUP: ;This should give a Baud Rate of just over 1500.
;BSF OSCCON,SCS
bsf STATUS,RP0
movlw D'207' ;207 GIVES 300BPS NO ERROR AT THIS BAUD RATE
movwf SPBRG
movlw b'00100000' ; brgh = low (2)
movwf TXSTA ; enable Async Transmission, set brgh
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
movwf RCSTA
return
;-------------------------------------------------------------
;INTIALISES UART FOR BAUD RATE OF 4800?
;-------------------------------------------------------------
GPSUART_SETUP:
BCF OSCCON,SCS
bsf STATUS,RP0
movlw D'191' ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw b'00100100' ; brgh = high (2)
movwf TXSTA ; enable Async Transmission, set brgh
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
movwf RCSTA
return
;------------------------------------------------------------
; INTILAISES LCD
;------------------------------------------------------------
INIT_LCD:
CALL MILLISEC30
MOVLW B'00111000' ;tell display its two line0
CALL COMMAND
MOVLW B'00001110'
CALL COMMAND
CALL CLEARSCREEN
MOVLW B'00000110'
CALL COMMAND
RETURN
;------------------------------------------------------------
; MOVES DDRAM TO BEGININNING OF SECOND LINE
;------------------------------------------------------------
SECOND_LINE:
MOVLW LIN2 ;set to line 2
CALL COMMAND ;output to the screen
RETURN
;------------------------------------------------------------
; EXECUTES COMMANDS IN W FOR LCD
;-----------------------------------------------------------
COMMAND:
BCF RS
BCF RW ;command coming
MOVWF LCD ;PUT OUT ONTO PORT
BSF E ;make sure the enable line is up
CALL MICROSEC50 ;WAIT
BCF E ;clock the data in
BSF RS
RETURN
;************************************************************
; DISPLAYS CONTENTS OF W ON LCD
;************************************************************
DISPLAY: ;make sure it will accept data
BSF RS
BCF RW
MOVWF LCD ;send data to lcd
BSF E ;make sure the enable line is up
CALL MICROSEC50
BCF E
CALL MICROSEC50 ;clock the data in
BSF RS
RETURN
;------------------------------------------------------------
;CLEARS SCREEN OF LCD
;------------------------------------------------------------
CLEARSCREEN:
BCF RS
BCF RW
MOVLW D'1'
MOVWF LCD
BSF E
CALL MILLISEC2
BCF E
CALL MILLISEC2
RETURN
;---------------------------------------------
;RETURNS NUMBER OF HUNDERS FOR VALUE IN W
;---------------------------------------------
GETHNDS
movwf t1
clrf w2
gethnds_loop
movlw .100
incf w2,f
subwf t1,f
btfsc STATUS,C
goto gethnds_loop
decf w2,w
return
;--------------------------------------------
;RETURNS NUMBER OF TENS FOR VALUE IN W
;--------------------------------------------
GETTENS
movwf t1
clrf w2
gettens_loop movlw .10
incf w2,f
subwf t1,f
btfsc STATUS,C
goto gettens_loop
decf w2,w
goto GETONES
;----------------------------------------------
;RETURNS NUMBER OF ONES FOR VALUE STORED IN W
;-------------------------------------------------
GETONES movwf w2
movlw .10
deltens_loop subwf w2,f
btfsc STATUS,C
goto deltens_loop
addwf w2,w
return
;--------------------------------------------------------------------------------------
;COMPARES 16-BIT NUMBER
;SETS BIT 0 OF SAMPLEREG IF NEW SAMPLE WAS GREATER THAN OR EQUAL TO THE OLD; CLEARS BIT 0 OF SAMPLE REG IF NOT.
;--------------------------------------------------------------------------------------
LARGECOMPAREOLDGTNEW:
MOVFW SAMPLEOLDLOW ;MOVES LOW BYTE OF OLD SAMPLE TO W
SUBWF SAMPLENEWLOW,w ;SUBTRACTS LOW BYTE OF OLD SAMPLE FROM NEW SAMPLE
MOVFW SAMPLEOLDHIGH ;MOVES HIGH BYTE OF OLD SAMPLE TO W
SKPC ;IF THE CARRY FLAG IS SET SAMPLENEW-SAMPLEOLD WAS POS OR 0 AND NEXT INSTRUCTION WILL BE SKIPPED
INCFSZ SAMPLEOLDHIGH,w ;INCREMENTS OLD SAMPLE. IF IT ZERO GOES TO NEXT INSTRUCTION.
SUBWF SAMPLENEWHIGH,w ;SUBTRACTS HIGH BYTE OF OLD SAMPLE FROM NEW.
SKPNC ;IF OLD WAS GREATER THAN NEW BIT ZERO OF SAMPLEREG IS CLEARED
BCF SAMPLEREG,0
SKPC ;IF NEW WAS GREATER THAN OLD BIT 0 OF SAMPLEREG IS SET
BSF SAMPLEREG,0
RETURN
;--------------------------------------------------------
;DISPLAYS THE LETTER Y
;--------------------------------------------------------
LETTER:
MOVLW 'T'
CALL SEND
RETURN
;----------------------------------------------
;30 MILLI-SECOND DELAY FOR 14.7456 MHz CLOCK
;----------------------------------------------
MILLISEC30:
movlw 0x65
movwf D1
movlw 0x57
movwf D2
Delay_1
decfsz D1, f
goto $+2
decfsz D2, f
goto Delay_1
;4 cycles
goto $+1
goto $+1
RETURN
;-----------------------------------------------
;2 MILLISECOND DELAY FOR 14.7456 MHz CLOCK
;-----------------------------------------------
MILLISEC2
movlw 0xC2
movwf D3
movlw 0x06
movwf D2
Delay_2
decfsz D3, f
goto $+2
decfsz D2, f
goto Delay_2
;------------------------------------------------
;50 MICROSECOND DELAY FOR 14.7456 MHz CLOCK
;------------------------------------------------
MICROSEC50:
;184 cycles
movlw 0x3D
movwf D4
Delay_3
decfsz D4, f
goto Delay_3
RETURN
;--------------------------------------------------
;TEN SECOND DELAY FOR 14.7456 CLOCK
;---------------------------------------------------
TENSECONDS:
movlw 0x01
movwf D5
movlw 0x5C
movwf D6
movlw 0x51
movwf D7
Delay_0
decfsz D5, f
goto $+2
decfsz D6, f
goto $+2
decfsz D7, f
goto Delay_0
RETURN
;-------------------------------------------------------
;4 MHZ-1SECOND
;-------------------------------------------------------
SECOND:
movlw 0x08
movwf D8
movlw 0x2F
movwf D9
movlw 0x03
movwf D10
Delay_6
decfsz D8, f
goto $+2
decfsz D9, f
goto $+2
decfsz D10, f
goto Delay_6
;3 cycles
goto $+1
nop
RETURN
;-------------------------------------------------------
;4 MHz-0.1SECONDS
;-------------------------------------------------------
TENTHOFSECOND:
movlw 0x1F
movwf D12
movlw 0x4F
movwf D13
Delay14
decfsz D12, f
goto $+2
decfsz D13, f
goto Delay14
;2 cycles
goto $+1
RETURN
JOE:
BSF RCSTA,SPEN
MOVLW 'B'
CALL SEND
MOVLW 'R'
CALL SEND
MOVLW 'A'
CALL SEND
MOVLW 'P'
CALL SEND
MOVLW 'A'
CALL SEND
BCF RCSTA,SPEN
BCF PORTB,7
CALL SECOND
GOTO JOE
;-----------------------------------------------------------------------------------------------------------------------------------------------
END