PIC Development Board with PK3

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I would recommend you mark those pins, clip them off or slide piece of wire insulation over them to remind you never to use them for anything for debugging
@JohnInTX When I ran code I don't know why I am getting fixed adc value 2.048. Read_I2C_Device() function return ADC value in rd_buf[]

What's the wrong in below part of code

C:
  while(1)
    { 
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ; // get new conversion 
       __delay_ms(10);
    
  
     if(Result3 == 0) // if successful read..
{
       WriteCommand(0x80); // this line update lcd line position
        ADC_Result = (rd_buf[0] << 8) + rd_buf[1]; 
        Result_V = (float)ADC_Result;
        Result_V *= 2.048 / 32768.0;
        sprintf( (char *) A_buffer,"value: %5.3f", Result_V );
        LCD_Data(A_buffer);
        asm("nop");

}
    }
 

JohnInTX

Joined Jun 26, 2012
4,787
Input voltage >= FSR of the programmable gain amplifier?

For your ADC setup,
AIN0 should be connected to the wiper of the potentiometer.
AIN1 should be connected to GROUND.
FSR = +/- 2.048V (set by PGA[2:0] in the Config Register)

The raw ADC reading will be in the range of 0000h <= ADC_Result <= 7FFFh as the pot wiper voltage goes from 0.000V <= WIPER VOLTAGE < 2.048V.

Your arithmetic checks out on the calculator.

I would set a breakpoint on line 11 above and inspect ADC_Result as the pot changes. It looks to me like the ADC is railed i.e. reporting maximum value (7FFFh) always.
Change the pot, click RUN to hit the breakpoint again and verify that ADC_Result is changing as expected.
If you don't know what to expect, Read the integer ADC_Result in the debugger, convert it from hex to decimal then run it through your arithmetic on the calculator. The result should be the pot voltage.

EDIT: rename Vref to FSR to agree with ADC architecture.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Input voltage >= FSR of the programmable gain amplifier?
Okay when I change pot I get value from 0 to 2.048V

I'm confused by reading datasheet.

Datasheet 9.6.3 config register, page 28

I think after sending two bytes micro should send next two bytes value to set configure register to get 4.096V

I know I need to set PGA[2:0] to 001 for +- 4.096V

I don't understand how to get value from 0 to +- 4.096V
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I don't understand how to get value from 0 to +- 4.096V
See 9.5.4 Data Format in the datasheet.
Volts = (ADC count / 2^N) * Vref.
The ADC is 16bit 2's complement. One bit is the sign and 15 bits are the value so N = 15 and 2^N = 32768. The converted ADC count is some fraction of 2^15 scaled to Vref.

EXAMPLE:
If Vref = 2.048V and the count is 3457, the input voltage is
(3457/32768) * 2.048 = 0.216V

Note that the voltage is measured between AINP and AINN.
Vref and which pins are the analog inputs are determined by how you have written the CONFIG register.
If you change Vref, the PGA in this ADC, you need to change the scaling factor in your math from 2.048 to 4.096.
So change the PGA bits in the CONFIG register and change the 2.048 to 4.096 or whatever the PGA is set to.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
@JohnInTX I think I've done enough work with ADS1115 and I think I should move on now

I want to read multiple switches on board. I've written blocking program to read multiple switches. Now I want to write non blocking program to read multiple switches

1629213652801.png


Blocking delay program for switch buttons
C:
//
#define _XTAL_FREQ 20000000 // crystal 20MHz

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2 // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON // Power Up Timer (Enabled)
#pragma config BOREN = OFF // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0 // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1 // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5 // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON // Code Protect Boot (Enabled)
#pragma config CPD = ON // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON // Config. Write Protect (Enabled)
#pragma config WRTB = ON // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = OFF       // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = OFF       // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = OFF // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma warning disable 520

#include <xc.h>
#include <stdio.h>

#define SW1 PORTBbits.RB0
#define SW2 PORTBbits.RB1
#define SW3 PORTBbits.RB2
#define SW4 PORTBbits.RB3
       

#define Switch_Pressed 1
#define Switch_Not_Pressed 0

#define LCD_RS              LATAbits.LATA2
#define LCD_TRIS_RS         TRISAbits.TRISA2
#define LCD_RW              LATAbits.LATA1
#define LCD_TRIS_RW         TRISAbits.TRISA1
#define LCD_E               LATAbits.LATA0
#define LCD_TRIS_E          TRISAbits.TRISA0

#define  LCDPORT            LATD
#define  LCDTRISD           LATD


void Port_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);

void Port_Initialized (void)
{
// LATx registers
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

// TRISx registers
    TRISA = 0x00; // RS, R/W and E
    TRISB = 0x00; // switches are connected to Pin0, Pin1, Pin2, Pin3 of PORT B
    TRISC = 0x00; // all are output, Unused
    TRISD = 0x00; // LCD Data pins
    TRISE = 0x00; // All are output, Unused

    ANCON0 = 0x00; // set to digital port
    ANCON1 = 0x00; // Set to digital port
    CM1CON = 0x00; // Comparator off
    CM2CON = 0x00; // Comparator off
    ADCON0 = 0x00; // A/D conversion Disabled
    ADCON1 = 0x00; // A/D conversion Disabled
    ADCON2 = 0x00; // A/D conversion Disabled
}

// Return 1 if Switch1 is pressed and 0 if not pressed
__bit Check_Switch_1(void)
{
  if(SW1 == 1) // Check Switch is pressed
      {
        __delay_ms(50); // wait 50 ms for de-bounce period
         if(SW1 == 1) // check switch again
          return Switch_Pressed;
      }
  return Switch_Not_Pressed;
}

// Return 1 if Switch2 is pressed and 0 if not pressed
__bit Check_Switch_2(void)
{
  if(SW2 == 1) // Check Switch is pressed
      {
        __delay_ms(50); // wait 50 ms for de-bounce period
          if(SW2 == 1) // check switch again
           return Switch_Pressed;
       }
  return Switch_Not_Pressed;
}
// Return 1 if Switch3 is pressed and 0 if not pressed
__bit Check_Switch_3(void)
{
  if(SW3 == 1) // Check Switch is pressed
      {
         __delay_ms(50); // wait 50 ms for de-bounce period
         if(SW3 == 1) //check switch again
          return Switch_Pressed;
       }
    return Switch_Not_Pressed;
}

// Return 1 if Switch4 is pressed and 0 if not pressed
__bit Check_Switch_4(void)
{
  if(SW4 == 1) // Check Switch is pressed
      {
         __delay_ms(20); // wait 50 ms for de-bounce period
          if(SW4 == 1) // check switch again
          return Switch_Pressed;
      }
    return Switch_Not_Pressed;
}

// check switches, return 1 if SW1 pressed, 2 if SW2 pressed, 3 if SW3 pressed, 4 if SW4 pressed
// Return 0 if no switches are pressed
unsigned char Check_Switches(void)
  {
      unsigned char ReturnValue = 0;
     
      if (Check_Switch_1()== Switch_Pressed )
        {
           ReturnValue = '1' ;
        }
      else if (Check_Switch_2()== Switch_Pressed)
        {
           ReturnValue = '2';
        }
      else if (Check_Switch_3()== Switch_Pressed)
        {
           ReturnValue = '3';
        }
      else if (Check_Switch_4()== Switch_Pressed)
        {
           ReturnValue = '4';
        }
     
  return ReturnValue;
  }

// Wait for 5 ms
void WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    LCD_RS = 0;                                  //setup to send command
    WriteNibble(command);                        //write the high nibble
    WriteNibble( (unsigned char)(command<<4) );  //then the low nibble
}

//Initialized  LCD
void LCD_Initialized()
{
    LCDTRISD &=0x0f;                //ensure data bits are output
    LCD_E=0;                        //clear enable
    LCD_RS = 0;                     //going to write command
    LCD_TRIS_E=0;                   //Set enable to output
    LCD_TRIS_RS=0;                  //set RS to output
    LCD_TRIS_RW=0;
    LCD_RW=0;
    __delay_ms(30);                 //delay for LCD to initialize.
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(1);                  //required delay
    WriteCommand(0x20);             //set to 4 bit interface
    WriteCommand(0x2c);             //set to 4 bit interface, 2 line and 5*10 font
    WriteCommand(0x06);             //move cursor right after write
    WriteCommand(0x0F);             //turn on display with flashing cursor
    WriteCommand(0x01);             //clear display
    __delay_ms(2);
}

//Send a character to the LCD
void WriteChar(unsigned char Chr)
{
    WaitLCDBusy();                         //wait until not busy
    LCD_RS=1;                              //Setup to send character
    WriteNibble(Chr);                      //write the high nibble  
    WriteNibble( (unsigned char)(Chr<<4)); //then the low nibble
}

//Send any 4 bits to the LCD
void WriteNibble(unsigned char command)
{
    LCDPORT &= 0x0f;                        //clear the data bits
    LCDPORT|=((command & 0xf0));            //or in the new data
    LCD_E = 1;                              //enable the LCD interface
    NOP();                                  // delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
}

void LCD_Data( unsigned char *string)
{
    while (*string != '\0')
    {
      WriteChar(*string);
        string++;
    }
}


unsigned char Switch_N;

void main(void)
{
     Switch_N = 0;
     unsigned char Data2;
     unsigned char string[6];
     string[0] = Switch_N;
     string[1] = 0; //null terminator
   
    Port_Initialized ();
    LCD_Initialized();
   
    while(1)
    {
       if( Switch_N = Check_Switches())
       {
           WriteCommand(0x80);

           WriteChar( Switch_N );
           asm("nop");
       }
       
    }
   
   
}
When I press SW1 I get 1 on screen
When I press SW2 I get 2 on screen
When I press SW3 I get 3 on screen
When I press SW4 I get 1 on screen

I want to read multiple switches using timer interrupt. I can set timer interrupt. I'm having trouble to read multiple switches using timer interrupt.

Any help would be apricated
 

JohnInTX

Joined Jun 26, 2012
4,787
So.. first you need the timer interrupt. I'd start with a 1ms period or something in that range. I usually use TIMER 2 and PR2 to generate a repetitive interrupt.
Code that.

Next, think about how you would debounce a switch if you only looked at it once every 1ms (or whatever the interrupt period) instead of blocking. There are many ways to do it but think about how you could count 20-50 1ms tiks and know if the switch stays closed for that time.
If the switch stays closed, set a flag. When the switch opens, clear the flag. The main loop just looks at the flag for each switch, not the switch itself.

Draw a flow chart for ONE switch and see what you come up with.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
So.. first you need the timer interrupt. I'd start with a 1ms period or something in that range. I usually use TIMER 2 and PR2 to generate a repetitive interrupt.
Code that.
I already wrote code for 1ms

Debugging simulator screenshot

1629221415876.png

approximate 1ms

C:
#define _XTAL_FREQ 8000000

#include <xc.h>
// PIC18F45K80 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = HIGH   // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF       // Extended Instruction Set (Enabled)
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS  // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-01FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 02000-03FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 04000-05FFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 06000-07FFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-01FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 02000-03FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)


volatile int flag = 0;

void Port_Initialized (void);
void Timer0_Initialized (void);
void __interrupt(high_priority) tcInt(void);

void Port_Initialized (void)
{
    // LATx registers
    LATA =  0x00;
    LATB =  0x00;
    LATC =  0x00;
    LATD =  0x00;
    LATE =  0x00;

//  TRISx registers
    TRISA = 0x00;      // All are output, Unused
    TRISB = 0x00;      // all are output, Unused
    TRISC = 0x00;      // all are output, Unused
    TRISD = 0x00;      // all are output, Unused
    TRISE = 0x00;      // All are output, Unused

    ANCON0 = 0x00;     // set to digital port
    ANCON1 = 0x00;     // Set to digital port
    CM1CON = 0x00;     // Comparator off
    CM2CON = 0x00;     // Comparator off
    ADCON0 = 0x00;     // A/D conversion Disabled
    ADCON1 = 0x00;     // A/D conversion Disabled
    ADCON2 = 0x00;     // A/D conversion Disabled
}
    
void Timer0_Initialized (void)
{
     TMR0L = 250;    //Timer0 Register Low Byte   
 
    //T0CON: TIMER0 CONTROL REGISTER
     TMR0ON = 1; //Timer0 On
     T08BIT = 1; // Timer0 is configured as an 8-bit timer/counter0
     T0CS = 0;   // Internal instruction cycle clock (CLKO)
     T0SE = 1;    //Increments on high-to-low transition on T0CKI pin0
     PSA = 0; //Timer0 prescaler is assigned; Timer0 clock input comes from prescaler output   
     //1:8 Prescale value
     T0PS2 = 1;
     T0PS1 = 1;
     T0PS0 = 1;
     //INTCON: INTERRUPT CONTROL
    
     PEIE = 0;   //Disables all peripheral interrupts
     TMR0IE = 1; //Enables the TMR0 overflow interrupt
     INT0IE = 0; //Disables the INT0 external interrupt
     RBIE = 0; //Disables the RB port change interrupt
     TMR0IF = 0;// cleared timer overflow flag
     INT0IF = 0; // disabled external interrupt
     RBIF = 0; //disabled Port Change Interrupt Flag bit
     GIE = 1;    // Enable Global Interrupt Enable bit
}

void main(void)
{
    Port_Initialized ();
    Timer0_Initialized ();
 
    while (1)
    {
       if (flag == 1)
       {
           // do something
       }
    }
}


void __interrupt(high_priority) tcInt(void)
{
  if (TMR0IF == 1) // Timer0 overflow interrupt flag bit
  {
      flag = 1;
      
      TMR0IF = 0;
        
      TMR0L = 250;    //Timer0 Register Low Byte     
      
  }
    
  }
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
You must clear flag variable outside interrupt routine, for example when you are readed button status (pressed, not pressed, debounced etc).
Thanks trebla, I did clear flag outside ISR
C:
while (1)
    {
       if (flag == 1)
       {
          flag = 0; // clear flag
           // do something
       }
    }
 

JohnInTX

Joined Jun 26, 2012
4,787
So you have a flag that indicates to the main program when 1ms has elapsed. That's good.

Before going farther, complete the flow charts:
On the left side, what do you do if the flag is NOT set? Answer: Nothing, you proceed to the next thing in your main flow (not shown). You don't loop, just go on to the next thing.
In the interrupt what do you do when the Timer Interrupt Flag is NOT set?
You absolutely must know all of that because you can't code what you haven't figured out.
So fix that first.

Next:
Define what the buttons look like to the main program. Main does NOT care about debouncing, logic levels, or even if it's a physical button. It might be a sonar range, a temperature over a limit, a voltage over a setpoint - anything. Main ONLY cares about if that input is TRUE or FALSE. It doesn't need any other details.

With that in mind, it makes sense to define the button as a flag which is 1 when the input is TRUE and 0 when the input is FALSE. Nothing more or less. Name the flag BUTTON_x where _x is the button number.

Think how you would debounce the button and present BUTTON_x to main. I am short of time today so here is a starting place.

C:
unsigned char counter;
bit BUTTON_x;

if input == FALSE{
  counter = 0;  // button is open, reset everything
  BUTTON_x = FALSE;
}
else{  // input is true, debounce if necessary
   if(BUTTON_x == FALSE){  // if button closed but not fully debounced yet
     counter++;
     if(counter == DEBOUNCE_TIKS)
        BUTTON_x = TRUE;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
} // input is true
Make sense?
 

JohnInTX

Joined Jun 26, 2012
4,787
No

#432 says that the only thing you do in the interrupt routine is set a flag that tells main that it is time to run the debounce.

The debounce flow you posted does not follow the pseudo code that i posted.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
The debounce flow you posted does not follow the pseudo code that i posted.
I don't fully understand the concept of debounce. So before making flowchart and code. I want to understand it completely.

Let's say I have a switch that stops bouncing after 100 ms.

We read button state every 1ms.
if the switch is closed increments counter
if the switch is open restart counter

What happens if we read the switches just at the instant that it is bouncing?

What happens If we read the switch less often than the bounce time?
 

JohnInTX

Joined Jun 26, 2012
4,787
Good questions but you are over-thinking the problem. A TACT switch has a max bounce time of 3-5ms then it is stable. 20-25 successive TRUE readings at 1ms intervals is sufficient to handle mechanical contact bounce for now.
 

trebla

Joined Jun 29, 2019
547
I don't fully understand the concept of debounce. So before making flowchart and code. I want to understand it completely.

Let's say I have a switch that stops bouncing after 100 ms.

We read button state every 1ms.
if the switch is closed increments counter
if the switch is open restart counter

What happens if we read the switches just at the instant that it is bouncing?

What happens If we read the switch less often than the bounce time?
For this purpose you can use variables for holding debouncing cycle current status -idle, detected, debouncing, pressed etc. depending what your routine requires. I remember, we have discussed about the same topic in another thread earlier and i gave some examples for you also. So keep interrupt and debouncing routine separately, set timing flag in interrupt routine and deal with debounce status and timing counters in debounce routine where you can use for exact timing reading and clearing the flag you are set in interrupt routine.
 
Top