Hot!debouncing in 12F675

Author
Andy_Taiwanese
Super Member
  • Total Posts : 508
  • Reward points : 0
  • Joined: 2014/12/19 02:59:38
  • Location: 0
  • Status: offline
2018/03/13 19:29:39 (permalink)
0

debouncing in 12F675

Hi, there.
This is the first time using 12F675 ,and I'm implementing the debouncing by timer.
Because I can't go in debug session now, may I need you guys to help me review this little code?
(I tried to click "Project proerties -> Supported debug header -> Choose AC162050, but didn't work, it popped up this image(attachment)
 
main.c
void main(void) {
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    
    while(1){
        
        
    }//end of while
}//end of main

 
interrupt_manager.c
volatile uint8_t PIN_Gp4StateNow;
volatile uint8_t PIN_Gp4StateNext;

volatile uint8_t PIN_STATE;



void interrupt INTERRUPT_InterruptManager (void){
    if(INTCONbits.T0IE == 1 && INTCONbits.T0IF == 1){
        INTCONbits.T0IF = 0;
        
        PIN_Gp4StateNow = PIN_Gp4StateNext;
        PIN_Gp4StateNext = GPIObits.GP4;
        
        PIN_STATE = PIN_STATE << 1;
        
        if(PIN_Gp4StateNow == PIN_Gp4StateNext == HIGH) PIN_STATE || 1;
        else if(PIN_Gp4StateNow == PIN_Gp4StateNext == LOW) PIN_STATE || 0;
        
        if(PIN_STATE && 0b00000111 == 0b00000100) ~GPIObits.GP5;
        
    }
}

oscillator_manager.c
void OSCILLATOR_MANAGER_Initialize(void){
    OSCCAL = 0b10000000; // OSCCAL — OSCILLATOR CALIBRATION REGISTER (ADDRESS: 90h)
                                // bit 7-2 CAL5:CAL0: 6-bit Signed Oscillator Calibration bits
                                    // 111111 = Maximum frequency
                                    // 100000 = Center frequency
                                    // 000000 = Minimum frequency
                                // bit 1-0 Unimplemented: Read as '0'
}

pin_manager.c
void PIN_MANAGER_Initialize(void){
    /**
    TRIS registers
    */
    TRISIO = 0b00010000;
    
    /**
    GPIO registers
    */
    GPIO = 0b00000000;
    
    /**
    ANSEL registers
    */
    ANSELbits.ANS = 0b0000;
    
    /**
    WPU registers
    */
    WPU = 0x00;

}

system_initialize.c
void SYSTEM_Initialize(void){
    PIN_MANAGER_Initialize();
    OSCILLATOR_MANAGER_Initialize();
    TMR0_Initialize();
}

tmr.c
void TMR0_Initialize(void){
    OPTION_REGbits.T0CS = 0; // bit 5 T0CS: TMR0 Clock Source Select bit
                                    // 1 = Transition on GP2/T0CKI pin
                                    // 0 = Internal instruction cycle clock (CLKOUT)
    OPTION_REGbits.PSA = 0; // bit 3 PSA: Prescaler Assignment bit
                                    // 1 = Prescaler is assigned to the WDT
                                    // 0 = Prescaler is assigned to the TIMER0 module
    OPTION_REGbits.PS = 0b110; // bit 2-0 PS2:PS0: Prescaler Rate Select bits
                                    // 110 = 1:128
    
    
    TMR0 = 250; // 250us*128 = 32000us = 32ms
    
    // Clearing IF flag before enabling the interrupt.
    TMR_ClearTimer0InterruptFlag();
    
    // Enabling TMR2 interrupt.
    TMR_Timer0InterruptEnable();
}

 
This debouncing is for falling edge trigger.
 
I'm not sure that I need reload tmr0 in every interrupt? or the manipulation of GPIO5 is correct?
BTW, I didn't see the ON OFF register of tmr0, I guess tmr0 is on by default.
 
Thank you!
 
 
post edited by Andy_Taiwanese - 2018/03/13 20:01:45

Attached Image(s)

#1

2 Replies Related Threads

    FabianL
    Senior Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2017/04/24 05:45:11
    • Location: Germany, Baden-Württemberg
    • Status: offline
    Re: debouncing in 12F675 2018/03/14 02:30:56 (permalink)
    0
    Hi,
     
    never used that device but:
     
    This code:

    PIN_STATE = PIN_STATE << 1;

     

    if(PIN_Gp4StateNow == PIN_Gp4StateNext == HIGH) PIN_STATE || 1;
    else if(PIN_Gp4StateNow == PIN_Gp4StateNext == LOW) PIN_STATE || 0;
            
    if(PIN_STATE && 0b00000111 == 0b00000100) ~GPIObits.GP5;


     
    Doesn't do much:
     
    1.) You never initialize PIN_STATE, imagine it is initialized as 0x00:

    // will stay 0x00

    PIN_STATE = 0x00 << 1;


     
    '<< 1' can be seen as a 'multiply by two' operation.
     
    2.) You are not assigning anything to PIN_STATE. '||' is a boolean expression operator, so when PIN_STATE is 0x00:

    // When GP4 was equal value HIGH for at least one timer0 overflow:

    if(PIN_Gp4StateNow == PIN_Gp4StateNext == HIGH) true;

    // I guess even the free compiler would optimise that away as it does nothing

     

    // When GP4 was equal value LOW for at least one timer0 overflow:
    else if(PIN_Gp4StateNow == PIN_Gp4StateNext == LOW) false;

    // same as above.. does nothing


     
    For PIN_STATE != 0x00:

    // When GP4 was equal value HIGH for at least one timer0 overflow:

    if(PIN_Gp4StateNow == PIN_Gp4StateNext == HIGH) true;

    // I guess even the free compiler would optimise that away as it does nothing

     

    // When GP4 was equal value LOW for at least one timer0 overflow:
    else if(PIN_Gp4StateNow == PIN_Gp4StateNext == LOW) true;

    // same as above.. does nothing


     
    3.) Again you are using the boolean expression operator '&&' instead of a bitwise operator '&'. And what happens next is because of the higher precedence of the operator '==' over '&&':

    // step 1:

    if(PIN_STATE && 0b00000111 == 0b00000100) ~GPIObits.GP5;

    // step 2:

    if(PIN_STATE && false) ~GPIObits.GP5;

    // step 3:

    if(false) ~GPIObits.GP5;

    // step 4:

    // statement never executed


     
    To be honest I don't for sure understand what your aim was here anyways. Please state what condition you wanted to check for. Also using additional braces to change the overall expression to:
     

    if( (PIN_STATE && 0b00000111) == 0b00000100 ) ~GPIObits.GP5;


     
    Would not lead to anything useful.
     
    Also:

    ~GPIObits.GP5;


     
    does nothing, as it is purely negating the value of GPIObits.GP5, but not reassigning it.
     
    You probably want something like this (toggle GP5):

    GPIObits.GP5 = ~GPIObits.GP5;


     
    To answer your other question. Yes, you have to reload the TMR0 register in your ISR to achieve the desired period.
    TMR0 will increment by 1 every (1 / ((FOSC/4) / 128)) seconds. You haven't told what your FOSC was, but from the comments in your code I'm guessing it's 4MHz.
     
    The preload value you used in your initialization is also wrong. If you want your ISR executed every 32ms, it has to be:

    TMR0 = 256 - 250; // 250us*128 = 32000us = 32ms


     
    Because the interrupt is generated whenever TMR0 overflows from 0xFF to 0x00.
    This is also the reason why you have to reload TMR0 in your ISR. Unless you can live with a period of 32.768ms instead, in which case you can initialize TMR0 as 0x00 and don't have to think about reloading it ;-).
     
    When timing is very important though, consider that by reloading the TMR0 you will loose 2 instruction cycles (see 4.1 Timer0 Operation of the datasheet).
     
    Regards
    Fabian
    #2
    Mysil
    Super Member
    • Total Posts : 2758
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: debouncing in 12F675 2018/03/14 12:36:56 (permalink)
    0
    Hi,
     
    Code fragments from message #1 have been made to work on PIC12F675 using MPLAB Simulator,
    and PIC16F688 hardware.
    Debouncing code seem to be a mix of 2 different algorithms, using both 2 discrete variables and a shifted variable that is able to keep 8 sequential states in a single byte.
    Since testing for 2 different devices, some preprocessing directives have been inserted.
     
    If forum software behave, packaged project will be attached.
     
       Mysil
    post edited by Mysil - 2018/03/14 12:43:53
    #3
    Jump to:
    © 2018 APG vNext Commercial Version 4.5