I have interfaced a matrix keypad with the xmega a3bu and have configured it with usb cdc protocol, but when i see the key pressed data in the real term, if click a button once its displaying multiple times(as shown in the image). Any suggestions on what i should do to prevent it?
One click leading to displaying multiple time on the real term
Looks like a missing semi-colon on line 47 ;-)
Seriously, how do you expect anyone to suggest a fix without showing the code?
oops,my bad.
#define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> #include <asf.h> void row_col1(void); void row_col2(void); void row_col3(void); void row_col4(void); void row1_col(void); void row2_col(void); void row3_col(void); void row4_col(void); void row1_col1(void); void row2_col2(void); void row3_col3(void); void row4_col4(void); void col1(void); void col2(void); void col3(void); void col4(void); void blink(void); unsigned int blinkduration = 0; /** * \brief main function */ int main (void) { PORTC.DIRCLR = 0x0F; PORTC.DIRSET = 0xF0; PORTR.DIRSET = 0x03; PORTR_OUTSET = 0x03; PORTD_DIRSET = 0x20; PORTD_OUTCLR = 0x20; #if SAMD21 || SAMR21 /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clocks.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ system_init(); #else /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clock.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ sysclk_init(); board_init(); #endif // Initialize interrupt vector table support. irq_initialize_vectors(); // Enable interrupts cpu_irq_enable(); /* Call a local utility routine to initialize C-Library Standard I/O over * a USB CDC protocol. Tunable parameters in a conf_usb.h file must be * supplied to configure the USB device correctly. */ stdio_usb_init(); // Get and echo characters forever. while (true) { row_col1(); _delay_ms(10); row_col2(); _delay_ms(10); row_col3(); _delay_ms(10); row_col4(); _delay_ms(10); row1_col(); _delay_ms(10); row2_col(); _delay_ms(10); row3_col(); _delay_ms(10); row4_col(); _delay_ms(10); row1_col1(); _delay_ms(10); row2_col2(); _delay_ms(10); row3_col3(); _delay_ms(10); row4_col4(); _delay_ms(10); col1(); _delay_ms(10); col2(); _delay_ms(10); col3(); _delay_ms(10); col4(); _delay_ms(10); } } void row_col1() { PORTC.OUTSET = 0x20; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xD0; if(((PORTC.IN & 0x01)==0b00000001)&&((PORTC.IN & 0x2F)==0b00100000)) //1 { printf("1"); } } void row_col2() { PORTC.OUTSET = 0x40; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xB0; if(((PORTC.IN & 0x01))&&((PORTC.IN & 0x4F)==0b01000000)) //2 { printf("2"); } } void row_col3() { PORTC.OUTSET = 0x80; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0x70; if(((PORTC.IN & 0x01))&&((PORTC.IN & 0x8F)==0b10000000)) //3 { printf("3"); } } void row_col4() { PORTC.OUTSET = 0x10; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xE0; if(((PORTC.IN & 0x01))&&((PORTC.IN & 0x1F)==0b00010000)) //4 { printf("4"); } } /////////////////////////////////////////////////////////////////////////////////////// void row1_col() { PORTC.OUTSET = 0x20; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xD0; if(((PORTC.IN & 0x02))&&((PORTC.IN & 0x2F)==0b00100000)) //5 { printf("5"); } } void row2_col() { PORTC.OUTSET = 0x40; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xB0; if(((PORTC.IN & 0x02))&&((PORTC.IN & 0x4F)==0b01000000)) //6 { printf("6"); } } void row3_col() { PORTC.OUTSET = 0x80; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0x70; if(((PORTC.IN & 0x02))&&((PORTC.IN & 0x8F)==0b10000000)) //7 { printf("7"); } } void row4_col() { PORTC.OUTSET = 0x10; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xE0; if(((PORTC.IN & 0x02))&&((PORTC.IN & 0x1F)==0b00010000)) //8 { printf("8"); } } ////////////////////////////////////////////////////////////////////////////////////////////////////// void row1_col1() { PORTC.OUTSET = 0x20; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xD0; if(((PORTC.IN & 0x04))&&((PORTC.IN & 0x2F)==0b00100000)) //9 { printf("9"); } } void row2_col2() { PORTC.OUTSET = 0x40; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xB0; if(((PORTC.IN & 0x04))&&((PORTC.IN & 0x4F)==0b01000000)) //10 { printf("10"); } } void row3_col3() { PORTC.OUTSET = 0x80; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0x70; if(((PORTC.IN & 0x04))&&((PORTC.IN & 0x8F)==0b10000000)) //11 { printf("11"); } } void row4_col4() { PORTC.OUTSET = 0x10; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xE0; if(((PORTC.IN & 0x04))&&((PORTC.IN & 0x1F)==0b00010000)) //12 { printf("12"); } } ////////////////////////////////////////////////////////////////////////////////// void col1() { PORTC.OUTSET = 0x20; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xD0; if(((PORTC.IN & 0x08))&&((PORTC.IN & 0x2F)==0b00100000)) //13 { printf("13"); } } void col2() { PORTC.OUTSET = 0x40; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xB0; if(((PORTC.IN & 0x08))&&((PORTC.IN & 0x4F)==0b01000000)) //14 { printf("14"); } } void col3() { PORTC.OUTSET = 0x80; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0x70; if(((PORTC.IN & 0x08))&&((PORTC.IN & 0x8F)==0b10000000)) //15 { printf("15"); } } void col4() { PORTC.OUTSET = 0x10; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xE0; if(((PORTC.IN & 0x08))&&((PORTC.IN & 0x1F)==0b00010000)) //16 { printf("16"); } }
I don't see anything in there to debounce your keypad.
Does a delay before every printf function help to prevent debounce?
Does a delay before every printf function help to prevent debounce?
No.
To debounce a signal you need to read it, wait, read it again, and then, if both reads returned the same value, process that value as being debounced. You need the signal to be stable in one state, or the other, for a period of time.
Can you tell me how to implement it in xmega a3bu?
In xmega a3bu, it is exactly same way as mega 328P or a tiny 2313.
Here is the like to the definitive description of switch bounce and how to manage it in software, not specific to any particular MCU:
http://www.ganssle.com/debouncin...
Jim
I don't think Ganssle mentions the method I use which is 'vertical counters'...
https://www.compuphase.com/elect...
...which is very code efficient. I run the code inside a timer ISR running at 5-10ms.
I like it because as written it does a full 8-bit port in one go but can also be easily scaled to 16, 24, or even 32 bits wide.
the method I use which is 'vertical counters'...
Cliff
can you suggest me a sample code. I'm not understanding on how to proceed?
can you suggest me a sample code. I'm not understanding on how to proceed?
Have you read the Ganssle articles? Have you searched for 'denounce vertical counters'?
I denounce vertical counters!
I denounce vertical counters!
Ah, caught out by my phone's autocorrect.
void row_col1() { PORTC.OUTSET = 0x20; PORTC.OUTCLR = 0x0F; PORTC_OUTCLR = 0xD0; if(((PORTC.IN & 0x01)==0b00000001)&&((PORTC.IN & 0x2F)==0b00100000)) //1 { timeout_start_singleshot(0,10); } // Check for debounce timeout expire if (timeout_test_and_clear_expired(10)) { // Toggle LED0 if button is pressed down if (((PORTC.IN & 0x01)==0b00000001)&&((PORTC.IN & 0x2F)==0b00100000)) { PORTR_OUTCLR = PIN0_bm; _delay_ms(100); PORTR_OUTSET = PIN0_bm; }
Here I've used a timeout function for my debounce code, I'm ticking 10 times and checking again if the button is pressed, but it does not seem to work.
You really are making something simple into a complex mess. You’re supposed to sample the input ten times!
Shouldn't it be done using ticking like above.I'm checking the button after 10 ticks again.
Thank you!