PIC Development Board with PK3

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
For each button is better to use its own counter variable.
Thank you
Button 1 toggle LED 1
Button 2 toggle LED 2
In this way we can read all four button's
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 counter1;
unsigned char counter2;
unsigned char counter3;
unsigned char counter4;

__bit BUTTON_x1;
__bit BUTTON_x2;
__bit BUTTON_x3;
__bit BUTTON_x4;

__bit PREVIOUS_BUTTON_x1 = 0;
__bit PREVIOUS_BUTTON_x2 = 0;
__bit PREVIOUS_BUTTON_x3 = 0;
__bit PREVIOUS_BUTTON_x4 = 0;

__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define LED_1             LATDbits.LATD0
#define LED_2             LATDbits.LATD1
#define LED_3             LATDbits.LATD2
#define LED_4             LATDbits.LATD3

#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 = 0xFF;      // 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 Sw1 ()
{
    if (Button_1 == 0)
  {
    counter1 = 0;  // button is open, reset everything
    BUTTON_x1 = 0;
  }
  else
  {
    if(BUTTON_x1 == 0)
    {
      counter1++;
      if(counter1 == DEBOUNCE_TIKS)
        BUTTON_x1 = 1;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
  }
}

void Sw2 ()
{
    if (Button_2 == 0)
  {
    counter2 = 0;  // button is open, reset everything
    BUTTON_x2 = 0;
  }
  else
  {
    if(BUTTON_x2 == 0)
    {
      counter2++;
      if(counter2 == DEBOUNCE_TIKS)
        BUTTON_x2 = 1;    // fully debounced
    } // else, button TRUE and is already debounced, nothing to do
  }
}
void Run_Debounce(void)
{
Sw1 ();
Sw2 ();

}

void main(void)
{
    Port_Initialized ();
    Timer0_Initialized ();
    LED_1 = 0;
    LED_2 = 0;
    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
    
        if((PREVIOUS_BUTTON_x1 == 0) && (BUTTON_x1==1))
        {
          LED_1 =~ LED_1;
        }
        
    
        PREVIOUS_BUTTON_x1 = BUTTON_x1; // update ?previous? condition every time through
      
         if((PREVIOUS_BUTTON_x2 == 0) && (BUTTON_x2==1))
        {
          LED_2 =~ LED_2;
        }
            
        PREVIOUS_BUTTON_x2 = BUTTON_x2; // update ?previous? condition every time through
}
}

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
For multiple inputs to read and debounce my approach would be define a structure with a counter and status flags for each input:
Done with structure

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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define LED_1             LATDbits.LATD0
#define LED_2             LATDbits.LATD1
#define LED_3             LATDbits.LATD2
#define LED_4             LATDbits.LATD3

#define DEBOUNCE_TIKS  10

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

struct btn_debounce
{
    unsigned char counter;
    char status ; //one bit flags
    char prev_status;
} Button_x1, Button_x2, Button_x3, Button_x4;

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 = 0xFF;      // 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 Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;   
  }
  else
  {
    if( Button_x1.status == 0)
    {
      Button_x1.counter++;
      if(Button_x1.counter == DEBOUNCE_TIKS)
          Button_x1.status = 1;    // fully debounced
    }
  }
}

void Sw2 ()
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;   
  }
  else
  {
    if( Button_x2.status == 0)
    {
      Button_x2.counter++;
      if(Button_x2.counter == DEBOUNCE_TIKS)
          Button_x2.status = 1;    // fully debounced
    }
  }
}

void Run_Debounce(void)
{
 Sw1 ();
 Sw2 ();
}

void main(void)
{
    Button_x1.counter = 0;
    Button_x1.status = 0;
    Button_x1.prev_status = 0;
    
    Button_x2.counter = 0;
    Button_x2.status = 0;
    Button_x2.prev_status = 0;
    
    Port_Initialized ();
    Timer0_Initialized ();
    LED_1 = 0;
    LED_2 = 0;
    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
      
        if((Button_x1.prev_status == 0) && ( Button_x1.status == 1))
        {
          LED_1 =~ LED_1;
        }
        
        if((Button_x2.prev_status == 0) && ( Button_x2.status == 1))
        {
          LED_2 =~ LED_2;
        }
        
        Button_x1.prev_status = Button_x1.status; // update ?previous? condition every time through
        Button_x2.prev_status = Button_x2.status; // update ?previous? condition every time through
}
}

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
I am trying to display key press on the screen after toggling button. I ran code but it doesn't work as expected When I press button I get multiple press with garbage value

screen1.jpg

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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define RS                LATAbits.LATA2
#define RW                LATAbits.LATA1
#define EN                LATAbits.LATA0

#define  LCDPORT          LATD
#define  LCDTRISD         LATD

#define DEBOUNCE_TIKS     15

void Port_Initialized (void);
void Timer0_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void __interrupt(high_priority) tcInt(void);

struct btn_debounce
{
    unsigned char counter;
    char status ; //one bit flags
} Button_x1, Button_x2, Button_x3, Button_x4;


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 = 0xF;      // Button connected to RB0-RB3
    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 WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    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
    EN = 0;                         //clear enable
    RS = 0;                         //going to write command
    TRISBbits.TRISB6 = 0;           //Set enable to output
    TRISBbits.TRISB4 = 0;           //set RS to output
    TRISBbits.TRISB5 = 0;
    RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __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(0x0C);             //turn on display
    WriteCommand(0x01);             //clear display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    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
    EN = 1;                                 //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    EN = 0;                                 //disable it
    NOP();
}

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

void Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;  
  }
  else
  {
    if( Button_x1.status == 0)
    {
      Button_x1.counter++;
      if(Button_x1.counter == DEBOUNCE_TIKS)
          Button_x1.status = 1;    // fully debounced
    }
  }
}

void Sw2 ()
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;  
  }
  else
  {
    if( Button_x2.status == 0)
    {
      Button_x2.counter++;
      if(Button_x2.counter == DEBOUNCE_TIKS)
          Button_x2.status = 1;    // fully debounced
    }
  }
}

void Run_Debounce(void)
{
Sw1 ();
Sw2 ();
}

void main(void)
{
    unsigned char Data1[1] = "1";
    unsigned char Data2[1] = "2";
    Button_x1.counter = 0;
    Button_x1.status = 0;
   
    Button_x2.counter = 0;
    Button_x2.status = 0;
   
    Port_Initialized ();
    Timer0_Initialized ();
    LCD_Initialized();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
           }
     
        if ( Button_x1.status == 1)
           {
                LCD_Data(Data1);
           }
       
       if ( Button_x2.status == 1)
          {
              LCD_Data(Data2);
          }    
    }
}

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;

  }

}
 

trebla

Joined Jun 29, 2019
599
I am trying to display key press on the screen after toggling button. I ran code but it doesn't work as expected When I press button I get multiple press with garbage value
Multiple data are sent to LCD during button is still pressed while debounce counter is counted to maximum value and the status flag is 1. You either put the LCD print command after setting status flag to 1 like:

C:
void Sw2 ()
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0; 
  }
  else
  {
    if( Button_x2.status == 0)
    {
      Button_x2.counter++;
      if(Button_x2.counter == DEBOUNCE_TIKS)
          Button_x2.status = 1;    // fully debounced
          LCD_Data(Data2); //Print data only once per press
    }
  }
}
or add to btn_debounce structure additional bit flag for give signal to LCD print command:

C:
struct btn_debounce
{
    unsigned char counter;
    char status ; //one bit flags
    char lcd :1; // signal for LCD routine
} Button_x1, Button_x2, Button_x3, Button_x4;
Then set this flag after setting status flag and check this flag instead of status for printing to LCD. Don't forget clear this flag after printing.
 

trebla

Joined Jun 29, 2019
599
By the way, you are reserved for status flag whole byte but using only one bit value 0 or 1. It is better to reserve only one bit for this flag, then you save one byte within each button structure variable:

C:
struct btn_debounce
{
    unsigned char counter; //one byte variable
    //second byte, divided to one bit flags
    char status :1; //one bit flag
    char lcd :1; // second one bit flag
    //you can add 6 more one bit variables below
} Button_x1, Button_x2, Button_x3, Button_x4;
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Multiple data are sent to LCD during button is still pressed while debounce counter is counted to maximum value and the status flag is 1. You either put the LCD print command after setting status flag to 1 like:
I have tried as you said but still getting multiple pressed on screen

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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define RS                LATAbits.LATA2
#define RW                LATAbits.LATA1
#define EN                LATAbits.LATA0

#define  LCDPORT          LATD
#define  LCDTRISD         LATD

#define DEBOUNCE_TIKS     10

void Port_Initialized (void);
void Timer0_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void __interrupt(high_priority) tcInt(void);

struct btn_debounce
{
    unsigned char counter;
    char status : 1 ; //one bit flags
} Button_x1, Button_x2, Button_x3, Button_x4;

unsigned char Data1[1] = "1";
unsigned char Data2[1] = "2";

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 = 0xF;      // Button connected to RB0-RB3
    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 WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    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
    EN = 0;                         //clear enable
    RS = 0;                         //going to write command
    TRISBbits.TRISB6 = 0;           //Set enable to output
    TRISBbits.TRISB4 = 0;           //set RS to output
    TRISBbits.TRISB5 = 0;
    RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __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(0x0C);             //turn on display
    WriteCommand(0x01);             //clear display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    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
    EN = 1;                                 //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    EN = 0;                                 //disable it
    NOP();
}

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

void Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;  
  }
  else
  {
    if( Button_x1.status == 0)
    {
      Button_x1.counter++;
      if(Button_x1.counter == DEBOUNCE_TIKS)
          Button_x1.status = 1;    // fully debounced
           LCD_Data(Data1);
    }
  }
}

void Sw2 ()
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;  
  }
  else
  {
    if( Button_x2.status == 0)
    {
      Button_x2.counter++;
      if(Button_x2.counter == DEBOUNCE_TIKS)
          Button_x2.status = 1;    // fully debounced
           LCD_Data(Data2);
    }
  }
}

void Run_Debounce(void)
{
Sw1 ();
Sw2 ();
}

void main(void)
{

    Button_x1.counter = 0;
    Button_x1.status = 0;
   
    Button_x2.counter = 0;
    Button_x2.status = 0;
   
    Port_Initialized ();
    Timer0_Initialized ();
    LCD_Initialized();

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

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;

  }

}
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
You don’t have brackets after the IF statements on lines 218 and 239.

But you should not be doing the LCD in the debounce routine at all. Schedule and run the debounce functions as simple utility functions then use their output flags in main to control other things. You were doing that before.

Also, you are not resetting the LCD cursor between messages so the text will be running together like your photo shows.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
By the way, you are reserved for status flag whole byte but using only one bit value 0 or 1. It is better to reserve only one bit for this flag, then you save one byte within each button structure variable:
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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define RS                LATAbits.LATA2
#define RW                LATAbits.LATA1
#define EN                LATAbits.LATA0

#define  LCDPORT          LATD
#define  LCDTRISD         LATD

#define DEBOUNCE_TIKS     10

void Port_Initialized (void);
void Timer0_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void __interrupt(high_priority) tcInt(void);

struct btn_debounce
{
    unsigned char counter;
    char status : 1 ; //one bit flags
    char lcd :1; // signal for LCD routine
} Button_x1, Button_x2, Button_x3, Button_x4;

unsigned char Data1[1] = "1";
unsigned char Data2[1] = "2";

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 = 0xF;      // Button connected to RB0-RB3
    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 WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    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
    EN = 0;                         //clear enable
    RS = 0;                         //going to write command
    TRISBbits.TRISB6 = 0;           //Set enable to output
    TRISBbits.TRISB4 = 0;           //set RS to output
    TRISBbits.TRISB5 = 0;
    RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __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(0x0C);             //turn on display
    WriteCommand(0x01);             //clear display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    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
    EN = 1;                                 //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    EN = 0;                                 //disable it
    NOP(); 
}

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

void Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;   
  }
  else
  {
    if( Button_x1.status == 0)
    {
      Button_x1.counter++;
      if(Button_x1.counter == DEBOUNCE_TIKS)
          Button_x1.status = 1;    // fully debounced
          Button_x1.lcd = 1;
    }
  }
}

void Sw2 ()
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;   
  }
  else
  {
    if( Button_x2.status == 0)
    {
      Button_x2.counter++;
      if(Button_x2.counter == DEBOUNCE_TIKS)
          Button_x2.status = 1;    // fully debounced
           Button_x2.lcd = 1;
    }
  }
}

void Run_Debounce(void)
{
 Sw1 ();
 Sw2 ();
}

void main(void)
{
 
    Button_x1.counter = 0;
    Button_x1.status = 0;
    
    Button_x2.counter = 0;
    Button_x2.status = 0;
    
    Port_Initialized ();
    Timer0_Initialized ();
    LCD_Initialized();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
              
                    
        if ( Button_x1.lcd == 1)
           {
               LCD_Data(Data1);
               Button_x1.lcd = 0;
           }
        
          
         if ( Button_x2.lcd == 1)
           {
                LCD_Data(Data2);
                Button_x2.lcd = 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;
  }

}
 

trebla

Joined Jun 29, 2019
599
IF statements, started from line 219 and 238 are multi-line and must be inside block :

Code:
if(Button_x2.counter == DEBOUNCE_TIKS) 
{
          Button_x2.status = 1;    // fully debounced
           Button_x2.lcd = 1;
}
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
button 2.png

Why is data displaying only on four position

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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define RS                LATAbits.LATA2
#define RW                LATAbits.LATA1
#define EN                LATAbits.LATA0

#define  LCDPORT          LATD
#define  LCDTRISD         LATD

#define DEBOUNCE_TIKS     10

void Port_Initialized (void);
void Timer0_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void __interrupt(high_priority) tcInt(void);
void Sw1 ();
void Sw2 ();

struct btn_debounce
{
    unsigned char counter;
    char status : 1 ; //one bit flags
    char lcd :1; // signal for LCD routine
} Button_x1, Button_x2, Button_x3, Button_x4;

unsigned char Data1[1] = "1";
unsigned char Data2[1] = "2";

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 = 0xF;      // Button connected to RB0-RB3
    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 WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    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
    EN = 0;                         //clear enable
    RS = 0;                         //going to write command
    TRISBbits.TRISB6 = 0;           //Set enable to output
    TRISBbits.TRISB4 = 0;           //set RS to output
    TRISBbits.TRISB5 = 0;
    RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __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(0x0C);             //turn on display
    WriteCommand(0x01);             //clear display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    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
    EN = 1;                                 //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    EN = 0;                                 //disable it
    NOP(); 
}

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

void Run_Debounce(void)
{
 Sw1 ();
 Sw2 ();
}

void Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;   
    }
   else
   {
      if( Button_x1.status == 0)
      {
         Button_x1.counter++;
         if(Button_x1.counter == DEBOUNCE_TIKS)
         {
            Button_x1.status = 1;    // fully debounced
             Button_x1.lcd = 1;
         }
       }
   }
}
void Sw2 (void)
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;   
  }
  else
  {
    if( Button_x2.status == 0)
    {
        Button_x2.counter++;
        if(Button_x2.counter == DEBOUNCE_TIKS)
        {
          Button_x2.status = 1;    // fully debounced
           Button_x2.lcd = 1;
        }
    }

  }
}


void main(void)
{
 
    Button_x1.counter = 0;
    Button_x1.status = 0;
    
    Button_x2.counter = 0;
    Button_x2.status = 0;
    
    Port_Initialized ();
    Timer0_Initialized ();
    LCD_Initialized();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
              
                    
        if ( Button_x1.lcd == 1)
           {
               LCD_Data(Data1);
            //   WriteCommand(0x80); //// Move the cursor to beginning of first line.
               Button_x1.lcd = 0;
              
           }
                
         if ( Button_x2.lcd == 1)
           {
                LCD_Data(Data2);
              
                Button_x2.lcd = 0;
                
           }
          WriteCommand(0x80); //// Move the cursor to beginning of first line.
        }   
    }
}

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;

  }

}
 

hexreader

Joined Apr 16, 2011
619
Change:
Code:
unsigned char Data1[1] = "1";
unsigned char Data2[1] = "2";
"1" is two bytes, not one
unsigned char Data1[] = "1";
unsigned char Data2[] = "2";
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Change:
Code:
unsigned char Data1[1] = "1";
unsigned char Data2[1] = "2";
Thank you. It works

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)


__bit Interrupt_Flag_1ms;

#define Button_1          PORTBbits.RB0
#define Button_2          PORTBbits.RB1
#define Button_3          PORTBbits.RB2
#define Button_4          PORTBbits.RB3

#define RS                LATAbits.LATA2
#define RW                LATAbits.LATA1
#define EN                LATAbits.LATA0

#define  LCDPORT          LATD
#define  LCDTRISD         LATD

#define DEBOUNCE_TIKS     10

void Port_Initialized (void);
void Timer0_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void __interrupt(high_priority) tcInt(void);
void Sw1 ();
void Sw2 ();

struct btn_debounce
{
    unsigned char counter;
    char status : 1 ; //one bit flags
    char lcd :1; // signal for LCD routine
} Button_x1, Button_x2, Button_x3, Button_x4;

unsigned char Data1[] = "1";
unsigned char Data2[] = "2";

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 = 0xF;      // Button connected to RB0-RB3
    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 WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                               //wait until not busy
    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
    EN = 0;                         //clear enable
    RS = 0;                         //going to write command
    TRISBbits.TRISB6 = 0;           //Set enable to output
    TRISBbits.TRISB4 = 0;           //set RS to output
    TRISBbits.TRISB5 = 0;
    RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __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(0x0C);             //turn on display
    WriteCommand(0x01);             //clear display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    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
    EN = 1;                                 //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    EN = 0;                                 //disable it
    NOP();
}

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

void Run_Debounce(void)
{
Sw1 ();
Sw2 ();
}

void Sw1 ()
{
   if (Button_1 == 0)
    {
      Button_x1.counter = 0;
      Button_x1.status = 0;  
    }
   else
   {
      if( Button_x1.status == 0)
      {
         Button_x1.counter++;
         if(Button_x1.counter == DEBOUNCE_TIKS)
         {
            Button_x1.status = 1;    // fully debounced
             Button_x1.lcd = 1;
         }
       }
   }
}
void Sw2 (void)
{
   if (Button_2 == 0)
    {
      Button_x2.counter = 0;
      Button_x2.status = 0;  
  }
  else
  {
    if( Button_x2.status == 0)
    {
        Button_x2.counter++;
        if(Button_x2.counter == DEBOUNCE_TIKS)
        {
          Button_x2.status = 1;    // fully debounced
           Button_x2.lcd = 1;
        }
    }

  }
}


void main(void)
{

    Button_x1.counter = 0;
    Button_x1.status = 0;
   
    Button_x2.counter = 0;
    Button_x2.status = 0;
   
    Port_Initialized ();
    Timer0_Initialized ();
    LCD_Initialized();

    while (1)
    {
        if (Interrupt_Flag_1ms == 1)
           {
               Interrupt_Flag_1ms = 0;  // clear the flag for next time
               Run_Debounce();        // process switch
             
                   
        if ( Button_x1.lcd == 1)
           {
               LCD_Data(Data1);
            //   WriteCommand(0x80); //// Move the cursor to beginning of first line.
               Button_x1.lcd = 0;
             
           }
               
         if ( Button_x2.lcd == 1)
           {
                LCD_Data(Data2);
             
                Button_x2.lcd = 0;
               
           }
          WriteCommand(0x80); //// Move the cursor to beginning of first line.
        }  
    }
}

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
I am trying to read matrix keypad on board
keym.jpg

Pull Up resistors
I set output pins to LOW.
I Read input pin.
If input pin is LOW, then a key is pressed.

Pull Down resistors
I set output pins to High.
I Read input pin.
If input pin is High, then a key is pressed.

I wrote a program to test the one key. code written as following. When I ran code LED is turning ON continuously if push key or if I don't push the key

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)

__bit Interrupt_Flag_1ms;

#define B1          PORTBbits.RB0      //C1 Set RB0 as input pin
#define B2          LATBbits.LATB1     //R1 Set RB1 as output pin

#define LED         LATDbits.LATD0

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 = 0x01;      // 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 main(void)
{
    Port_Initialized ();

    B1 = 1;
    B2 = 0;
    LED = 0;           
    while (1)
    {
    
      if (B1 == 0)
      {
           LED = 1;
       }
    }
}
I haven't added debounce routine I would do it later. I just want to read only one key
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Reading the code, that is what I would expect it to do.
I want the LED to be on whenever I press the button in Keypad for the first time. So in this process I don't need debounce routine so I haven't written code for debounce.

I'm surprised because I don't see a pull up pull down resistor on the board nor schematic. I have noticed in a google search that the pull up or pull down resistor is always connected to the keypad
 

JohnInTX

Joined Jun 26, 2012
4,787
I'm surprised because I don't see a pull up pull down resistor on the board nor schematic. I have noticed in a google search that the pull up or pull down resistor is always connected to the keypad
PORTD can be configured with internal pullups. I'd use that for driving the rows and reading the columns with those pullups. 4 outputs, 4 inputs. Section 11.5 in the datasheet.

And again, I think it is better to debug with MPLABX and PK3 using breakpoints to find where the code goes. Whenever you use an indicator like the LCD or an LED, you have added to your debugging task - you have to debug the indicator as well as the original task.
Just my $.02
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
PORTD can be configured with internal pullups. I'd use that for driving the rows and reading the columns with those pullups. 4 outputs, 4 inputs. Section 11.5 in the datasheet.
I have connected C1 to RD0 and R1 to RD1
Which switch should I test (#494) ? I am checking SW17 12

Is following configuration correct for Pull Up resistors?

I set output pin R1 to LOW.
I set input pin C1 to High.
I Read input pin.
If input pin is LOW, then a key is pressed.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I have connected C1 to RD0 and R1 to RD1
Which switch should I test (#494) ?
There is only 1 switch at the intersection of R1 and C1, #12.

I would hook up the ALL rows R4-R1to RD7-RD4 as outputs and the columns to C4-C1 to RD3-RD0 as inputs using TRISD=0x0f. Enable PORTD pull-ups using RDPU/. Init RD7-RD4 outputs to all 1 by writing to LATD. You do not have to write 1 to input port bits.

Turn on the first row by setting RD7 to 0. Read PORTD and look for any 0 bit in RD3-RD0. If you find one, that is your closed switch. If not, set RD7 and clear RD6 to select the next row and look again for any 0 on RD3-RD0. Continue until you find a closed switch at a row-column intersection or find no switch closed in which case, it is time to start the row output from the beginning. If you DO find a switch closed, a 0 bit in RD7-RD4 will indicate the row and a 0 bit in RD3-RD0 will indicate the column of the closed switch.

You should print the switch matrix with the port-bit assignments and run a few examples on paper before coding.
Example: if connected as I suggest, switch #12 closed at R1,C1 will have a PORTD value of
11101110
1110————the row output
——1110——the column input

This only one of many ways to do the scanning but it’s a starting point. You should not try to code it until you have a good grasp of how the low level scanning for a closed switch at an intersection of a row output and column input is done.

Don’t worry about debouncing or assigning an output code to a switch for now.
 
Last edited:
Top