Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Interrupts

Status
Not open for further replies.
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.

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
 
I haven't had time to go through/simulate your code, but one thing that jumps out at me is this, at the beginning of your ISR:

Code:
BTFSS	  PIR1,TMR1IF			
GOTO	  $-1

If you have an interrupt other than from TMR1 your ISR is going to get stuck in an endless loop (well, endless until TMR1 overflows and sets TMR1IF again).

Put a label before your ISR return code (movf STATUS_Save,w) and goto that label if TMR1IF isn't set. Or code your ISR to handle any other interrupts you have enabled.

Also, make sure you have RP0/RP1 set correctly in your ISR. Put a BANKSEL PIR1 before your reference to PIR1. Lastly, stick your W_Save and STATUS_Save into the shared portion of data memory (0x70-7F), that way they're accessible regardless of what RP0 and RP1 are set to when you enter the ISR.

Code:
W_Save			  EQU 0X70    ; Put in shared memory
STATUS_Save		  EQU 0X71    ; Put in shared memory
. . .
ISR:
movwf     W_Save				;SAVES STATUS REGISTER 
movf      STATUS,w
movwf     STATUS_Save

BANKSEL     PIR1                            ; Ensure bank bits in STATUS reg are set correctly
BTFSS	  PIR1,TMR1IF			
GOTO	  EXIT_ISR                    ; Not ideal; if an interrupt occurs for other than TMR1 the ISR should handle it and clear the flag bit
bcf		  PIR1,TMR1IF
BANKSEL     TIMERCOUNTER          ; Once again, set bank bits (not really needed since PIR1 is also in bank 0)
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

EXIT_ISR:
movf      STATUS_Save,w
movwf     STATUS
swapf     W_Save,f
swapf     W_Save,w
retfie
 
Last edited:
Hi again,

I ran some slightly different code where a loop sends 12 until it gets interrupted sends 55, and then returns to sending 12. It does it for a while, but eventually stops. I think the problem may be the program is being interrupt while 12 is being sent. In other words when the code is polling:

btfss TXSTA,TRMT ; (1) transmission is complete if hi
goto WtHere

not sure though.

I just made a couple more of the suggestions you made. I don't think the problem is the banks selected.





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	  RETURNFROMINT 
bcf		  PIR1,TMR1IF

NUMBER
MOVLW	  D'55'
CALL	  SEND

GOTO	  RETURNFROMINT

RETURNFROMINT:
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

CLRF	TIMERCOUNTER
CALL	UART_SETUP		
CALL	INTERRUPTSETUP

DUMMY
MOVLW	D'12'
CALL	SEND
CALL	SECOND 
GOTO    DUMMY 


CALL	GETBREATHINGRATE


;-------------------------------------------------------
;GETS BREATHING RATE 
;------------------------------------------------------

GETBREATHINGRATE:
CLRF 	  SAMPLEOLD 
CLRF	  SAMPLENEW 
CLRF 	  NUMBER_OF_BREATHS
CLRF	  TIMERCOUNTER
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
;-----------------------------------------------------------------------------------------------------------------------------------------------
 
Maybe disable interrupts while inside your SEND call?

Also, if you're sending 12 over and over, and just want to send 55 once when the interrupt occurs, how about storing the value to send in a variable, setting it to 12, then calling SEND in your main loop as you are now, and have the ISR change the value to 55 so it gets sent on the next call to SEND? At the end of the SEND call set the value back to 12. That eliminates another possible problem-causer, doing a CALL from within the ISR.

So, for example:

Code:
SENDVAL  equ 0x72   ; place to put value to be sent
...
ISR:
...
  movlw 0x55
  movwf  SENDVAL
...

DUMMY:
movfw  SENDVAL
call      SEND
...

SEND:
... (existing code)
MOVLW   0x12
MOVWF   SENDVAL    ; Set value back to 12 after sending
RETURN

I don't think the problem is the banks selected.
It still could be though. There are places in your code where you do change the bank bits to access registers, and if the interrupt occurs while you're in a bank other than 0, your ISR isn't handling this. Putting your W_SAVE and STATUS_SAVE in the 70-7F area of memory, and clearing the bank bits in the ISR after saving W and STATUS will solve those issues. Try these changes:

Code:
W_SAVE  EQU 0x70        ; These addresses are accessible regardless of the RP bits
STATUS_Save EQU 0x71
...
ISR:
movwf     W_Save				;SAVES STATUS REGISTER 
movf      STATUS,w
movwf     STATUS_Save

BANKSEL     PIR1                    ; Set bank bits since you don't know what they are at the time of the interrupt
BTFSS	  PIR1,TMR1IF			
GOTO	  RETURNFROMINT 
bcf		  PIR1,TMR1IF

NUMBER
MOVLW	  D'55'
CALL	  SEND

;GOTO	  RETURNFROMINT  ; No need for this line since RETURNFROMINT follows immediately!

RETURNFROMINT:
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
 
Last edited:
yeah, disabling the interrupt during the send call worked and i've made all the changes you suggested. Thank you for all the help, your a life saver.

cheers,
ed.
 
Setting up your program to deal with interrupts is simpler than you've done it with the 3 "NOP" instructions. You use "org" directives to place either the ISR code itself at address 0x04 OR the jump instruction that directs the code to the ISR code segment at address 0x04.

If you do your "org" statements as such -

Code:
		org		0x00		;locate jump instruction that directs program counter to program ROM address
		goto		START		;where start of main program resides at program ROM address 0x00

		org		0x04		;locate jump instruction that directs program counter to program ROM address
		goto		ISR   		;where start of ISR code resides at program ROM address 0x04

The assembler will now locate the jump instruction "goto START" at program ROM address 0x00. This is the program ROM address where the program counter first starts upon initial power up as well as upon a reset. It will proceed to jump to the starting line of your main program, which is labeled "START".

The assembler will also locate the jump instruction "goto ISR" at program ROM address 0x04. Now when an interrupt is triggered and the program counter jumps to program ROM address 0x04, it will see the jump instruction "goto ISR", which will prompt the PC to jump to the line labeled "ISR", which is the starting line of your interrupt service routine.

This will allow you to locate the starting line of your main program as well as your ISR code at any place you want to place it in the main code.

Also, you got your swapf instruction swapping data from W when you should be using swapf to swap the STATUS nibbles to keep from affecting the zero bit. At the start of your interrupt it should read -

Code:
                movwf		W_Save
		swapf		STATUS,W
		movwf		STATUS_Save

And to return from interrupt -

Code:
		swapf		STATUS_Save,W
		movwf		STATUS		
		movfw		W_Save
		retfie

Hope this helps.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top