-3

enter image description here Question 1- In a system like the one below, the user is expected to enter a 4-digit password. The first time the program runs, it should say "Enter Password". When the user presses the Square key after entering the 4-digit password, if the password is 1234, the led connected to b0 should flash and the LCD screen should say you know the password. If he enters the password incorrectly 3 times, "BLOKE" should be written on the screen. And then he should enter the 4-digit "4321" blocking password. If he enters the blocking password correctly, the led connected to b0 should flash and the LCD should show you know the password.

  • 1
    What have you done so far? Is there any specific point/problem you're stuck at? On StackOverflow, people don't do your homework from scratch, and they expect some effort/research from you. – Tagli Jan 27 '22 at 14:27
  • 1
    Today is now 2022-JAN-28 03:27 and I wonder how long is will take the moderators to delete this topic. The poster has not provided any proof of work so that action seems justified. – Dan1138 Jan 28 '22 at 03:28
  • Do you really expect an answer with such a title???? Hmmmm – Mike Jan 28 '22 at 05:57
  • 1
    @Mike, The OP has no right to expect an answer but I made one for him anyway. What I posted is about 90% of the work, All the OP needs to do now is the other 90% of the work and actually comprehend what I provided then extend it to complete the assignment,. – Dan1138 Jan 28 '22 at 08:10

1 Answers1

0

I expect this thread to be deleted by the moderators in a few hours or maybe days.

Until then I am going to have some fun and post an application that implements the infrastructure that "should" get the Proteus simulation models for the PIC16F877A, LCD module and 3x4 Keypad working.

The code that implements the password validation is left for the Original Poster to implement.

Be warned I have not tested this code with the Proteus simulation tool. It seems to work in the MPLABX simulator but that's not saying much.

/*
 * File:    main.c
 * Author:  dan1138
 * Target:  PIC16F877A
 * Compiler: XC8 v2.32
 * IDE: MPLABX v5.50
 * 
 * Created on January 27, 2022, 10:29 PM
 * 
 *                          PIC16F877A
 *                  +----------:_:----------+
 *        VPP ->  1 : MCLR/VPP      PGD/RB7 : 40 <> LCD_D7/PGD
 *            <>  2 : RA0/AN0       PGC/RB6 : 39 <> LCD_D6/PGC
 *            <>  3 : RA1               RB5 : 38 <> LCD_D5
 *            <>  4 : RA2               RB4 : 37 <> LCD_D4
 *            <>  5 : RA3               RB3 : 36 <> LCD_EN
 *            <>  6 : RA4               RB2 : 35 <> LCD_RW
 *            <>  7 : RA5               RB1 : 34 <> LCD_RS
 *            <>  8 : RE0          INT0/RB0 : 33 <> LED
 *            <>  9 : RE1               VDD : 32 <- PWR
 *            <> 10 : RE2               VSS : 31 <- GND
 *        PWR -> 11 : VDD               RD7 : 30 <> 
 *        GND -> 12 : VSS               RD6 : 29 <> 
 * 20MHz XTAL <> 13 : OSC1              RD5 : 28 <> 
 * 20MHz XTAL <> 14 : OSC2              RD4 : 27 <> 
 *      KP_C3 <> 15 : RC0/SOSCO   RX/DT/RC7 : 26 <> KP_RD
 *      KP_C2 <> 16 : RC1/SOSCI   TX/CK/RC6 : 25 <> KP_RC
 *      KP_C1 <> 17 : RC2/CCP1          RC5 : 24 <> KP_RB
 *            <> 18 : RC3               RC4 : 23 <> KP_RA
 *            <> 19 : RD0               RD3 : 22 <> 
 *            <> 20 : RD1               RD2 : 21 <> 
 *                  +-----------------------:
 *                           DIP-40
 * Description:
 * 
 */
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

/*
 * Tell compiler what we intend to set the system oscillator frequency as.
 */
#define _XTAL_FREQ (20000000UL)

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

/* Define the LCD port pins */
#define LCD_DATA_BITS_MASK  0x3C
#define LCD_PORT_OUT        PORTC
#define LCD_PORT_DIR        TRISC

#define LCD_RS_PIN          PORTBbits.RB1
#define LCD_RW_PIN          PORTBbits.RB2
#define LCD_EN_PIN          PORTBbits.RB3
#define LCD_D4_PIN          PORTBbits.RB4
#define LCD_D5_PIN          PORTBbits.RB5
#define LCD_D6_PIN          PORTBbits.RB6
#define LCD_D7_PIN          PORTBbits.RB7

#define LCD_RS_DIR          TRISBbits.TRISB1
#define LCD_RW_DIR          TRISBbits.TRISB2
#define LCD_EN_DIR          TRISBbits.TRISB3
#define LCD_D4_DIR          TRISBbits.TRISB4
#define LCD_D5_DIR          TRISBbits.TRISB5
#define LCD_D6_DIR          TRISBbits.TRISB6
#define LCD_D7_DIR          TRISBbits.TRISB7

/* Clear display command */
#define CLEAR_DISPLAY       0b00000001

/* Return home command */
#define RETURN_HOME         0b00000010

/* Display ON/OFF Control defines */
#define DON                 0b00001111   /* Display on      */
#define DOFF                0b00001011   /* Display off     */
#define CURSOR_ON           0b00001111   /* Cursor on       */
#define CURSOR_OFF          0b00001101   /* Cursor off      */
#define BLINK_ON            0b00001111   /* Cursor Blink    */
#define BLINK_OFF           0b00001110   /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT      0b00010011   /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT     0b00010111   /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT     0b00011011   /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT    0b00011111   /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT            0b00101111   /* 4-bit Interface               */
#define EIGHT_BIT           0b00111111   /* 8-bit Interface               */
#define LINE_5X7            0b00110011   /* 5x7 characters, single line   */
#define LINE_5X10           0b00110111   /* 5x10 characters               */
#define LINES_5X7           0b00111011   /* 5x7 characters, multiple line */

/* Start address of each line */
#define LINE_ONE            0x00
#define LINE_TWO            0x40

static void LCD_E_Pulse(void)
{
    LCD_EN_PIN = 1;
    __delay_us(4);
    LCD_EN_PIN = 0;
    __delay_us(4);
}

static void LCD_DelayPOR(void)
{
    __delay_ms(15);
}

static void LCD_Delay(void)
{
    __delay_ms(5);
}

static void LCD_PutByte(unsigned char LCD_Data)
{
    LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
    
    /* send first(high) nibble */
    LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
    if(LCD_Data & 0x10) LCD_D4_PIN = 1;
    if(LCD_Data & 0x20) LCD_D5_PIN = 1;
    if(LCD_Data & 0x40) LCD_D6_PIN = 1;
    if(LCD_Data & 0x80) LCD_D7_PIN = 1;
    LCD_E_Pulse();
    
    /* send second(low) nibble */
    LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
    if(LCD_Data & 0x01) LCD_D4_PIN = 1;
    if(LCD_Data & 0x02) LCD_D5_PIN = 1;
    if(LCD_Data & 0x04) LCD_D6_PIN = 1;
    if(LCD_Data & 0x08) LCD_D7_PIN = 1;
    LCD_E_Pulse();

    LCD_PORT_DIR |= LCD_DATA_BITS_MASK; /* make LCD data bits inputs */
}

void LCD_SetPosition(unsigned char data)
{
    LCD_RS_PIN = 0;
    LCD_PutByte((unsigned char)(data | 0x80));
    __delay_us(40);
}

void LCD_WriteCmd(unsigned char data)
{
    LCD_RS_PIN = 0;
    LCD_PutByte(data);
    __delay_ms(4);
}

void LCD_WriteData(unsigned char data)
{
    LCD_RS_PIN = 1;
    LCD_PutByte(data);
    LCD_RS_PIN = 0;
    __delay_us(40);
}

void LCD_Init(void) 
{
    unsigned char LCD_Data;
    
    LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK;    /* make LCD data bits outputs */
    LCD_EN_DIR = 0;                         /* make LCD Enable strobe an output */
    LCD_RW_DIR = 0;                         /* make LCD Read/Write an output */
    LCD_RS_DIR = 0;                         /* make LCD Register select an output */
    LCD_EN_PIN = 0;                         /* set LCD Enable strobe to not active */
    LCD_RW_PIN = 0;                         /* set LCD write mode  */
    LCD_RS_PIN = 0;                         /* set LCD Register select to command group */
    LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
    LCD_DelayPOR();                         /* wait for LCD power on to complete */

    /* Force LCD to 8-bit mode */
    LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
    LCD_D4_PIN = 1;
    LCD_D5_PIN = 1;
    LCD_E_Pulse();
    LCD_Delay();
    LCD_E_Pulse();
    LCD_Delay();
    LCD_E_Pulse();
    LCD_Delay();
    
    /* Set LCD to 4-bit mode */
    LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
    LCD_D5_PIN = 1;
    LCD_E_Pulse();
    LCD_Delay();

    /* Initialize LCD mode */
    LCD_WriteCmd(FOUR_BIT & LINES_5X7);

    /* Turn on display, Setup cursor and blinking */
    LCD_WriteCmd(DOFF & CURSOR_OFF & BLINK_OFF);
    LCD_WriteCmd(DON & CURSOR_OFF & BLINK_OFF);
    LCD_WriteCmd(CLEAR_DISPLAY);
    LCD_WriteCmd(SHIFT_CUR_LEFT);

    /* Set first position on line one, left most character */
    LCD_SetPosition(LINE_ONE);
}
/*
 * Hook for printf
 */
void putch(char txData)
{
    LCD_WriteData(txData);
}
/*
 * Keypad 3x4
 */
#define KP_DEBOUNCE_COUNT (16)

#define KP_RA_IN      PORTCbits.RC4
#define KP_RB_IN      PORTCbits.RC5
#define KP_RC_IN      PORTCbits.RC6
#define KP_RD_IN      PORTCbits.RC7
#define KP_C1_OUT     PORTCbits.RC2
#define KP_C2_OUT     PORTCbits.RC1
#define KP_C3_OUT     PORTCbits.RC0

#define KP_RA_IN_DIR  TRISCbits.TRISC4
#define KP_RB_IN_DIR  TRISCbits.TRISC5
#define KP_RC_IN_DIR  TRISCbits.TRISC6
#define KP_RD_IN_DIR  TRISCbits.TRISC7
#define KP_C1_OUT_DIR TRISCbits.TRISC2
#define KP_C2_OUT_DIR TRISCbits.TRISC1
#define KP_C3_OUT_DIR TRISCbits.TRISC0

enum eKeyEvent
{
    eNoEvent = 0,
    eKeyChanged
};

typedef enum eKeyEvent eKeyEvent_t;

struct sKeypadEvent
{
    unsigned int ButtonMatrix;
    unsigned int ChangedMask;    
};

typedef struct sKeypadEvent KeypadEvent_t;

static unsigned int  KP_Sample;
static unsigned int  KP_Last;
static unsigned int  KP_Changed;
static unsigned int  KP_Stable;
static unsigned char KP_DebounceCounter;
/*
 * Initialize the GPIO pins used for the 3x4 keypad
 */
void Keypad_Init(void)
{
    KP_RB_IN_DIR  = 1;
    KP_RB_IN_DIR  = 1;
    KP_RC_IN_DIR  = 1;
    KP_RD_IN_DIR  = 1;
    KP_C1_OUT_DIR = 0;
    KP_C2_OUT_DIR = 0;
    KP_C3_OUT_DIR = 0;
    KP_Last = 0;
    KP_DebounceCounter = 0;
}
/*
 * Called from ISR handler to sample all keys
 * in the keypad matrix, debounce and update the
 * stable state.
 */
void Keypad_Scan(void)
{
    KP_Sample = 0;
    KP_C1_OUT = 1;
    KP_C2_OUT = 1;
    KP_C3_OUT = 1;
    KP_C2_OUT_DIR = 1;
    KP_C3_OUT_DIR = 1;
    KP_C1_OUT_DIR = 0;
    KP_C1_OUT = 0;
    if (!KP_RA_IN) KP_Sample |= 0x0001;
    if (!KP_RB_IN) KP_Sample |= 0x0002;
    if (!KP_RC_IN) KP_Sample |= 0x0004;
    if (!KP_RD_IN) KP_Sample |= 0x0008;
    KP_C1_OUT = 1;
    KP_C1_OUT_DIR = 1;
    KP_C3_OUT_DIR = 1;
    KP_C2_OUT_DIR = 0;
    KP_C2_OUT = 0;
    if (!KP_RA_IN) KP_Sample |= 0x0010;
    if (!KP_RB_IN) KP_Sample |= 0x0020;
    if (!KP_RC_IN) KP_Sample |= 0x0040;
    if (!KP_RD_IN) KP_Sample |= 0x0080;
    KP_C2_OUT = 1;
    KP_C2_OUT_DIR = 1;
    KP_C1_OUT_DIR = 1;
    KP_C3_OUT_DIR = 0;
    KP_C3_OUT = 0;
    if (!KP_RA_IN) KP_Sample |= 0x0100;
    if (!KP_RB_IN) KP_Sample |= 0x0200;
    if (!KP_RC_IN) KP_Sample |= 0x0400;
    if (!KP_RD_IN) KP_Sample |= 0x0800;
    KP_C2_OUT = 0;
    KP_C1_OUT = 0;
    KP_C1_OUT_DIR = 0;
    KP_C2_OUT_DIR = 0;
    KP_C3_OUT_DIR = 0;
    
    /* check if matrix changed since last scan */
    if ((KP_Sample ^ KP_Last) != 0)
    {
        KP_Last = KP_Sample;
        KP_DebounceCounter = 0;
        return;
    }

    /* check if we have sampled inputs for long enough to debounce */
    if (KP_DebounceCounter < KP_DEBOUNCE_COUNT)
    {
        KP_DebounceCounter++;
        return;
    }

    /* Update the stable output only after pevious stable state has been read */
    if (KP_Changed == 0)
    {
        KP_Changed = KP_Sample ^ KP_Stable;
        KP_Stable = KP_Sample;
    }
}
/*
 * Returns non-zero when a key event occurs.
 * A key event is when one key is pressed or released.
 */
eKeyEvent_t Keypad_GetEvent(void)
{
    eKeyEvent_t Event;
    

    INTCONbits.TMR0IE = 0;  /* disable tick to read keypad sample memory */
    if (KP_Changed == 0)
    {
        Event = eNoEvent;
    }
    else
    {
        Event = eKeyChanged;
    }
    INTCONbits.TMR0IE = 1;  /* enable tick */
    
    return Event;
}
/*
 * Returns ASCII character of keypad event.
 * If more than one key is pressed returns ZERO.
 */
unsigned char Keypad_GetKey(KeypadEvent_t * KeypadEvent)
{
    unsigned char Key;
    unsigned int ButtonMatrix;
    unsigned int ChangedMask;    

    Key = 0;
    INTCONbits.TMR0IE = 0;  /* disable tick to read keypad sample memory */
    ButtonMatrix = KP_Stable;
    ChangedMask  = KP_Changed;
    /* Tell ISR we have read the current state */
    KP_Changed = 0;
    INTCONbits.TMR0IE = 1;  /* enable tick */

    /* return current state of the keypad matrix */
    if (KeypadEvent)
    {
        KeypadEvent->ButtonMatrix = ButtonMatrix;
        KeypadEvent->ChangedMask  = ChangedMask;
    }
    /* decode key in ASCII */
    if (ChangedMask)
    {
        switch (ButtonMatrix)
        {
        case 0x0001U:
            Key = '1';
            break;
        case 0x0002U:
            Key = '4';
            break;
        case 0x0004U:
            Key = '7';
            break;
        case 0x0008U:
            Key = '*';
            break;
        case 0x0010U:
            Key = '2';
            break;
        case 0x0020U:
            Key = '5';
            break;
        case 0x0040U:
            Key = '8';
            break;
        case 0x0080U:
            Key = '0';
            break;
        case 0x0100U:
            Key = '3';
            break;
        case 0x0200U:
            Key = '6';
            break;
        case 0x0400U:
            Key = '9';
            break;
        case 0x0800U:
            Key = '#';
            break;
        default:
            Key = 0;
            break;
        }
    }
    return Key;
}
/*
 * Setup TIMER0 to assert an interrupt every 16384 instruction cycles
 */
void Tick_Init(void)
{
    INTCONbits.TMR0IE = 0;
    OPTION_REG = 0xD3;      /* TMR0 clock FOSC/4Y, TMR0 prescale 1:16      */
    TMR0 = 0;               /* TIMER0 will assert the overflow flag every 256*16 (4096)               */
    INTCONbits.TMR0IF = 0;  /* instruction cycles, with a 5MHz oscillator this is 0.8192 milliseconds. */
    INTCONbits.TMR0IE = 1;
}
/*
 * Main application
 */

volatile unsigned char SysTick;

void main(void) 
{
    unsigned int  KP_sample;
    unsigned char Key;
    KeypadEvent_t Keypad_Event;

    /* Disable all interrupt sources */
    INTCON = 0;
    PIE1 = 0;
    PIE2 = 0;
    /* Make all GPIO pins digital */
    ADCON1 = 0x0F;
    CMCON = 0x07;
    
    LCD_Init();
    Keypad_Init();
    Tick_Init();
    
    /* Enable interrupt system */
    INTCONbits.PEIE = 1;
    INTCONbits.GIE  = 1;

    __delay_ms(100);

    LCD_SetPosition(LINE_ONE);
    printf("Enter Password");
    
    /*
     * Application loop
     */
    for(;;)
    {
        /* check for and process key presses */
        if (Keypad_GetEvent() == eKeyChanged)
        {
            LCD_SetPosition(LINE_TWO);
            printf("Key Pressed:    ");
            Key = Keypad_GetKey(&Keypad_Event);
            if (Key != 0)
            {
                LCD_SetPosition(LINE_TWO+13);
                LCD_WriteData(Key);
                switch (Key)
                {
                    case '0':
                        break;
                    case '1':
                        break;
                    case '2':
                        break;
                    case '3':
                        break;
                    case '4':
                        break;
                    case '5':
                        break;
                    case '6':
                        break;
                    case '7':
                        break;
                    case '8':
                        break;
                    case '9':
                        break;
                    case '*':
                        break;
                    case '#':
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
/*
 * Interrupt handlers
 */
void __interrupt() ISR_Handler(void)
{
    /* Handle system tick */
    if (INTCONbits.TMR0IE)
    {
        if(INTCONbits.TMR0IF)
        {
            INTCONbits.TMR0IF = 0;
            SysTick++;
            Keypad_Scan();
        }
    }
}
Dan1138
  • 1,150
  • 8
  • 11