Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Unstable timer1/interrupt.. Works/works not... grrr

Status
Not open for further replies.

zanor

Member level 4
Joined
Feb 17, 2006
Messages
79
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Norway
Activity points
2,039
timer1 interrupt

Hi!

I'm in progress of making my own scrolling led sign. Almoast everything is working fine by now. I have set up timer1 (btw, pic16f648a) to 1:8 prescale, and interrupt on overflow. This works fine, but sometimes it just finds out that it will not interrupt any more.

The sign scrolls but then suddenly it stops (on a random position in the string) and stays there. I know the rest of the PIC program continues to run because I use 5 lines and only 1 is lit at a time.

I also have some tables in my code that I must change PCLATCH before I jump to, could it be something with this?

Please help me!

I post my whole code, It's kinda messy :p

I have tried with another chip so thats not the foult...

Code:
		__config 0x3F50
		LIST   P=PIC16F648A		
		include <P16F648A.INC>


; Variables and Constants
	cblock	0x20			;start of general purpose registers
		count			;used in delay routine
		count1			;used in delay routine
		counta			;used in delay routine
		countb			;used in delay routine
		SENDME
		CR				; Current row
		LOOPC			; Loop counter
		LOOPD			; Loop data
		STRING_I		; String index
		CHAR_I			; Char index
		C_FONT			; Current font
		O_FONT			; Offset
		P_FONT			; Page
		temp
		temp2
		tmp_status		; Used to save info during interrupt
		tmp_w			; Used to save info during interrupt
	endc

SCK		equ 0x06		; HC595 Serial clock
SI		equ 0x05		; HC595 Serial data
RCK		equ	0x07		; HC595 Output clock

; Char and string adress
StringTable	equ 0x500
FontTable	equ	0xA00

	ORG 000H  ; a reset redirects program to this point

	GOTO PRG_START

    ORG 004H  ; an interrupt redirects the program to here
	MOVWF	tmp_w
	MOVFW	STATUS
	MOVWF	tmp_status


	BCF		PIR1, TMR1IF

	INCF	CHAR_I
	
	MOVFW	CHAR_I
	SUBLW	0x06
	BTFSS	STATUS, Z
	GOTO 	done
	
	MOVLW	0x01
	MOVWF	CHAR_I
	INCF	STRING_I
	
done
	MOVFW	tmp_status
	MOVWF	STATUS
	MOVFW	tmp_w
	RETFIE
	
    

PRG_START
; Initialize PORT's
	BSF		STATUS, RP0	; Bank1
	MOVLW	0x02		; Set RX (RB1) to input
	MOVWF	TRISB
	MOVLW	0x00
	MOVWF	TRISA

; Set speed to 4MHz
	MOVLW	0x08
	MOVWF	PCON

; USART initialize
	MOVLW	0x24		; Transmitter: RS232
	MOVWF	TXSTA		;
	BCF		STATUS, RP0	; Bank 0
	MOVLW	0x90		; Receiver: RS232
	MOVWF	RCSTA		;
	
; USART Baud rate adjust
	BSF 	STATUS, RP0	; Bank1
	MOVLW 	0x19		; Set Baud rate 9.6000 @ 4 MHz
	MOVWF 	SPBRG
	BCF 	STATUS, RP0	; Bank 0

; Turn ON Timer1	
	MOVLW	0x31;
	MOVWF	T1CON
	
; Enable interrupts
	BSF		INTCON, GIE	; global interrupt enable
	BSF		INTCON, PEIE	; enable peripheral interrrupt
	BSF		STATUS, RP0	; Bank1
	BSF		PIE1, TMR1IE	; enable timer1 interrupt
	BCF		STATUS, RP0	; Bank0
	
	

	MOVLW	0x05		; Starting at bottom row
	MOVWF	CR			; and working upwards.
	
	MOVLW	0x01		; 1 - 5, 1 = Space
	MOVWF	CHAR_I
	MOVLW	0x00
	MOVWF	STRING_I

MAIN
	MOVLW	0x08		; Loop trough 8 bits
	MOVWF	LOOPC

	BSF		PORTB, SCK	; Send a start
	BCF		PORTB, SCK	; clock pulse
	
	CLRF	LOOPD		; Start from scratch
	
	MOVF	STRING_I, F	; See if it
	BTFSC	STATUS, Z	; is the first char
	GOTO	HERE		; Yes? then skip this part

	DECF	STRING_I, F

	CALL	get_char
	CALL	get_font	; Get row data
	
	MOVWF	LOOPD
		
	INCF	STRING_I, F
	
HERE

	CALL	get_char
	CALL	get_font	; Get row data
	
	MOVWF	temp2
	RLF		temp2, F
	RLF		temp2, F
	RLF		temp2, F
	
	MOVFW	CHAR_I
	MOVWF	temp
	
LOOP1
	RLF		temp2, F
	RLF		LOOPD, F
	
	DECFSZ	temp, F
	GOTO	LOOP1

LOOP
	
	BCF		PORTB, SI	; Clear bit to send
	RLF		LOOPD, F	; Rotate so we get the bit
						; we want into Carrey
	BTFSC	STATUS, C	; Did we get a 1?
	BSF		PORTB, SI	; Yes, then set bit to send
	
	BSF		PORTB, SCK	; And send it
	BCF		PORTB, SCK
	
	DECFSZ	LOOPC, F	; Decrease loop counter,
	GOTO 	LOOP		; are we finished looping?
	
	MOVLW	0x00
	MOVWF	PORTA
	
	BSF		PORTB, RCK	; Yes, then display
	BCF		PORTB, RCK  ; the line sent
		
	MOVFW	CR			; Move current row to W
	CALL	tbl_row		; Get PORTA byte
	MOVWF	PORTA		; Display current row
	
	;CALL	Delay1
	
	DECFSZ	CR, F
	GOTO	MAIN		; Not last row, display next
	MOVLW	0x05		; Last row, begin from
	MOVWF	CR			; bottom row again.			
	
	GOTO	MAIN
	
get_char
	MOVLW	HIGH tbl_string
	MOVWF	PCLATH
	
	MOVFW	STRING_I
	CALL	tbl_string
	
	MOVWF	temp
	MOVLW	HIGH MAIN
	MOVWF	PCLATH
	
	MOVFW	temp
	
	RETURN
	
	
get_font
	MOVWF	C_FONT

	MOVLW	HIGH tbl_font	; Get starting page
	MOVWF	P_FONT			; address.
	
	MOVLW	LOW tbl_font	; Get offset
	ADDWF	C_FONT, W
	BTFSC	STATUS, C
	INCF	P_FONT, F
	
	ADDWF	C_FONT, W
	BTFSC	STATUS, C
	INCF	P_FONT, F
	
	ADDWF	C_FONT, W
	BTFSC	STATUS, C
	INCF	P_FONT, F
	
	ADDWF	C_FONT, W
	BTFSC	STATUS, C
	INCF	P_FONT, F
	
	ADDWF	C_FONT, W
	BTFSC	STATUS, C
	INCF	P_FONT, F

	ADDWF	CR,	W
	MOVWF	O_FONT
	
	MOVFW	P_FONT
	MOVWF	PCLATH
	
	MOVFW	O_FONT
	CALL	tbl_font
	
	MOVWF	temp
	MOVLW	HIGH MAIN
	MOVWF	PCLATH
	MOVFW	temp
	
	RETURN

tbl_row
	addwf	PCL, F
	retlw	0x00	; Dummy entry..... (PCL + 0)
	retlw	0x01	; Row 1 (PORTA byte)
	retlw	0x02	; Row 2
	retlw	0x04	; ...
	retlw	0x08
	retlw	0x80
	
tbl_data
	addwf	PCL, F
	retlw	0x00	; Dummy entry..... (PCL + 0)
	retlw	0xDB	; Row 1 data
	retlw	0xAA	; Row 2
	retlw	0x81	; ...
	retlw	0x0F
	retlw	0xFF		


; Delay routines (Ripped form some website)

Long_Delay				
		movlw	d'50'		;delay 5 seconds
		call	Delay100W
		return

Delay100W	movwf	count		;delay W x 100mS
d2		call	Delay100	;maximum delay 25.5 seconds
		decfsz	count	,f
		goto	d2
		return

Delay255	movlw	0xff		;delay 255 mS
		goto	d0
Delay100	movlw	d'100'		;delay 100mS
		goto	d0
Delay50		movlw	d'50'		;delay 50mS
		goto	d0
Delay20		movlw	d'20'		;delay 20mS
		goto	d0
Delay10		movlw	d'10'		;delay 10mS
		goto	d0
Delay1		movlw	d'1'		;delay 1mS
		goto	d0
Delay5		movlw	0x05		;delay 5.000 ms (4 MHz clock)
d0		movwf	count1
d1		movlw	0xE7
		movwf	counta
		movlw	0x04
		movwf	countb
Delay_0		decfsz	counta, f
		goto	$+2
		decfsz	countb, f
		goto	Delay_0

		decfsz	count1	,f
		goto	d1
		return

		
		
		ORG StringTable
tbl_string

		ADDWF	PCL, F
		
		dt	"STIAN AAAABBBBCCCCAAAABBBBCCCC          A                   A                   A                   "
		dt	"B                   B                   B                   B                   B                   "
		dt	"D                   D                   D                   D                   D                   "

		
		ORG	FontTable
tbl_font

		MOVWF	PCL

		dt	0x00, 0x00, 0x00, 0x00, 0x00	; 0, Dummy entry
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00
		dt	0x00, 0x00, 0x00, 0x00, 0x00

And yes, I haven't posted my whole list of char data. :)
 

pic16f648a isr

Hi zanor
It sounds like you are having problems with PCLATH. If you do not save PCLATH during an ISR any GOTO/CALL in the ISR may vector to an unexpected address.

Try the following Interupt start & end to ensure correct context saving.
Code:
IntVec	movwf	W_TEMP  ; std context saving
	swapf	STATUS,W      ; ....
	movwf	STATUS_TEMP   ; ....
	movf	PCLATH,W       ; ....
	movwf	PCLATH_TEMP   ; ....
	clrf	PCLATH         ; page0
	clrf	STATUS	      ; bank0
;
;
; ******** interupt routine here ************
;
;
ISRdone
	movf	PCLATH_TEMP,W   	; std context restore
	movwf	PCLATH		      ; ....
	swapf	STATUS_TEMP,W	  ; ....
	movwf	STATUS		      ; ....
	swapf	W_TEMP,F	       ; ....
	swapf	W_TEMP,W	       ; ....
	retfie
;


Do any of your tables cross a 256 word boundary?
If so set table (eg. ADDWF PC,F instruction) at the start of a 256 word boundary
Code:
ORG 0x??00    ; start of table
       ADDWF PC,F
       DT ..................

If your table is longer than 256 words refer to:
Implementing a Table Read
https://ww1.microchip.com/downloads/en/AppNotes/00556e.pdf

Replace 'CALL' with:
Code:
LCALL         ; this sets PCLATH before call
pagesel $     ; this sets PCLATH back to local page

These macros are recognised by MPASM - I do not know about other assemblers.

Hope this helps ... Polymath
 

    zanor

    Points: 2
    Helpful Answer Positive Rating
timer1 pic16f648a

polymath said:
Hi zanor
Try the following Interupt start & end to ensure correct context saving.
Code:
IntVec	movwf	W_TEMP  ; std context saving
	swapf	STATUS,W      ; ....
	movwf	STATUS_TEMP   ; ....
	movf	PCLATH,W       ; ....
	movwf	PCLATH_TEMP   ; ....
	clrf	PCLATH         ; page0
	clrf	STATUS	      ; bank0
;
;
; ******** interupt routine here ************
;
;
ISRdone
	movf	PCLATH_TEMP,W   	; std context restore
	movwf	PCLATH		      ; ....
	swapf	STATUS_TEMP,W	  ; ....
	movwf	STATUS		      ; ....
	swapf	W_TEMP,F	       ; ....
	swapf	W_TEMP,W	       ; ....
	retfie
;

Seriously, I love you! hehe :D Works great now! altleast for the last 15min :)
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top