Question about Danni`s debounce code

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

On this weekend I have decided to play wih debouncing software. I have chosen Danni`s code.
I took a paper and I started to work things out.
After spending few hours on the code this sofware is more or less clear but I have some questions about it :

Below pasting it once again:
I is changed a bit for newer interrupts vectors and I add some comments.

/************************************************************************
;*                                                                      *
;*              Testing Read and debounce up to 8 keys                  *
;*              Bulletproof: 4 equal samples needed                     *
;*                                                                      *
;*              Author: P. Dannegger                                    *
;*                      danni@specs.de                                  *
;*                                                                      *
;***********************************************************************/
#include 
#include 


#define KEY_INPUT       PINC //(PINC>>3)|(PIND>>4))&(0x03)
//How can I set for debouncing PINC3 or PIND5 ???
//As far as I am concern When I am using only PINC I can below choose apropriate mask

#define LED_OUTPUT      PORTB
#define LED_DIR         DDRB

char key_state;                         // debounced and inverted key state:
                                        // bit = 1: key pressed
char key_press;                        // key press detect


ISR(TIMER0_OVF_vect)
{
  static char ct0, ct1;
  char i;

  i = key_state ^ ~KEY_INPUT;           // key changed ?
  ct0 = ~( ct0 & i );                   // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                // reset or count ct1
  i &= ct0 & ct1;                       // count until roll over ?
  key_state ^= i;                       // then toggle debounced state
                                        // now debouncing finished
  key_press |= key_state & i;           // 0->1: key press detect
}


char get_key_press( char key_mask )
{
  cli();
  key_mask &= key_press;                // read key(s)
  key_press ^= key_mask;                // clear key(s)
  sei();
  return key_mask;
}


int main( void )
{	
  key_state = 0;
  key_press = 0;

  TCCR0 = 1<<CS01;                      //divide by 256 * 256
//changed value using 1000000 clock was TCCR0 = 1<<CS02;
  TIMSK = 1<<TOIE0;                     //enable timer interrupt

  LED_DIR = 0xFF;
  LED_OUTPUT = 0xFF;
  sei();
  for(;;)  
  {                                            // main loop
    LED_OUTPUT^=get_key_press( 0xFF );        // toggle LEDs on key press
	
	}	
}


Questions:

1) How can I provide PINC3 and PIND5 to the software debouncer. I have tried my way but it is not working as I thought :/. All I want to do is provide pin states from different ports

2) What do you think about prescaler to the timer0??
When I am using 1000 000 clock I think by 256 is to much.

3) How would you make counter based on this code .
For example when we push one buttom it increases its value and when we press second switch it decrease its value.

Thanks in advance

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

1) How can I provide PINC3 and PIND5 to the software debouncer. I have tried my way but it is not working as I thought :/. All I want to do is provide pin states from different ports

You have two different roads you can go:
i) Combine the input from the two ports, replacing

#define KEY_INPUT       PINC

Something like this

#define KEY_INPUT       (PIND & 1<<5)|(PINC & 1<<3)

You now have the debounced PIND5 in bit 5 and PINC3 in bit 3 in key_state and key_press.

Your attempt does not work, or is running the risk not to work, as there might be a 1 at PIND4 which the OR-operator would propagate and which would show as a "fake PINC3".

Quote:
3) How would you make counter based on this code .

Could you be more specific? Is the problem in the counting? Or in the use of get_key_press()? Or something else?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define KEY_INPUT       ((PIND & 1<<5)|(PINC & 1<<3))

General advice, always make sure the #define can be used in an expression. In this case it is needed (~ has high precedence).
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Eeek! Of-course, Lars! Sloppy me...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey

That`s true that my code was not considereted in 100% but Johan
your code:

#define KEY_INPUT       (PIND & 1<<5)|(PINC & 1<<3)

is not working properly as well.
after 8 interrupts when PINC3 and PIND5 is on the PINC3 goes high.
I don`t know why it is behaving like that.
Just remind you frieds that when I am using only PORTC everything is ok I mean appropriate pins on PORTB goes high after I release buttons.
Maybe Lars is right:

Quote:
General advice, always make sure the #define can be used in an expression.

But how to check it ??

and Lars what did you mean by:

Quote:
In this case it is needed (~ has high precedence). In this case it is needed (~ has high precedence).

~ this is negation why you want to use it ??
I suppose I misunderstood you.

So could you explain me this and extend your solution please ??

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I was missing brackets ;)
I haven`t noticed that your codes are diffrent.
Hmm even details are so important ;)
Now I think I should menage with the "counter"
I wanted to taste debouncer making the counter
Example:
one button pressed:
register++
second button pressed:
register--
and I wanted to display it on diodes ;)

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Ifryd wrote:

I wanted to taste debouncer making the counter
Example:
one button pressed:
register++
second button pressed:
register--
and I wanted to display it on diodes ;)

Adam

Thats, what the function get_key_press was made for.

You must only give the bitmask of the key, which you want to test and it returns non zero, if the key was pressed.

/************************************************************************
;*                                                                      *
;*              Testing Read and debounce up to 8 keys                  *
;*              Bulletproof: 4 equal samples needed                     *
;*                                                                      *
;*              Author: P. Dannegger                                    *
;*                      danni@specs.de                                  *
;*                                                                      *
;***********************************************************************/
#include 
#include 

#define KEY_INPUT       ((PIND & 1<<PD4)|(PINC & 1<<PC3))

#define LED_OUTPUT      PORTB
#define LED_DIR         DDRB

char key_state;                         // debounced and inverted key state:
                                        // bit = 1: key pressed
char key_press;                        // key press detect


ISR(TIMER0_OVF_vect)
{
  static char ct0, ct1;
  char i;

  i = key_state ^ ~KEY_INPUT;           // key changed ?
  ct0 = ~( ct0 & i );                   // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                // reset or count ct1
  i &= ct0 & ct1;                       // count until roll over ?
  key_state ^= i;                       // then toggle debounced state
                                        // now debouncing finished
  key_press |= key_state & i;           // 0->1: key press detect
}


char get_key_press( char key_mask )
{
  cli();
  key_mask &= key_press;                // read key(s)
  key_press ^= key_mask;                // clear key(s)
  sei();
  return key_mask;
}


int main( void )
{ 
  unsigned char i = 0;  
  key_state = 0;
  key_press = 0;

  TCCR0 = 1<<CS01;                      //divide by 256 * 256
//changed value using 1000000 clock was TCCR0 = 1<<CS02;
  TIMSK = 1<<TOIE0;                     //enable timer interrupt

  LED_DIR = 0xFF;
  LED_OUTPUT = 0xFF;
  sei();
  for(;;) 
  {                                            // main loop
    if(get_key_press(1<<PD4))
      i++;
    if(get_key_press(1<<PC3))
      i--;
    LED_OUTPUT = i;
   }   
}

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Peter! Allow me to hijack ever so slightly: If you do a thorough search here you will find that I somewhere have posted "straight forward" debouncing code for a full port (three samples in three byte variables). At the same time I saw your code, thought it was obfuscated, and did nothing more. Last week (while on a boring 3-day course) I had anoher look at it, and I must say that after understanding what you are doing it's a real gem! Thank you for sharing!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Peter,

Thanks for the excellent key debounce code.

Just for the sake of interest, what if I want to use 8 equal samples for the debouncing? What should be the code for ct2?

ISR(TIMER0_OVF_vect)
{
  static char ct0, ct1, ct2;
  char i;

  i = key_state ^ ~KEY_INPUT;           // key changed ?
  ct0 = ~( ct0 & i );                   // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                // reset or count ct1

  ct2 = ct1 ^ (ct2 & i);                // reset or count ct2, << correct???


  i &= ct0 & ct1 & ct2;                 // count until roll over ?
  key_state ^= i;                       // then toggle debounced state
                                        // now debouncing finished
  key_press |= key_state & i;           // 0->1: key press detect
}

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

eblc1388 wrote:

Just for the sake of interest, what if I want to use 8 equal samples for the debouncing? What should be the code for ct2?

  ct2 = (ct0 & ct1) ^ (ct2 & i);

But what do you expect from this change ?

If you have problems on the 4 time debounce, it seems, that your scanning interval was to short.
It should be at least 2ms. 10..50ms should be preferred.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like to say more than thank you for sharing with us this
great code for debouncing. I have already aplied it to my AVR and it works great :)

eblc1388 wrote:
Just for the sake of interest, what if I want to use 8 equal samples for the debouncing? What should be the code for ct2?

Yes I would like to ask this question too.
If you could spill the beans how to make it we all would be on cloud nine ;)

Ups writing posts to slow ;)

Yeah I forgot to ask abbout prescaler for the timer but now when we now about time for intervals everything is clear ;)

danni wrote:
It should be at least 2ms. 10..50ms should be preferred.

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

danni wrote:
But what do you expect from this change ?

That would give me more flexibility and options in choosing a shorter interval for the timer interrupt.

Thanks again for the code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been trying to get mine first real avr project to work. I managed to get debouncing to work ok on mine testboard with one button. I did use variation of dannis code.

Mine problem is basically same than this thread has described. I'm unable call get_key_press() with right bit number. I assume that pinmask is bit number on key_press variable.

So i need bit of help with reading keys on PB3 and PB4 and re

Further on, this code newer reach breakpoint set into get_key_press function, when testing this code with avr studio debugger. Any particular reason for that or feature of debugger?

Hardware is described on inithardware function.

//HammerSTAR II battery level meter and LED driver controller
//Chip:  		ATTiny13
//Clock: 		Internal 9,6Mhz
 

#include 
#include 

#define LED1OFF       PORTB |= (1<<2) 
#define LED1ON        PORTB &= ~(1<<2) 
#define LED1SWAP      PORTB ^= (1<<2)

#define KEY_PIN		((PINB & 1<<3)|(PINB & 1<<4))
#define KEY1		3 
#define KEY2		4 

#define REPEAT_MASK   (1<<KEY1^1<<KEY2) // repeat: key1, key2 
#define REPEAT_START  50                // after 500ms 
#define REPEAT_NEXT   20                // every 200ms 


//Functions
void init_hardware(void);
void DebounceSwitch(void);

unsigned char get_key_press(unsigned char key_mask); 
unsigned char get_key_short(unsigned char key_mask);
unsigned char get_key_rpt(unsigned char key_mask);
unsigned char get_key_long(unsigned char key_mask);  


//Global variables
unsigned char key_state;	// debounced and inverted key state:bit = 1: key pressed             			   
unsigned char key_press;	// key press detect 
unsigned char key_rpt;		// key long press and repeat 


int main (void)
{
	init_hardware();

	// Set OutA, OutB, LED1 to 1 this turns them off
	LED1OFF;
	
	sei(); //  Enable global interrupts

   for (;;){
 
	if (get_key_press( KEY1 )){
		LED1ON;
	}

	if (get_key_press( KEY2 )){
		LED1OFF;
	}
	 
   } 
}

// Timer0 Compare match A interrupt
// Button Debouncer
ISR(TIM0_COMPA_vect)
{
 DebounceSwitch();
}



// Service routine called by a timer interrupt 
void DebounceSwitch(void) {
 
  static unsigned char ct0;  
  static unsigned char ct1;
  static unsigned char rpt; 
         unsigned char i;

    i = key_state ^ ~((PINB & 1<<3)|(PINB & 1<<4));		// Has key changed?
    ct0 = ~( ct0 & i );                  				// reset or count ct0 
    ct1 = ct0 ^ (ct1 & i);               				// reset or count ct1 
    i &= ct0 & ct1;                      				// count until roll over ? 
    key_state ^= i;                      				// then toggle debounced state 
    key_press |= key_state & i;          				// 0->1: key press detect 
	
	if( (key_state & REPEAT_MASK) == 0 ) // check repeat function 
      rpt = REPEAT_START;                // start delay 
    
	if( --rpt == 0 ){                    // Decrease every 10ms until
     rpt = REPEAT_NEXT;                  // repeat delay 
     key_rpt |= key_state & REPEAT_MASK; 
    }    
} // End debounceSwitch
 

unsigned char get_key_press( unsigned char key_mask ) 
{ 
  cli();                  // read and clear atomic ! 
  key_mask &= key_press;  // read key(s) 
  key_press ^= key_mask;  // clear key(s) 
  sei();
  return key_mask; 
} 


unsigned char get_key_rpt( unsigned char key_mask ) 
{ 
  cli();                // read and clear atomic ! 
  key_mask &= key_rpt;  // read key(s) 
  key_rpt ^= key_mask;  // clear key(s) 
  sei(); 
  return key_mask; 
} 


unsigned char get_key_short(unsigned char key_mask ) 
{ 
  cli();         // read key state and key press atomic ! 
  return get_key_press( ~key_state & key_mask ); 
} 


unsigned char  get_key_long(unsigned char key_mask ) 
{ 
  return get_key_press( get_key_rpt( key_mask )); 
} 


void init_hardware(void)
{
//Chip: ATTiny13 clock internal 9,6MHz
//Pin1: ADC0
//Pin2: Digital in K1 		(PB3)
//Pin3: Digital in K2 		(PB4)
//Pin4: GND
//Pin5: Digital out A 		(PB0)
//Pin6: Digital out B 		(PB1)
//Pin7: Digital out LED1	(PB2)
//Pin8: Vcc


// PB3, PB4 As Input pin
	DDRB &= ~(1<<3);		//KEY1
    DDRB &= ~(1<<4);		//KEY2

// PB3,PB4 Activate internal pullUp resistor on input pins
    PORTB |= 1<<DDB3;
    PORTB |= 1<<DDB4;

// PB0, PB1, PB2 as digital out
	DDRB |= 1<<DDB0;
	DDRB |= 1<<DDB1;
	DDRB |= 1<<DDB2;

// Timer0 setup
// CTC mode interrupt every 5ms
//
// Interrupt time = 10 ms (95232 ticks)
// real time = 9.92 ms (95232 ticks)
// error = 6.912000000000035 seconds/day
// prescaler = 1024 (106.666666 us ... 27.3066666 ms)

// Configure timer0 for CTC mode
	TCCR0B |= 1 << WGM02;

// Set prescaler to 1024
	TCCR0B |= 1 << CS00;
	TCCR0B |= 1 << CS02;

// Set CTC compare value to 10ms 
  	OCR0A   = 163; 

// Enable CTC interrupt
	TIMSK0 |= 1<<OCIE0A;

// ADC configuration
// Internal reference 1.1v
// Resolution 10bit
// Single conversion mode
// Sample on every 60s
// Channel 0

// Set prescaler to 64 -> ADC clock 150khz
	ADCSRA &= ~1 << ADPS0;
	ADCSRA |= 1 << ADPS1; 
	ADCSRA |= 1 << ADPS2;

// ADC Voltage reference selection, internal 1.1v
	ADMUX |= 1 << REFS0;

// ADC Channel0
	ADMUX &= ~1 << MUX0;
	ADMUX &= ~1 << MUX1; 

// Disable digital input of pin PB5 (ADC channel0)
	ADCSRB |= 1 << ADC0D;

// Turn ADC on
	ADCSRA |= 1 << ADEN;

} //End init_hardware
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CoolHammer wrote:

#define KEY_PIN		((PINB & 1<<3)|(PINB & 1<<4))

There is no need to mask on this line, it cost only code.

The routine debounce always a whole port, there is no change in code space or SRAM on debouncing 8 pins or only one.

The correct line must be:

#define KEY_PIN		PINB

Masking and oring was only needed, if the used keys are on different ports. So they fit into a single byte.

Furthermore you should avoid subroutine calls inside an interrupt. It may cause saving tons of unused registers (wasting time and SRAM for nothing).

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Last night i managed to get code working. I will remove function call from ISR handling and do some other cleaning also but here is working code.

//HammerSTAR II battery level meter and LED driver controller
//Chip:  		ATTiny13
//Clock: 		Internal 9,6Mhz
 

#include 
#include 

#define LED1OFF       PORTB |= (1<<2) 
#define LED1ON        PORTB &= ~(1<<2) 
#define LED1SWAP      PORTB ^= (1<<2)

#define KEY_PIN		PINB
#define KEY1		3 
#define KEY2		4 

#define REPEAT_MASK   (1<<KEY1^1<<KEY2) // repeat: key1, key2 
#define REPEAT_START  50                // after 500ms 
#define REPEAT_NEXT   20                // every 200ms 


//Functions
static inline void init_hardware(void);
void DebounceSwitch(void);
void dummy(void);


unsigned char get_key_press(unsigned char key_mask)__attribute__ ((noinline)); 
unsigned char get_key_short(unsigned char key_mask)__attribute__ ((noinline));
unsigned char get_key_rpt(unsigned char key_mask)__attribute__ ((noinline));
unsigned char get_key_long(unsigned char key_mask)__attribute__ ((noinline));  


//Global variables
volatile unsigned char key_state;	// debounced and inverted key state:bit = 1: key pressed             			   
volatile unsigned char key_press;	// key press detect 
volatile unsigned char key_rpt;		// key long press and repeat 

int main (void)
{

	volatile unsigned char key1;
	volatile unsigned char key2;

	key_state = 0;
  	key_press = 0; 


	init_hardware();

	// Set OutA, OutB, LED1 to 1 this turns them off
	//LED1OFF;
	
	LED1ON;

	sei(); //  Enable global interrupts

   while (1)
   {
		key1 = get_key_press( 1<<3 );
		key2 = get_key_press( 1<<4 );

		if (key1){
			LED1ON;
		}

		if (key2){
			LED1OFF;
		}

	 
   }// End while
return 0;    
}// End main()


// Timer0 Compare match A interrupt
// Button Debouncer
ISR(TIM0_COMPA_vect)
{
 DebounceSwitch();

}



// Service routine called by a timer interrupt 
void DebounceSwitch(void) {
 
  static unsigned char ct0;  
  static unsigned char ct1;
  static unsigned char rpt; 
  volatile unsigned char i;				 

    i = key_state ^ ~PINB;				 // Has key changed?
    ct0 = ~( ct0 & i );                  // reset or count ct0 
    ct1 = ct0 ^ (ct1 & i);               // reset or count ct1 
    i &= ct0 & ct1;                      // count until roll over ? 
    key_state ^= i;                      // then toggle debounced state 
    key_press |= key_state & i;          // 0->1: key press detect 
	
	if( (key_state & REPEAT_MASK) == 0 ) // check repeat function 
      rpt = REPEAT_START;                // start delay 
    
	if( --rpt == 0 ){                    // Decrease every 10ms until
     rpt = REPEAT_NEXT;                  // repeat delay 
     key_rpt |= key_state & REPEAT_MASK; 
    }    
} // End debounceSwitch
 

unsigned char get_key_press( unsigned char key_mask ) 
{ 
  cli();                  // read and clear atomic ! 
  key_mask &= key_press;  // read key(s) 
  key_press ^= key_mask;  // clear key(s) 
  sei();
  return key_mask; 
} 


unsigned char get_key_rpt( unsigned char key_mask ) 
 { 
  cli();                // read and clear atomic ! 
  key_mask &= key_rpt;  // read key(s) 
  key_rpt ^= key_mask;  // clear key(s) 
  sei(); 
  return key_mask; 
} 


unsigned char get_key_short(unsigned char key_mask ) 
{ 
  cli();         // read key state and key press atomic ! 
  return get_key_press( ~key_state & key_mask ); 
} 


unsigned char  get_key_long(unsigned char key_mask ) 
{ 
  return get_key_press( get_key_rpt( key_mask )); 
} 

// Init hardware.
// Function is called only once so well give compiler a hint to inline it. This saves us few bytes

static inline void init_hardware(void)
{
//Chip: ATTiny13 clock internal 9,6MHz
//Pin1: ADC0
//Pin2: Digital in K1 		(PB3)
//Pin3: Digital in K2 		(PB4)
//Pin4: GND
//Pin5: Digital out A 		(PB0)
//Pin6: Digital out B 		(PB1)
//Pin7: Digital out LED1	(PB2)
//Pin8: Vcc


// PB3, PB4 As Input pin

	DDRB &= ~(1<<3);		//KEY1
    DDRB &= ~(1<<4);		//KEY2

// PB3,PB4 Activate internal pullUp resistor on input pins
    PORTB |= 1<<DDB3;
    PORTB |= 1<<DDB4;

// PB0, PB1, PB2 as digital out
	DDRB |= 1<<DDB0;
	DDRB |= 1<<DDB1;
	DDRB |= 1<<DDB2;

// Timer0 setup
// CTC mode interrupt every 5ms
//
// Interrupt time = 10 ms (95232 ticks)
// real time = 9.92 ms (95232 ticks)
// error = 6.912000000000035 seconds/day
// prescaler = 1024 (106.666666 us ... 27.3066666 ms)

// Configure timer0 for CTC mode
	TCCR0B |= 1 << WGM02;

// Set prescaler to 1024
	TCCR0B |= 1 << CS00;
	TCCR0B |= 1 << CS02;

// Set CTC compare value to 10ms 
  	OCR0A   = 163; 

// Enable CTC interrupt
	TIMSK0 |= 1<<OCIE0A;

// ADC configuration
// Internal reference 1.1v
// Resolution 10bit
// Single conversion mode
// Sample on every 60s
// Channel 0

// Set prescaler to 64 -> ADC clock 150khz
	ADCSRA &= ~1 << ADPS0;
	ADCSRA |= 1 << ADPS1; 
	ADCSRA |= 1 << ADPS2;

// ADC Voltage reference selection, internal 1.1v
	ADMUX |= 1 << REFS0;

// ADC Channel0
	ADMUX &= ~1 << MUX0;
	ADMUX &= ~1 << MUX1; 

// Disable digital input of pin PB5 (ADC channel0)
	ADCSRB |= 1 << ADC0D;

// Turn ADC on
	ADCSRA |= 1 << ADEN;

} //End init_hardware

I think all mine problems were due the compiler was optimizing code quite heavily. Therefore i needed to tell compiler to handle few variables differently. This is done by adding property (is this right term) volatile to these variables.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Danni's (Peter's) code to debounce is great. I've got it sensing 4 different switches on a 1msec interrupt timer and there's not been a single problem.

Thanks for sharing.

Stephen

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all.

I have a question about Danni's debounce code, too.

What if I have two buttons connected to different ports, but the same pins (e.g. PC3 and PD3? How should I change the code to get it working? Is it even possible?

Thank you for advice

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simply merge the 2 bits into a single byte before processing.
In your case, as they are both Px3, you will require a shift/roll operation before the merge.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, this is one of the beauties of Dannis code. Simply replace the "crude" read of the pins

~PINB

with whatever is needed.

Switches are active high? No problem:

~PINB

Switches on high nibble of PORTC and low nibble of PORTD. No problem:

((PINC & 0xF0)| (PIND & 0x0F))

More than eight switches? Just change all those unsigned char to unsigned int to get 16 debounced bits instead of 8.

Etc..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]