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.

Switch Debouncing Steps Correct?

Status
Not open for further replies.

Drew C.

New Member
I'm using a pic16f627a, i have a switch connected to the External interrupt INT, I want to debounce that using a delay of ~50ms using the Timer0 interrupt.
How do I do that?
From what I understand, when the external interrupt is generated, in the interrupt service routine, I should
1. Disable the external interrupt by clearing INTE
2.I should set a counter equivalent to that 50ms
3. I set a debounced flag to 0.
4. In the Timer0 interrupt routine, I decrement that counter, and then if it's 0, then I set the debounced flag to 1.
5. Back in the external interrupt routine, I wait until the debounced flag is set to 1
6. If it's 1, then I do whatever I want to do(light on led or something), then clear the the INTF flag
7. Reenable the interrupt by setting INTE

Is that correct?
Somehow this seems logical to me, but it doesn't work, it just seems to be stuck somewhere, could someone please help? :roll:
 
Hi drew,,
i am not an expert at programming pics ,but i dont think you have to do it that way..
if you disable interrupts how is the int pin going to work...?
 
this small pgm reads switches
it is from Nigels site..

it uses polling process..not interrupts .

Code:
;Tutorial 2.1 - Nigel Goodwin 2002
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)


LEDPORT	Equ	PORTA			;set constant LEDPORT = 'PORTA'
SWPORT	Equ	PORTA			;set constant SWPORT = 'PORTA'
LEDTRIS	Equ	TRISA			;set constant for TRIS register
SW1	Equ	7			;set constants for the switches
SW2	Equ	6
SW3	Equ	5
SW4	Equ	4
LED1	Equ	3			;and for the LED's
LED2	Equ	2
LED3	Equ	1
LED4	Equ	0

;end of defines
	
	org	0x0000			;org sets the origin, 0x0000 for the 16F628,
					;this is where the program starts running	
	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84)

   	bsf 	STATUS,		RP0	;select bank 1
   	movlw 	b'11110000'		;set PortA 4 inputs, 4 outputs
   	movwf 	LEDTRIS
	bcf	STATUS,		RP0	;select bank 0
	clrf	LEDPORT			;set all outputs low


Loop	btfss	SWPORT,	SW1
	call	Switch1
	btfss	SWPORT,	SW2
	call	Switch2
	btfss	SWPORT,	SW3
	call	Switch3
	btfss	SWPORT,	SW4
	call	Switch4
	goto	Loop

Switch1	clrf	LEDPORT			;turn all LED's off
	bsf	SWPORT,	LED1		;turn LED1 on
	retlw	0x00

Switch2	clrf	LEDPORT			;turn all LED's off
	bsf	SWPORT,	LED2		;turn LED2 on
	retlw	0x00

Switch3	clrf	LEDPORT			;turn all LED's off
	bsf	SWPORT,	LED3		;turn LED3 on
	retlw	0x00

Switch4	clrf	LEDPORT			;turn all LED's off
	bsf	SWPORT,	LED4		;turn LED4 on
	retlw	0x00


	end
 
Page 106 of pdf...


When an interrupt is responded to, the GIE is cleared
to disable any further interrupt, the return address is
pushed into the stack and the PC is loaded with 0004h.
Once in the interrupt service routine the source(s) of
the interrupt can be determined by polling the interrupt
flag bits. The interrupt flag bit(s) must be cleared in
software before re-enabling interrupts to avoid RB0/
INT recursive interrupts.

could you post your code ?
have you pointed to your interrupt service routine in location 0004h..?
 
Drew C. said:
1. Disable the external interrupt by clearing INTE
2.I should set a counter equivalent to that 50ms
3. I set a debounced flag to 0.
4. In the Timer0 interrupt routine, I decrement that counter, and then if it's 0, then I set the debounced flag to 1.
5. Back in the external interrupt routine, I wait until the debounced flag is set to 1
6. If it's 1, then I do whatever I want to do(light on led or something), then clear the the INTF flag
7. Reenable the interrupt by setting INTE

Is that correct?
Somehow this seems logical to me, but it doesn't work, it just seems to be stuck somewhere, could someone please help? :roll:

Two things:
1. I understand what you are doing by clearing INTIE to inhibit further bounce-triggered interrupts. You can and should clear the INTIF flag and re-enable that interrupt in the TMR0 ISR when the timer expires. It is pointless and problematic to put this elsewhere.
2. However, this strategy has a flaw. Say your button has a pullup so that you trigger on the falling edge of the pin If the user holds down the button for more than 50 mS and then releases it, it will initially be a rising edge but this is inevitably followed by bounces full of both rising and falling edges, so you get a spurious second interrupt.
The fix: In the TMR0 ISR, when the debounce counter>0, also check the value of the pin. If it's low (button is held down), just reset the counter to 50mS. Thus the user MUST release the button and the counter will wait the requisite 50mS of clean low time before reenabling INT0.

There is a minor difference to this method, the wait is now from when the button is released PLUS any detected bouncing time PLUS 50mS. You may want to decrease the debounce period since most bouncing will likely be detected.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top