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.

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.

New Articles From Microcontroller Tips

Back
Top