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.
Asked
Active
Viewed 73 times
-3
-
1What 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
-
1Today 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 Answers
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