Problem with delay loop - 16f628

Status
Not open for further replies.

gregmcc

Member
I've used one of the pic delay calculators to generate a delay of 10 seconds. If I use this in a simple led blink routine it works. I'm now using using it in my program however and am having problems.

What the program does is the following:
I"m using RB0 interrupt to increment a counter every time its triggered. In the main program whenever the counter reaches 10, I pulse a LED. This bit works 100%

Where the problem now comes in, is in my main loop of the program every 10 seconds I want to blink another led (eventually this will be replaced with a serial output routine)

The problem is this 10 second led is never pulsed. Am I missing something obvious?
The problem is probably somewhere around the carryon label, but for the life of me I can't figure it out.

Code:
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__CONFIG 0x3F34

;--------------------------------------------------------------------------------------
; Variables
;--------------------------------------------------------------------------------------

	cblock 	0x20 			;start of general purpose registers
		count1 			;used in delay routine
		count2 			;used in delay routine 
		
		count4
		count5 			;used in delay routine 
		count6 			;used in delay routine
		count7
		TEMP			; temp variable for w register
		flash_count		; number of flashes
	endc
	
	org	0x0000			;org sets the origin, 0x0000 for the 16F628,
					;this is where the program starts running	

	goto start

;--------------------------------------------------------------------------------------
; Interrupt
;--------------------------------------------------------------------------------------
	
	org 0004h		; interrupt routine
	movwf TEMP		; store value of w in temp
	incf flash_count,1	; increment flash count

	bsf	PORTB,	2		;turn on RB7 only!
	call	Delay100ms			;this waits for a while!
	bcf	PORTB,	2		;turn off RB7 only!.

	bcf	INTCON, INTF	; clear interrupt flag
	movfw TEMP		; restore value of w
	retfie			; end of routine

;--------------------------------------------------------------------------------------
; Main
;--------------------------------------------------------------------------------------

start
	; setup RB0 as a interrupt
	bsf INTCON,GIE	; GIE - global interrupt enable
	bsf INTCON,INTE	; INTE - RB0 - interrupt enable

	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84

   	bsf 	STATUS,		RP0	;select bank 1
   	movlw 	b'00000001'		
   	movwf 	TRISB			; set RB0 as input


	movlw  b'00010000';
	movwf	TRISA			;set first 4 pins on PortA as outputs

	bcf	STATUS,		RP0	;select bank 0
	clrf	PORTA
	clrf	PORTB			;set all outputs low

	;setup variables for 10 sec loop
	movlw 0x5a
	movwf count4
	movlw 0xcd
	movwf count5
	movlw 0x16
	movwf count6


Loop	

	; when count = 10 pulse LED
	movlw 0x0a
	subwf flash_count,0
	btfss STATUS,0
	goto carryon
	
	bsf	PORTB,	1		

	call	Delay100ms			
	bcf	PORTB,	1		
	clrf flash_count	


carryon

	decfsz	count4,1
	goto $+2
	decfsz	count5,1
	goto $+2
	decfsz 	count6,1
	goto Loop

;10 secs reached
	bsf PORTB,  3				; pulse 10 second timer led
	call	Delay100ms			
	bcf	PORTB,3

	goto	Loop			;go back and do it again

;-------------------------------------------------------------------
;Delay 100ms
;-------------------------------------------------------------------

Delay100ms
			;199993 cycles
	movlw	0x3E
	movwf	count1
	movlw	0x9D
	movwf	count2
Delay100ms_0
	decfsz	count1, f
	goto	$+2
	decfsz	count2, f
	goto	Delay100ms_0
	return


	end
 
Last edited:
Without studying the code much, I would suggets it's a VERY, VERY bad idea to be calling a delay routine from within the ISR, particularly one which is also called outside the ISR.

There really seems no reason to be using an ISR anyway, it's a trivial task to do with polling.

If you want to use the ISR, use it to set a flag, and let your main program poll that flag - keep ISR's short and efficient.
 
Nigel - thanks for the info. I"ll have a look at using polling. It sounds easier to do anyway. Your right though, as I'm going to be calling a routine to do a serial comms to the PC and if it keeps getting interrupted by the ISR with a delay routine in it then it will most likely never work.

I think I"ve also figured out my problem - I've modified the simple 10 sec delay routine and in the loop put in a flash led routing which adds in another 200ms or so to the delay routine. This will probably turn the 10 sec delay routing into a 10 min routine
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…