Davies MSP430 Software Debounce  - Page 1
Forum section: electronics / general

author: Mattjd
author_rank: Regular Contributor
timestamp: October 13, 2017, 06:24:14 am
content: Hello All,I've been looking at Davies MSP430 Ebook, specifically the software debounce section.The code isCode:// debtim1.c - press button B1 to light LED1 with debounce// Samples input at 5 ms intervals set by Timer_A, 32KHz ACLK// Shift reg for debounce, different thresholds for press and release// Olimex 1121STK board, LED1 active low on P2.3,// button B1 active low on P2.1// J H Davies, 2007-04-10; IAR Kickstart version 3.42A//----------------------------------------------------------------------#include <io430x11x1.h>// Specific device#include <intrinsics.h>// Intrinsic functions#include <stdint.h>// Standard integer typesunion {// Debounced state of P2INunsigned char DebP2IN;// Complete bytestruct {unsigned char DebP2IN_0 : 1;unsigned char DebP2IN_1 : 1;unsigned char DebP2IN_2 : 1;unsigned char DebP2IN_3 : 1;unsigned char DebP2IN_4 : 1;unsigned char DebP2IN_5 : 1;unsigned char DebP2IN_6 : 1;unsigned char DebP2IN_7 : 1;} DebP2IN_bit;// Individual bits};#define RAWB1P2IN_bit.P2IN_1#define DEBB1DebP2IN_bit.DebP2IN_1#define LED1P2OUT_bit.P2OUT_3void main (void){WDTCTL = WDTPW | WDTHOLD;// Stop watchdog timerP2OUT_bit.P2OUT_3 = 1;// Preload LED1 off (active low!)P2DIR_bit.P2DIR_3 = 1;// Set pin with LED1 to outputDebP2IN = 0xFF;// Initial debounced state of portTACCR0 = 160;// 160 counts at 32KHz = 5msTACCTL0 = CCIE;// Enable interrupts on Compare 0TACTL = MC_1|TASSEL_1|TACLR;// Set up and start Timer A// "Up to CCR0" mode, no clock division, clock from ACLK, clear timerfor (;;) {// Loop forever__low_power_mode_3();// Enter LPM3, only ACLK active// Return to main function when a debounced transition has occurredLED1 = DEBB1;// Update LED1 from debounced button}}//----------------------------------------------------------------------// Interrupt service routine for Timer A chan 0; no need to acknowledge// Device returns to LPM3 automatically after ISR unless input changes// PRESS_THRESHOLD = 0x3F = 0b00111111, needs 2 successive 0s (enough?)// RELEASE_THRESHOLD = 0xFC = 0b11111100, 6 successive 1s (too many?)//----------------------------------------------------------------------#define PRESS_THRESHOLD0x3F#define RELEASE_THRESHOLD0xFC#pragma vector = TIMERA0_VECTOR__interrupt void TA0_ISR (void){static uint8_t P21ShiftReg = 0xFF;// Shift reg for history of P2.1P21ShiftReg >>= 1;// Update history in shift registerif (RAWB1 == 1) {// Insert latest input from B1P21ShiftReg |= BIT7;// Set msb if input high}if (DEBB1 == 0) {// Current debounced value low, looking for input to go high (release)if (P21ShiftReg >= RELEASE_THRESHOLD) {// button releasedDEBB1 = 1;// New debounced state high__low_power_mode_off_on_exit();// Wake main routine}} else {// Current debounced value high, looking for input to go low (press)if (P21ShiftReg <= PRESS_THRESHOLD) {// button pressedDEBB1 = 0;// New debounced state low__low_power_mode_off_on_exit();// Wake main routine}}}my code on msp430fr6989Code:#include <msp430.h>#include <intrinsics.h> // Intrinsic functions#include <stdint.h> // Standard integer typesunion DebP2IN{ // Debounced state of P2INunsigned char byte; // Complete bytestruct bit {unsigned char DebP2IN_0 : 1;unsigned char DebP2IN_1 : 1;unsigned char DebP2IN_2 : 1;unsigned char DebP2IN_3 : 1;unsigned char DebP2IN_4 : 1;unsigned char DebP2IN_5 : 1;unsigned char DebP2IN_6 : 1;unsigned char DebP2IN_7 : 1;} bit1; // Individual bits} DebP2IN1; //both DebP2INx, bitx, refer to buttons.#define BUTTON1_PRESSED() !(P1IN & BIT1)#define DEBB1() DebP2IN1.bit1.DebP2IN_1#define LED1_ON() P1OUT |= BIT0; //P1.0 LED ON#define LED1_OFF() P1OUT &= ~BIT0; //P1.0 LED OFFvoid main (void){WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerPM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance modeP1OUT &= ~BIT0; //Pre-load LED P1.0 OffP1DIR |= BIT0; //Set P1.0 LED to outputP1DIR &= ~BIT1; //set P1.1 button to inputP1REN |= BIT1; //Enable Resistor Button P1.1P1OUT |= BIT1; //Set as Pullup resistor Button P1.1DebP2IN1.byte = 0xFF; //initialize debounce state of P1.1TA0CCR0 = 5000; // TA0 interrupt triggers every 5 msTA0CCTL0 |= CCIE; //Enable TA0 interruptTA0CTL |= (TASSEL_2 + MC_1 + TACLR); //SMCLK (1mhz) count to CCR0, clear timer__enable_interrupt();for(;;){if(DEBB1() == 1) //Update LED1 from debounced button{LED1_ON();}else if (DEBB1() == 0){LED1_OFF();}}}#define PRESS_THRESHOLD 0x3F#define RELEASE_THRESHOLD 0xFC#pragma vector = TIMER0_A0_VECTOR__interrupt void TA0_ISR (void){static uint8_t P11ShiftReg = 0xFF; // Shift Reg for history of P1.1P11ShiftReg >>= 1; // Update history in shift registerif (BUTTON1_PRESSED()) //Insert latest input from P1.1{P11ShiftReg |= BIT7; //Set MSB of Shiftreg P1.1 to 1}if (DEBB1() == 0) //when debounce value is low{if(P11ShiftReg >= RELEASE_THRESHOLD) //when button is released{DEBB1() = 1; //set new debounce state high}}else if(P11ShiftReg <= PRESS_THRESHOLD) //when debounce value is high and button is pressed{DEBB1() = 0; //set new debounce state low}}I'm understanding it, I think. When the button is pressed, the shift register in the ISR gets filled with ones. This causes DEBB1 to go high and due to the polling in main.c it turns on the LED. Once the button is released, shiftreg will eventually shift below Press_threshold and DEBB1 goes to zero, causing the LED to turn back off.What I am really confused about, is that if (in my code)DEBB1 = DebP2IN1.bit1.DebP2IN_1andDebP2IN1.bit1.DebP2IN_1 = 1as declared in the structurethen how does it ever get to zero for the conditionalif (DEBB1() == 0) to be true?Also, What is the significance of this lineCode:DebP2IN1.byte = 0xFF; //initialize debounce state of P1.1In my code, because DebP2IN1.byte gets used no where. At all.

author: ez24
author_rank: Super Contributor
timestamp: October 14, 2017, 05:50:27 am
content: watching

author: Fiki
author_rank: Newbie
timestamp: October 16, 2017, 08:03:17 am
content: Hi,I believe it's actually the other way around.Initially, the shift register is filled with ones and when the button is pressed, it gets filled with zeros. The button is active at low state.I would try to change the condition in ISR to:Code:if (P1IN & BIT1) // Button released, P1.1 at high state{P11ShiftReg |= BIT7; //Set MSB of Shiftreg P1.1 to 1}BIT7 of P11ShiftReg should be set if button is released.Fiki