PIC Development Board with PK3

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Make sense?
Can you expand your code a bit that show two routine, one main routine and one interrupt service routine?

maybe get some idea

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
Edit : When switch button is pressed or released, both times the switch bounces. I don't see debounce logic when button release in your code

Which line in the code check the switch whether it is open or closed?
 
Last edited:

trebla

Joined Jun 29, 2019
542
Let the interrupt routine set the flag as it works already and concentrate on the button routine.

In this button routine:
1. check the flag, if set clear it and check status variable (you must define it at beginning):
a) if status is idle (button not pressed awhile) check button input - if pressed change status to detected, if not, jump out of this routine
b) if status is detected increase debounce counter by one and check it is reached to 20 - if it is, change status to debounced, clear debounce counter and jump out of this routine, if not reached 20, just jump out of this routine
c) if status is debounced, check button input - if still pressed, just jump out of this routine, if released change status to released and increase debounce counter by one and check it is reached to 20 - if it is, change status to idle, clear debounce counter and jump out of this routine, if not reached 20, just jump out of this routine
2. you can send messages to rest of your program by setting different flags if, for example, you are setting status to "detected", then some another function receiving this flag is responsible to clear this flag.

Just let interrupt set the flag and the button routine will act every time it find the flag set depending the status variable

You can set up status names by:
#define IDLE 0
#define DETECTED 1
...etc

or by :
enum debounce { IDLE, DETECTED, ...etc }; // define constants
enum debounce status = IDLE; //declare status variable and initialize to IDLE
 

JohnInTX

Joined Jun 26, 2012
4,787
*exhales*

C-like:
unsigned char counter;
bit BUTTON_x;
bit Interrupt_Flag_1ms;

interrupt()
  if(TMR1IF == 1){
    TMR1IF = 0;
    reload the timer;
    Interrupt_Flag_1ms = 1;  // set flag to indicate 1ms has elapsed
  }
  ... process any other interrrupts
}
  
// Switch input/debounce support function
// Samples switch input on each call
// If switch is stays continuously TRUE for DEBOUCE_TIKS, set the BUTTON_x flag
// else clear BUTTON_x flag
void Run_Debounce(void){
if input == FALSE{    <<<<<<<<<<<<<<<<<< SAMPLE THE SWITCH INPUT,
   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

void main(void){
  do the init stuff, set up the timer etc.

  if (Interrupt_Flag_1ms == 1){  // if 1ms has elapsed, process the switch input(s), updates BUTTON_x flag
    Interrupt_Flag_1ms = 0;  // clear the flag for next time
    Run_Debounce();        // process switch
  }

   then do_other_stuff();

  // use the clean debounced button for something
   if(BUTTON_x == 1)
     LED_ON;
   else
     LED_OFF;
  
}
}
Edit : When switch button is pressed or released, both times the switch bounces. I don't see debounce logic when button release in your code
The debouncer only debounces on pressing the button. It does not debounce the release. That's OK for now.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
The debouncer only debounces on pressing the button. It does not debounce the release. That's OK for now.
I was doing research to understand switch debouncing , then I came across an old thread and saw your reply #3 with code

https://forum.allaboutcircuits.com/threads/debouncing-a-switch-in-software-using-a-pic16f72.100339/

The switch is debounced both ways.
what was the meaning of above sentence

It appears that in the code you increment the counter if the switch is closed and decrement the counter if the switch is open

Sorry for asking about the reply of old thread but clarification was required

Edit :
C-like:
void Run_Debounce(void){
if input == FALSE{    <<<<<<<<<<<<<<<<<< SAMPLE THE SWITCH INPUT,
   counter = 0;  // button is open, reset everything
   BUTTON_x = FALSE;
}
What is input in your code?
You are checking input directly but you haven't used it anywhere before in code
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
Debouncing both ways means that it not only debounces when the switch is pressed but for when it is released. There are reasons to do that but not here. The task is debouncing without blocking code. Let's stick to that.

What is input in your code?
You are checking input directly but you haven't used it anywhere before in code
This is pseudo-code, it is not meant to be complete or to compile without errors. I am just trying to get you to see the logic behind:
1) passing a flag out of an interrupt routine at 1ms intervals
2) doing the debounce action at 1ms intervals when the flag gets set by the interrupt routine. Clear the flag and process the debounce.
3) understanding ONE way of debouncing a switch.
READ the code and figure out its logic. Use a pencil and paper or write a flow chart from the pseudo-code. You can't proceed until you understand the logic of how this particular debouncer works.

Of those 3 items, which do you not understand?

The input is your button. It is TRUE when the button is pressed and FALSE when the button is released. You need to connect a button to an input port and determine what logic level is TRUE and what level is FALSE.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
This is pseudo-code, it is not meant to be complete or to compile without errors. I am just trying to get you to see the logic behind:
I've compiled and ran following code. When I press button LED is not turning ON but It supposed to turn ON It seems logic error in code

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)

unsigned char counter;
__bit BUTTON_x;
__bit Interrupt_Flag_1ms;

#define Button          PORTBbits.RB0
#define LED             LATDbits.LATD2
#define DEBOUNCE_TIKS  10

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 = 0x80;      // Button connected to RB0
    TRISC = 0x00;      // all are output, Unused
    TRISD = 0x00;      // LED connected to RD2 pin
    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 Run_Debounce(void)
{
  if (Button == 0)
  {  
    counter = 0;  // button is open, reset everything
    BUTTON_x = 0;
  }
  else
  {
    if(BUTTON_x == 0)
    { 
      counter++;
      if(counter == DEBOUNCE_TIKS)
        BUTTON_x = 1;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
  } 

}

void main(void)
{
    Port_Initialized ();
    Timer0_Initialized ();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
            
        if(BUTTON_x == 1)
            LED = 1;
        else
            LED = 0;
    }
}


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

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
OK.. so debug it.
Where would you start?
1629635765737.png


I set breakpoint on line 149. When cursor is on line 145 I click F7 then cursor stop at line 152 but I don't understand doesn't code go through line 147, 148

1629636037222.png

Edit : there is no problem in ISR routine I've debug it
 

JohnInTX

Joined Jun 26, 2012
4,787
I set breakpoint on line 149. When cursor is on line 145 I click F7 then cursor stop at line 152 but I don't understand doesn't code go through line 147, 148
That's probably because when you run it after the breakpoint the timer has not yet generated another interrupt and flag.

If you have confirmed the interrupt occurs at 1ms intervals with the stopwatch, clear that breakpoint and put two new ones in Run_Debounce() (post #446). Click RUN after each breakpoint.
It should break on line 123 when the button is open.
It should break on line 130 when the button is pressed.
Does it?
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
That's probably because when you run it after the breakpoint the timer has not yet generated another interrupt and flag.

If you have confirmed the interrupt occurs at 1ms intervals with the stopwatch, clear that breakpoint and put two new ones in Run_Debounce() (post #446). Click RUN after each breakpoint.
It should break on line 123 when the button is open.
It should break on line 130 when the button is pressed.
Does it?
yes It happens

When the button is open.

1629641365907.png


When the button is pressed.

1629641424594.png
 

JohnInTX

Joined Jun 26, 2012
4,787
It looks like it is reading the button.
Does it break at line 132 after 10 passes with the button pushed?

I assume you fixed the TRISB init problem present in #446.
 

JohnInTX

Joined Jun 26, 2012
4,787
fixed it TRISB = 0xFF; #446
I'm not sure how you got to the two breakpoints in #450 but yes, the port needs to be an input.

I'm not clear On which line do I have to set breakpoint ?
Read the Run_Debounce() function. When the button is closed it counts once time the routine is called up to 10 then sets a flag. Set a breakpoint to confirm that action.

When should I run program ? Do I have to hold button or press it once
In Run_Debounce() ?? Try it and see where the code goes. There are 3 conditions possible in Run_Debounce():
Button not held
Button held and counter counting up each time the function is called
Button held and counter has finished counting to 10 - flag is set.

Set the a breakpoint in each section to confirm the three actions. Once all are working, the BUTTON_x flag will follow the debounced button input.

EDIT: Your button input is a logic '1' when open and a logic '0' when pressed according to the schematic. Does that work with this line?
if (Button == 0) // if button is NOT pressed...

A good exercise at this point would be to fully comment the code in Run_Debounce() so that you know how it should work.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
@JohnInTX
i have found the solution after many attempts. So the cable between the microcontroller and push button was bad. I replaced the bad cable with a new cable.

Now When I press the button, LED goes turns on and when I release the button, LED goes turns off

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)

unsigned char counter;
__bit BUTTON_x;
__bit Interrupt_Flag_1ms;

#define Button          PORTBbits.RB0
#define LED             LATDbits.LATD2
#define DEBOUNCE_TIKS  10

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 = 0x80;      // Button connected to RB0
    TRISC = 0x00;      // all are output, Unused
    TRISD = 0x00;      // LED connected to RD2 pin
    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 Run_Debounce(void)
{
  if (Button == 0)
  {
    counter = 0;  // button is open, reset everything
    BUTTON_x = 0;
  }
  else
  {
    if(BUTTON_x == 0)
    {
      counter++;
      if(counter == DEBOUNCE_TIKS)
        BUTTON_x = 1;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
  }

}

void main(void)
{
    Port_Initialized ();
    Timer0_Initialized ();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
        
        if(BUTTON_x == 1)
            LED = 1;
        else
            LED = 0;
    }
}


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

  }

  }
I assume you fixed the TRISB init problem present in #446.
I was correct, sequence goes from left to right in increasing order
0x80 = 0b10000000 = RB0, RB1, RB2, RB3, RB4,RB5, RB6, and RB7
It show portB pin RB0 become input pin all other are output pins
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
So the cable between the microcontroller and push button was bad. I replaced the bad cable with a new cable.
It's a good idea to test the hardware by measuring the voltage at the PIC pin as you push and release the button.
I was correct, sequence goes from left to right in increasing order
0x80 = 0b10000000 = RB0, RB1, RB2, RB3, RB4,RB5, RB6, and RB7
It show portB pin RB0 become input pin all other are output pins
That is not the way the port bits are ordered. See table 11-4 in the datasheet. Left to right is RB7->RB0.

Did you step through the debounce routine to make sure it is actually doing the counting and correctly sensing the button?

When that is sorted, a couple of good exercises would be:
1) How would you make the button a toggle? Press once to turn the LED on continuously. Press again to turn the LED off.
2) How would you count the number of times that the button has been pressed.? One press and release is one count.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Did you step through the debounce routine to make sure it is actually doing the counting and correctly sensing the button?
I have debugged code. It's counting and correctly sensing the button

When that is sorted, a couple of good exercises would be:
1) How would you make the button a toggle? Press once to turn the LED on continuously. Press again to turn the LED off.
I have finished first task. Press once to turn the LED on continuously. Press again to turn the LED off.
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)

unsigned char counter;
__bit BUTTON_x;
__bit Interrupt_Flag_1ms;

#define Button          PORTBbits.RB0
#define LED             LATDbits.LATD2
#define DEBOUNCE_TIKS  10

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 = 0b00000001;      // Button connected to RB0
    TRISC = 0x00;      // all are output, Unused
    TRISD = 0x00;      // LED connected to RD2 pin
    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 Run_Debounce(void)
{
  if (Button == 0)
  {
    counter = 0;  // button is open, reset everything
    BUTTON_x = 0;
  }
  else
  {
    if(BUTTON_x == 0)
    {
      counter++;
      if(counter == DEBOUNCE_TIKS)
        BUTTON_x = 1;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
  }

}

void main(void)
{
    Port_Initialized ();
    Timer0_Initialized ();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
         
        if(BUTTON_x == 1)
            LED =~ LED;
   
    }
}
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Does it work reliably?
something is going wrong. I don't see any problem with logic

if(BUTTON_x == 1) // check state every time
LED ~= LED; // change LED state

I tried to trace the logic problem in the code but don't know where exactly the problem is happening. Can you point out where exactly the problem is occurring?
 
Top