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.

C18 ISR / Debounce Routine

Status
Not open for further replies.
Hello,

I have two push buttons seperately connected to RB0 and RB1 on an 18F2420. Each triggers the external interrupt on it's respective pin. In the 'first' version of the code for this each button has it's own debounce routine and that works. In the second I've tried to use a common routine for both switches but although it appears to work when single stepping through it in debug mode it doesn't in real time.

The problem must be with the labels assigned to the pins, not sure why; In the ISR for button1 I've made buttonX = button1 and in button2 ISR, buttonX = button2. Then used that common 'buttonX' in the debounce routine.

Any chance of having a quick peek at this code and putting me right?

This works......

Code:
// Stepper 15 - 
// 21.12.10

#include <p18f2420.h>
#include <delays.h>                    // the code for the delay routines is in here

#pragma config OSC  = INTIO7         // internal oscillator with Fosc/4 on RA6, I/O on RA7
#pragma config WDT = OFF
#pragma config PBADEN = ON            // portb bits 0 thru 4 as digital input (analog by default at POR)

#define button1         PORTBbits.RB0    // pin 21 stop / start
#define button2         PORTBbits.RB1    // pin 22 direction
#define L297_enable    PORTAbits.RA3    // pin 5
#define stepper_dir    PORTAbits.RA4    // pin 6
#define clk             PORTAbits.RA5    // pin 7
#define DetectsInARow   5

void ISR (void);                    // label
void clksig (void);                    // label
void interrupts_init (void);        // label
void timer0_init (void);            // label
//void Switch_Count (void);

#pragma udata   // declare statically allocated uinitialized variables
unsigned char Switch_Count;          // 8-bit variable
unsigned char button1flag;          // 8-bit variable
unsigned char button2flag;          // 8-bit variable


//________________________________________________________________________________________
#pragma code interrupt_vector_high = 0x08 // works ok without, here for reference.
void interrupt_vector_high (void)
    {
      _asm                            // assembly instructions follow
        goto ISR                         // jump to interrupt routine
      _endasm                            // end of assembly instructions
    }
//________________________________________________________________________________________
#pragma code
void main (void)
{    
    unsigned char Switch_Count = 0;
    
    OSCCON = 0b01100010;             // set Fosc = 4Mhz = 1uS instruction cycle time
    ADCON1 = 0xF;                    // sets all analog channels as digital inputs

    INTCON2bits.RBPU = 0;            // enable PORTB internal pullups
    TRISBbits.TRISB0 = 1;           // PORTB bit 0 (connected to switch) is input (1)
    TRISBbits.TRISB1 = 1;           // PORTB bit 1 (connected to switch) is input (1)
    TRISAbits.TRISA3 = 0;            // connected to L297 enable pin (10)
    TRISAbits.TRISA4 = 0;            // connected to L297 cw/ccw pin (17)
    TRISAbits.TRISA5 = 0;            // connected to L297 clk pin (18)
    
    //LATAbits.LATA3 = 0;
    PORTA = 0;                        // clear portA
    PORTB = 0;                        // clear portb
    button1flag = 0;
    button2flag = 0;

    interrupts_init();                // do the interrupts initialising routine
    timer0_init();                    // do the t0 initialising routine

    
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

       while (1)                        // wait here until interrupted by TMR0 or buttons
    {        
        if (button1flag == 1)        // do this debounce routine
        {    
            while (button1 != 1);    // NOT EQUAL TO 1 - stay here
            Switch_Count = 0;
        
            do
            { // monitor switch input for 5 highs in a row (5mS) 
                if (button1 != 0)    // button detected as not pressed
                { 
                Switch_Count++;        // increment count
                }
                else                // OTOH if detected as pressed        
                {
                Switch_Count = 0;    // reset count
                }   
                Delay10TCYx(100);    // wait 1mS
                
            } while (Switch_Count < DetectsInARow); //count <5 loop to DO again
            
                button1flag = 0;    // debounce done so clear flag to allow further interrupts
                                    // on this button to be processed.
        }

        if (button2flag == 1)        // do this debounce routine
        {    
            while (button2 != 1);    // NOT EQUAL TO 1 - stay here
            Switch_Count = 0;
        
            do
            { // monitor switch input for 5 highs in a row (5mS) 
                if (button2 != 0)    // button detected as not pressed
                { 
                Switch_Count++;        // increment count
                }
                else                // OTOH if detected as pressed        
                {
                Switch_Count = 0;    // reset count
                }   
                Delay10TCYx(100);    // wait 1mS
                
            } while (Switch_Count < DetectsInARow); //count <5 loop to DO again
            
                button2flag = 0;    // debounce done so clear flag to allow further interrupts
                                    // on this button to be processed.
        }
    }    
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#pragma interrupt ISR
void ISR (void)                                            
{
        // Decision 1
        if (INTCONbits.TMR0IF)            // T0 rolled over
        {
            INTCONbits.TMR0IF = 0;        // clear the T0 interrupt flag
        
            if (clk ==0)                // if RA5 is low
            {
            clk = 1;                    // make RA5 high
            }
            else                        // OTOH..if it was already high
            {
            clk = 0;                    // make it low
            }    
        }
        
        // Decision 2
        if (INTCONbits.INT0IF)            // button1 was pressed
        {
            INTCONbits.INT0IF = 0;        // reset the interrupt flag
            
            if (button1flag == 0)        // if not still in a debounce routine from a previous press
            {
                button1flag = 1;        // start a debounce routine after return from ISR
                
                if (L297_enable == 0)    // if L297chip disabled
                {
                L297_enable = 1;        // enable it
                }
                else                    // OTOH...if it was already enabled 
                {
                L297_enable = 0;        // disable it
                }
            }            
        }
        
        // Decision 3
        if (INTCON3bits.INT1IF)            // button2 was pressed
        {
            INTCON3bits.INT1IF = 0;        // clear the interrupt flag
            
            if (button2flag == 0)        // if not still in a debounce routine from a previous press
            {
                button2flag = 1;        // start a debounce routine after return from ISR
            
                if (stepper_dir == 0)    // if stepper was rotating ccw
                {
                stepper_dir = 1;        // make it go cw
                }
                else                    // OTOH...if it was already going cw
                {
                stepper_dir = 0;        // make it go ccw            
                }
            }            
        }
        
}    // return from the ISR

void interrupts_init (void)            // instructions to initialise the interrupts
{    
    INTCON2bits.INTEDG0 = 0;        // INT0 interrupt on falling edge
    INTCON2bits.INTEDG1 = 0;        // INT1 interrupt on falling edge
    INTCONbits.INT0IF = 0;            // clear the interrupt flag for INT0
    INTCONbits.INT0IE = 1;            // enables external interrupt INT0(RB0)
    INTCON3bits.INT1IF = 0;            // clear the interrupt flag for INT1
    INTCON3bits.INT1IE = 1;            // enables external interrupt for INT1 (RB1)
    INTCONbits.GIE = 1;                // enable all unmasked interrupts
}
void timer0_init (void)                // instruction to initialise T0
{
    //T0 interrupt settings:
    INTCONbits.TMR0IF = 0;            // clear T0 interrupt flag
    INTCONbits.TMR0IE = 1;            // enable T0 interrupt
    
    //T0 control settings:
    T0CONbits.T08BIT = 0;            // 16 bit mode
    T0CONbits.T0CS = 0;                // use instruction cycle clock
    T0CONbits.PSA = 1;                // prescaler NOT used
    TMR0H = 0;                        // clear the high byte
    TMR0L = 0;                        // clear the low byte
    T0CONbits.TMR0ON = 1;            // start timer !!!!!!!!!!!!!!!
}
This doesn't.......

Code:
// Stepper 15 - 
// 21.12.10

#include <p18f2420.h>
#include <delays.h>                    // the code for the delay routines is in here

#pragma config OSC  = INTIO7         // internal oscillator with Fosc/4 on RA6, I/O on RA7
#pragma config WDT = OFF
#pragma config PBADEN = ON            // portb bits 0 thru 4 as digital input (analog by default at POR)

#define button1         PORTBbits.RB0    // pin 21 stop / start
#define button2         PORTBbits.RB1    // pin 22 direction
#define L297_enable    PORTAbits.RA3    // pin 5
#define stepper_dir    PORTAbits.RA4    // pin 6
#define clk             PORTAbits.RA5    // pin 7
#define DetectsInARow   5

void ISR (void);                    // label
void clksig (void);                    // label
void interrupts_init (void);        // label
void timer0_init (void);            // label

#pragma udata   // declare statically allocated uinitialized variables
unsigned char Switch_Count;          // 8-bit variable
unsigned char buttonX;              // 8-bit variable
unsigned char buttonflag;              // 8-bit variable



//________________________________________________________________________________________
#pragma code interrupt_vector_high = 0x08 // works ok without, here for reference.
void interrupt_vector_high (void)
    {
      _asm                            // assembly instructions follow
        goto ISR                         // jump to interrupt routine
      _endasm                            // end of assembly instructions
    }
//________________________________________________________________________________________
#pragma code
void main (void)
{    
    unsigned char Switch_Count = 0;
    
    OSCCON = 0b01100010;             // set Fosc = 4Mhz = 1uS instruction cycle time
    ADCON1 = 0xF;                    // sets all analog channels as digital inputs

    INTCON2bits.RBPU = 0;            // enable PORTB internal pullups
    TRISBbits.TRISB0 = 1;           // PORTB bit 0 (connected to switch) is input (1)
    TRISBbits.TRISB1 = 1;           // PORTB bit 1 (connected to switch) is input (1)
    TRISAbits.TRISA3 = 0;            // connected to L297 enable pin (10)
    TRISAbits.TRISA4 = 0;            // connected to L297 cw/ccw pin (17)
    TRISAbits.TRISA5 = 0;            // connected to L297 clk pin (18)
    
    //LATAbits.LATA3 = 0;
    PORTA = 0;                        // clear portA
    PORTB = 0;                        // clear portb
    buttonflag = 0;
    

    interrupts_init();                // do the interrupts initialising routine
    timer0_init();                    // do the t0 initialising routine
    
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

       while (1)                        // wait here until interrupted by TMR0 or buttons
            
        if (buttonflag == 1)        // do this debounce routine because a switch has been pressed
        {    
            while (buttonX != 1);    // NOT EQUAL TO 1 - stay here
            Switch_Count = 0;
        
            do
            { // monitor switch input for 5 highs in a row (5mS) 
                if (buttonX != 0)    // button detected as not pressed
                            
                { 
                Switch_Count++;        // increment count
                }
                else                // OTOH if detected as pressed        
                {
                Switch_Count = 0;    // reset count
                }   
                //Delay10TCYx(100);    // wait 1mS
                
            } while (Switch_Count < DetectsInARow); //count <5 loop to DO again
            
                buttonflag = 0;        // debounce done so clear flag to allow further interrupts
                                    // on this button to be processed.
                                            
        }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#pragma interrupt ISR
void ISR (void)                                            
{
        // Decision 1
        if (INTCONbits.TMR0IF)            // T0 rolled over
        {
            INTCONbits.TMR0IF = 0;        // clear the T0 interrupt flag
        
            if (clk ==0)                // if RA5 is low
            {
            clk = 1;                    // make RA5 high
            }
            else                        // OTOH..if it was already high
            {
            clk = 0;                    // make it low
            }    
        }
        
        // Decision 2  - BUTTON 1
        if (INTCONbits.INT0IF)            // button1 was pressed
        {
            INTCONbits.INT0IF = 0;        // reset the interrupt flag
            
            buttonX = button1;
            
            if (buttonflag == 0)        // if not still in a debounce routine from a previous press
            {
                buttonflag = 1;            // start a debounce routine after return from ISR
                
                if (L297_enable == 0)    // if L297chip disabled
                {
                L297_enable = 1;        // enable it
                }
                else                    // OTOH...if it was already enabled 
                {
                L297_enable = 0;        // disable it
                }
            }
                
        }
        
        // Decision 3 - BUTTON 2
        if (INTCON3bits.INT1IF)            // button2 was pressed
        {
            INTCON3bits.INT1IF = 0;        // clear the interrupt flag
            
            buttonX = button2;
            
            if (buttonflag == 0)        // if not still in a debounce routine from a previous press
            {
                buttonflag = 1;            // start a debounce routine after return from ISR
            
                if (stepper_dir == 0)    // if stepper was rotating ccw
                {
                stepper_dir = 1;        // make it go cw
                }
                else                    // OTOH...if it was already going cw
                {
                stepper_dir = 0;        // make it go ccw            
                }
            }            
        }
        
}    // return from the ISR
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void interrupts_init (void)            // instructions to initialise the interrupts
{    
    INTCON2bits.INTEDG0 = 0;        // INT0 interrupt on falling edge
    INTCON2bits.INTEDG1 = 0;        // INT1 interrupt on falling edge
    INTCONbits.INT0IF = 0;            // clear the interrupt flag for INT0
    INTCONbits.INT0IE = 1;            // enables external interrupt INT0(RB0)
    INTCON3bits.INT1IF = 0;            // clear the interrupt flag for INT1
    INTCON3bits.INT1IE = 1;            // enables external interrupt for INT1 (RB1)
    INTCONbits.GIE = 1;                // enable all unmasked interrupts
}
void timer0_init (void)                // instruction to initialise T0
{
    //T0 interrupt settings:
    INTCONbits.TMR0IF = 0;            // clear T0 interrupt flag
    INTCONbits.TMR0IE = 1;            // enable T0 interrupt
    
    //T0 control settings:
    T0CONbits.T08BIT = 0;            // 16 bit mode
    T0CONbits.T0CS = 0;                // use instruction cycle clock
    T0CONbits.PSA = 1;                // prescaler NOT used
    TMR0H = 0;                        // clear the high byte
    TMR0L = 0;                        // clear the low byte
    T0CONbits.TMR0ON = 1;            // start timer 0
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Thanks in advance for any help.
 
The problem is that you are putting the value on the pin in button_X whereas you need to use the address of the pin. To do this requires a pointer to a bit variable which isn't supported by C18. You could get around it by having two variables, a pointer to the port address and a bit mask.

Mike.
 
Status
Not open for further replies.

Latest threads

Back
Top