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.

To interrupt or not to interrupt? [PIC12F629]

Status
Not open for further replies.

Gnome

New Member
So right now with the previous help my program is working properly. Now comes on of the larger debates that I have read about. Should interrupts be used for button detection or should I just use code. Now there is a part in my program were the PIC will goto sleep and wait for the WDT to awaken it, however I would like a button press to awaken the PIC early, to trigger an event, if need be. From what I understand only an interrupt can accomplish this.

Should I use code to detect a button press and the interrupt or just use the interrupt?

-Ken
 
While you generally need an interrupt "event" to wake up from sleep, you don't necessarily need to implement interrupts. For example, use IOC (interrupt on change) to detect a push-button state change and wake up from sleep but then poll and debounce the switch normally (don't enable global interrupts).

Regards, Mike

Code:
;
;  Copyright © 2010, Mike McLaren, Micro Application Consultants
;
suspend
        movf    GPIO,W          ; clear IOC mismatch condition    |B0
        bcf     INTCON,GPIF     ; clear IOC interrupt flag bit    |B0
        sleep                   ; sleep, wait for IOC interrupt   |B0
        nop                     ;                                 |B0
dbounce
        DelayCy(16*msecs)       ; 16-msec debounce interval       |B0
        comf    GPIO,W          ; sample active-lo switches       |B0
        andlw   b'00011000'     ; on GP4 and GP3 pins             |B0
        xorwf   swold,W         ; changes, press or release       |B0
        xorwf   swold,F         ; update switch state latch       |B0
        andwf   swold,W         ; filter out "new release" bits   |B0
        skpnz                   ; a "new press"? yes, skip, else  |B0
        goto    suspend         ; branch (sleep)                  |B0
        movwf   swnew           ; save "new press" bits           |B0

sw3
        btfss   swnew,3         ; sw3 press?  yes, skip, else     |B0
        goto    sw4             ; branch                          |B0
        nop                     ; perform "sw3" code here         |B0

sw4
        btfss   swnew,4         ; sw4 press?  yes, skip, else     |B0
        goto    swxit           ; branch                          |B0
        nop                     ; perform "sw4" code here         |B0

swxit
        goto    suspend         ; debounce release after sleep    |B0
;       goto    debounce        ; debounce release before sleep   |B0
 
Last edited:
It seems the software that I'm using doesn't simulate sleep, I'll have to wait until my PIC programmer comes in.

I did have a question about debouncing, why not just use the GPIF and btfsc to execute the button press code?

psuedo-code:
interrupt vector
delay of 24ms
btfsc GPIO, pin_3
goto action
bcf INTCON,0
retie

Wouldn't that allow the button to settle and then detect if it was still being pressed? Granted this is for non-simultaneous button presses.
 
I replaced the RBIF label with the correct GPIF label. Sorry.

I'm sorry, I don't understand what you're trying to do. Why would you want to execute a "goto" instruction or a 24-msec delay routine within an interrupt service routine?
 
I replaced the RBIF label with the correct GPIF label. Sorry.

I'm sorry, I don't understand what you're trying to do. Why would you want to execute a "goto" instruction or a 24-msec delay routine within an interrupt service routine?

As a note "goto" might have confused things, I just typed it as pseudo-code. I would call in the normal code. Is it bad to use a call in an interrupt? I thought that interrupts were used to call new functions.
 
As a note "goto" might have confused things, I just typed it as pseudo-code. I would call in the normal code. Is it bad to use a call in an interrupt? I thought that interrupts were used to call new functions.

Interrupts should be as short and fast as possible - and you certainly shouldn't call delay routines in one - in fact try and avoid subroutines in ISR's if you can, as stack space is VERY limited.

If you want an interrupt triggered delay, use the ISR to set a flag, and monitor the flag in the main program loop.
 
Well here is my code. Basically the PIC outputs a code and goes to sleep, wakes and repeats. If a button is pressed a modified code is output instead.

Code:
;First test run
;Microcontroller model: PIC12F629
;Clock Frequency 4.0 MHz
;Configuration Word: 31E9h
;
;*****[ Variables ]*****
	MOD_1	equ 0x55
	MOD_2	equ 0x56
	CODE	equ 0xAA
	Pin_7	equ 0
	Pin_6	equ 1
	Pin_5	equ 2
	fileA	equ 26h
	fileB	equ 27h
	fileC	equ 28h
	count	equ 29h
	Button1	equ 30h
	Button2	equ 31h
;
;===========================================================================
	org	0x0000		; 	Program Origin at mem location 0
	bcf	PCLATH,3
	bcf	PCLATH,4
	goto	L0001
	org	0x0004		;	Interrupt Location
	btfsc	GPIO,Pin_6	;	Checks if button one was pressed
	call	L0004
	btfsc	GPIO,Pin_5	;	Checks if button two was pressed
	call	L0005
;L0000:
;Continue Interrupt by initializing
	bcf	INTCON,0	;	Clears interrupt
	movlw	8		;	resets original loop counter
	movwf	count		;	and stores, then resets original
	movlw	CODE		;	CODE back into fileC
	movwf	fileC
	retfie
;---------------------------------------------------------------------------
L0001:				
;Initialization
	clrw
	bcf	STATUS,RP0	;	Bank 0
	clrf	TMR0		;	Clear Timer 0
;
;Set GPIO
;
;
	clrf	GPIO		;	Init GPIO
	movlw	07h		;	Set GP<2:0> to
	movwf	CMCON		;	digital IO
	bsf	STATUS,RP0	;	Bank 1
	movlw	06h		;	Set GP<2:1> as inputs
	movwf	TRISIO		;	and set GP<5:3, 0>
				;	as outputs
	movlw	8Fh		;	Turn off T0CKI,
	movwf	OPTION_REG	;	prescaler for WDT = 1:128
;
;Set Interrupts
;
	movlw	06h		;	Set IOC<2:1> to
	movwf	IOC		;	interrupt on change
				;	for button presses
;
	movlw	88h		;	Set INTCON<7,3> to
	movwf	INTCON		;	trigger interrupts
	bcf	STATUS,RP0	;	Bank 0
;
;===========================================================================
L0002:
;Main Program Start
	movlw	CODE		;	Stores the code in register W
	movwf	fileC		;	Moves CODE to file A
	bcf	INTCON,7	;	Disables GIE interrupt
	call	L0003
	bsf	INTCON,7	;	Enables GIE interrupt
	call	L0010
	goto	L0002		;	Repeat forever
;
;---------------------------------------------------------------------------
L0003:
;Serial Code output
	bcf	STATUS,0	;	Clears the carry bit
	movlw	8
	movwf	count
SLoop	btfss	fileC,0
	bcf	GPIO,Pin_7
	btfsc	fileC,0
	bsf	GPIO,Pin_7
	rrf	fileC,1
	call	L0006
	decfsz	count,1
	goto	SLoop
	bcf	GPIO,Pin_7
	call   	L0006
	return
;
;---------------------------------------------------------------------------
L0004:
;Button One Pressed
	bsf	Button1,0	;	Troubleshooting viewable change
;	call	L0006
	movlw	CODE
	addlw	MOD_1
	movwf	fileC
	call	L0003
	bcf	Button1,0	;	Troubleshooting viewable change
	return
;
;---------------------------------------------------------------------------
L0005:
;Button Two Pressed
	bsf	Button2,0	;	Troubleshooting viewable change
;	call	L0006
	movlw	CODE
	addlw	MOD_2
	movwf	fileC
	call	L0003
	bcf	Button2,0	;	Troubleshooting viewable change
	return
;
;---------------------------------------------------------------------------
L0006:
;Delay Function 200ms
	movlw	01h		;	Change to 9Eh after testing
	movwf	fileB
DelB	movlw	01h		;	Change to FDh
	movwf	fileA	 
DelA	decfsz  fileA,1 
	goto	DelA 
	decfsz  fileB,1 
	goto    DelB
	return
;
;---------------------------------------------------------------------------
L0007:
;Debouncer
	
;
;---------------------------------------------------------------------------
L0010:
;SLEEP function
	movf	GPIO,w		;	Stores GPIO in w so
				;	changes can be compared
	bcf	INTCON,0	;	Clears GPIF
;	sleep
	return
;
;---------------------------------------------------------------------------


	END

So should I redo the interrupt portion to remove the call instructions?
 
It depends on how many stack levels your main program uses. The 12F629 has a 8 level deep stack. The interrupt itself uses 1 level and your call's from within the interrupt uses another - so that's 2 stack levels for the Interrupt service routine. Since a interrupt can occur at any time this means you can only nest your main program 6 levels deep. If that is enough for your purposes, then it's fine the way it is.
 
Alright, I made sure to keep things tidy. The program should only go 6 levels at the max. during the interrupt and 2 during normal operation.
 
The interrupt includes the other two, so I have two levels left. But even if I used all 8 my program should take that into account ( If I am a good programmer ) and not overflow. Also any of you have a PIC programmer? I still have yet to test it on a real PIC. Yay for waiting on a package....
 
Status
Not open for further replies.

Latest threads

Back
Top