ここに画像の説明を入力してください 質問 1- 以下のようなシステムでは、ユーザーは 4 桁のパスワードを入力する必要があります。プログラムを初めて実行すると、「パスワードを入力してください」と表示されます。ユーザーが 4 桁のパスワードを入力した後に正方形キーを押すと、パスワードが 1234 の場合、b0 に接続されている LED が点滅し、LCD 画面にパスワードを知っていることが表示されます。パスワードを 3 回間違えると、画面に「BLOKE」と表示されるはずです。そして、4 桁の「4321」ブロッキング パスワードを入力する必要があります。彼がブロッキング パスワードを正しく入力すると、b0 に接続された LED が点滅し、LCD にパスワードを知っていることが表示されます。
質問する
42 次
1 に答える
0
このスレッドはモデレーターによって数時間または数日で削除されると思います。
それまでは、楽しみながら、PIC16F877A、LCD モジュール、および 3x4 キーパッドが動作する Proteus シミュレーション モデルを取得する必要があるインフラストラクチャを実装するアプリケーションを投稿します。
パスワード検証を実装するコードは、元の投稿者が実装するために残されています。
このコードを Proteus シミュレーション ツールでテストしていないことに注意してください。MPLABX シミュレーターでは動作するようですが、あまり意味がありません。
/*
* 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();
}
}
}
于 2022-01-28T08:05:30.157 に答える