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.

Interrupt on overflow.

Status
Not open for further replies.
Evening all. I'm trying to get my PIC to start a timer when it receives its first byte of information from the USART, then after 3 seconds make the PIC go to the start of my main body of code (labelled START).

This should only happen (returning to the START) if the rest of the events in the main body of code don't execute after the timer has been started (I'm fail-safing because it's using radio communication).

The rest of the code works fine, it's just the interrupt routine I'm having problems with. The code won't execute at all when it's there. If anyone can see where I might be going wrong I'd appreciate some help.

The .asm file is in the attachment.

Cheers, Mark
 
I seem to be having problems with attachments, so here's the code:

Code:
;***********************************
;		UserUnit.asm
;
;	wait's for a base unit code then
;	transmits own id code back
;	Mark Lazarides @50272135			
;***********************************

	LIST P = 16F628		;	MICIRCONTORLLER USED
	#include "P16F628.INC"	;	HEADER FILE (CONTAINS APPROPRIATE EQUATES SECTION

;=================================================================
;		CONFIGURATION WORD				
;=================================================================

	ERRORLEVEL 0,	-302	;	STOPS BANK SELECTION MESSAGES
	__CONFIG	0x3D18		;	COFIGURATION WORD (SETS OSCILATOR ETC)

	CBLOCK	0X20			;	START OF GENERAL PURPOSE REGISTERS
			COUNT			;	COUNT'S ARE FOR DELAY ROUTINES
			COUNT1		
			COUNTA
			COUNTB
			TEMPRECV		;	RECV'D INFO STORED HERE WHILE CHECKED
			TEMP_W			;	THESE THREE USED FOR TIMER RESET
			TEMP_STATUS
			TIMER_COUNT
	ENDC

	#DEFINE	BIMRX	PORTB,0		;	DEFINING BIM CONTROL LINES
	#DEFINE BIMTX	PORTB,3


	ORG	0x0000					;	THIS IS WHERE THE PROGRAM STARTS FROM
	
	GOTO	INITIALISE

=========================================================================
		INTERRUPT ROUTINE FOR TIMER
=========================================================================
	ORG	0X0004

	MOVWF	TEMP_W		;	SAVING W & STATUS REGISTER SETTINGS
	MOVFW	STATUS
	MOVWF	TEMP_STATUS
	DECFSZ	TIMER_COUNT,	F
	GOTO 	$+2
	GOTO	START
	BANKSEL	PIR1
	BCF		PIR1,	TMR1IF	;	CLEAR FLAG SET FOR TIMER
	MOVFW	TEMP_STATUS
	MOVWF	STATUS
	MOVFW	TEMP_W
	MOVLW	0X60
	BANKSEL	TXREG
	MOVWF	TXREG
	RETFIE

	
	

;============================================================================
;		SET UP THE CHIP FOR ASYNCH COMMS, AND SET PORTS
;============================================================================
INITIALISE	
	MOVLW	0x07				;	DISABLE THE COMPARATORS
	MOVWF	CMCON
	
	BANKSEL TRISA				;	SELECT BANK WITH TRIS REGISTER IN
	MOVLW	B'00100000'
	MOVWF	TRISA				;	SET RA5 AS INPUT, REST OUTPUTS

	MOVLW 	B'00000010'
	MOVWF	TRISB				;	SET RB1 AS INPUT, RB0 AS OUPUT(FOR ASYCNH COMS) REST AS OUTPUT

	BANKSEL SPBRG				;	SET BANK FOR SPBRG (TXSTA & PIE1 IN SAME BANK, NO NEED TO DO FOR NEXT OPERATION)
	MOVLW	D'12'
	MOVWF	SPBRG

	MOVLW	B'00100110'		
	MOVWF	TXSTA				;	SET TRANSMIT SETTINGS

	MOVLW	B'00000001'
	MOVWF	PIE1				;	DISABLE ALL INTERRUPTS <<APART FROM TMR1>>
	
	BANKSEL RCSTA				;	SELECT RCSTA BANK
	MOVLW	B'10010000'	
	MOVWF	RCSTA				;	SET RECIEVE SETTINGS


;=========================================================================
;		MAIN CODE BODY STARTS HERE
;=========================================================================

START
	BANKSEL	INTCON;	
BSF		INTCON,	GIE	;	ENABLE INTERRUPTS (IN GENERAL)
	BANKSEL	T1CON		;	SELECT TIMER 1 REGISTER BANK
	MOVLW	B'00000000'	;	
	MOVWF	TMR1H		;	RESET THE COUNTER TO ZERO
	MOVWF	TMR1L
	MOVLW	B'0011000'	;	SETS UP TIMER WITH 1:8 PRESCALAR
	MOVWF	T1CON
	MOVLW	D'10'
	MOVWF	TIMER_COUNT	;	PUT '6' INTO COUNT, USED FOR CHECKING NUMBER OF TIMES TIMER INTERRUPTED
	BANKSEL	PORTA		;	SELECT PORTA BANK
	BSF		BIMTX		;	SET THE BiM TO RECIEVE
	BCF		BIMRX
	MOVLW	D'3'		;	GIVE IT 3ms TO SETTLE
	CALL 	DELAY
	CALL 	RX_BYTE		;	WAIT FOR ID CODE
	BANKSEL	T1CON		;	set timer on when first byte received
	BSF	T1CON,	TMR1ON
	
	CALL	PRE_REMOVE	;	REMOVE PREAMBLE NONSENSE
START1	
	CALL	DECODE_ID
START2					;	DECODE IT AND SEND OUT ID SIGNAL AFTER 25ms
	GOTO	START

; the rest of the functions come after this, not included here.
 
You also have to set TMR1IE in PIE1 register as well as PEIE in INTCON to get interrupts to occur.

Also, since you are switching banks in the main routine while interrupts are enabled, there is a likelyhood than an interrupt can occur while bank1 is selected. Therefore, the correct bank should be explicitly selected within the interrupt service routine before file registers are accessed.
 
I've just re-checked the data sheets for the 628, but don't seem to be able to find why I should set PEIE for TMR1. Is it a trick of the trade?

With regards to changing the Bank, shouls I make a TEMP_W register in all both BANK 0 & BANK 1 (EDIT: Would I use the ORG statement to accomplish this?)? I can't see any other way of saving W before then putting STATUS in W to change to Bank 0 and save it there.

I 've changes the routine to save STATUS, by putting it into W using
Code:
SWAPF   STATUS, W
MOVWF   TEMP_STATUS
; Then to put it back into status when restoring using
Code:
SWAPF   TEMP_STATUS,W
MOVWF   STATUS
. This is so that the actual status register won't be affected (as it can be using the MOVFW I used previously.
 
Look in the datasheet at section 14-14 (page 103). It shows the interrupt logic, you will see why PEIE needs to be set.

As for your Temp_W. You need to place it in the shared area of memory.
the last 16 bytes on each page are shared between pages. So you can access those 16 bytes from any bank

There's another BIG error in your interrupt routine. After you already restored W and STATUS you do a banksel to TXREG , write to it and then retfie... So you screw up status after all. your interrupt code will always return in bank0 (txreg)
 
I'd forgotten that I'd left that in! I was using it to check whether or not the interrupt was occuring or not (observing the output of the USART for confirmation with a 0x60 byte), that won't be in the final code, but thanks for pointing it out.

I've checked the data sheet and see why I need to set PEIE. I'll give it a go and let you know how i get on.

thanks both for your advice.

Mark
 
I've made some adjustments to the code, but it still doesn't seem to work. bizarrely (to me anyway), it execuites the code fine the first couple of times after programming, then doesn't work after that (even after a power reset). I guess this has to do be because of the timer, but I can't see where I'm going wrong.

I've put both the TEMP_W and TEMP_STATUS in 0x70 and 0x71 respectively. I also now enable GIE & PEIE in the INTCON, and PIE1 <0> remains set as before. If anyone can see where I'm still going wrong it'd be a great help.

.asm file attached
 

Attachments

  • UserUnitiNTERRUPT.rar
    2.5 KB · Views: 225
I've made some adjustments to the code, but it still doesn't seem to work. bizarrely (to me anyway), it execuites the code fine the first couple of times after programming, then doesn't work after that (even after a power reset). I guess this has to do be because of the timer, but I can't see where I'm going wrong.

I've put both the TEMP_W and TEMP_STATUS in 0x70 and 0x71 respectively. I also now enable GIE & PEIE in the INTCON, and PIE1 <0> remains set as before. If anyone can see where I'm still going wrong it'd be a great help.

.asm file attached
 

Attachments

  • UserUnitiNTERRUPT.rar
    2.5 KB · Views: 209
BIG whoops! here :lol:

You have a GOTO start line in your interrupt routine. This will most certainly crash the pic by causing a stack overflow.

an interrupt routine must be seen as completely independent of the main program. All they share is variables, but you cannot just jump from interrupt code to main program code.
All you can do in the interrupt code is set a flag or fill a variable and then, when back in the main code check this variable and act accordingly
 
Yes, you can jump around inside your interrupt routine as much as you want, but you can't jump out of the interrupt routine.
 
Code:
RX_BYTE
	BTFSS	PIR1,	RCIF	;	THIS ROUTINE RECIEVES THE BYTE AND MOVES
	GOTO	RX_BYTE			;	IT TO A TEMPORARY REGISTER 

	BANKSEL	PIR1
	BCF		PIR1,	RCIF

	MOVFW 	RCREG		
	MOVWF	TEMPRECV	
	RETURN


I don't have time to read your code, and understand what you intend to do, but I found that you didn't clear PIR1, RCIF in the routine of RX_BYTE?

Will it cause problems??? I don't read your code clearly!

I debugged your code and found that this bit is never be cleared in program, and I add 2 line codes as above.
 
There are a couple of things that will cause your program to stop working.

First within your ISR, the statement "GOTO START" is ahead of the "BCF PIR1,TMR1IF" statement. That means the interrupt flag is still pending even after you leave the ISR through the "GOTO START" statement. The program will jump right back to the ISR a soon as "BSF INTCON,GIE" is executed.

Second, the UART stops receiving if OERR is set in RCSTA. To quote the datasheet:

Overrun bit OERR has to be cleared in software. This is done by resetting the receive logic (CREN is cleared and then set). If bit OERR is set, transfers from the RSR register to the RCREG register are inhibited, so it is essential to clear error bit OERR if it is set.

If the UART stops receiving, then your program stops working.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top