Arduino与Proteus仿真实例-密码输入、验证与更新仿真

密码输入、验证与更新仿真

本次实例将通过4X4矩阵键盘、LCD1602、EEPROM实现一个密码输入匹配、储存、更新。

1、仿真电路原理图

在这里插入图片描述

在仿真电路原理图中,4X4矩阵键盘通过PCF8574 IO扩展器驱动,请参考前面文章:

LCD1602通过4线连接方式驱动,请参考:

EEPROM数据储存与读取,请参考:

2、驱动代码实现

本次应用实例主要功能分为:

  • 密码储存与读取
  • 密码输入与验证
  • 密码更新

1)导入依赖头文件

1
2
3
4
5
6
#include <LiquidCrystal.h>
#include <Keypad\_I2C.h>
#include <Keypad.h>
#include <Wire.h>
#include <EEPROM.h>

2)设备定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// LCD1602
LiquidCrystal lcd(12, 11,5, 4, 3, 2);// RS、RW,D0~D7

#define KEYPAD\_I2CADDR 0x20
// I2C键盘
const byte ROWS = 4; // 4行
const byte COLS = 4; // 4列
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'\*','0','#','D'}
};
// PCF8574IO映射
byte rowPins[ROWS] = {0, 1, 2, 3}; // 连接键盘行引脚
byte colPins[COLS] = {4, 5, 6, 7}; // 连接键盘列引脚

TwoWire \*jwire = &Wire; // 键盘对象
Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, KEYPAD_I2CADDR, PCF8574, jwire );

3)密码储存及操作定义

1
2
3
4
5
6
7
8
9
10
11
12
#define PASSWORD\_ADDR 0x10 // 密码储存地址
#define PASSWORD\_INIT\_ADDR 0x01 // 密码状态地址
#define PASSWORD\_LEN 0x06 // 密码长度
#define PASSWORD\_UPDATE "\*#01#\*" // 密码更新
#define PASSWORD\_CMD\_COMPARE 0x01 // 密码验证
#define PASSWORD\_CMD\_UPDATE 0x02 // 密码更新

const char inited_password[PASSWORD_LEN] = {'1','2','3','4','5','6'}; // 默认密码
char saved_password[PASSWORD_LEN] = {0}; // EEPROM储存的密码
char current_password[PASSWORD_LEN] = {0}; // 当前输入密码
char password_cmd = PASSWORD_CMD_COMPARE; // 密码操作命令

4)默认密码初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 初始化密码
void init\_password(){
int isInited = 0;
isInited = EEPROM.read(PASSWORD_INIT_ADDR); // 读取密码状态
if(isInited != 1){ // 密码未初始化
int addr = PASSWORD_ADDR;
for(unsigned char i = 0;i < PASSWORD_LEN;i++){
EEPROM.write(addr,inited_password[i]); // 写入默认密码
addr++;
}
EEPROM.write(PASSWORD_INIT_ADDR,1); // 更新密码标志
Serial.println("initialized password");
}
}

init_password函数用于初始化默认密码,在第一次开机启动时通过调用EEPROM.write函数将默认密码数据写入EEPROM。

5)从EEPROM中读取密码

1
2
3
4
5
6
7
8
9
// 读取密码
void read\_password(){
int addr = PASSWORD_ADDR;
for(unsigned char i = 0;i < PASSWORD_LEN;i++){
saved_password[i] = (char)EEPROM.read(addr);
addr++;
}
}

read_password函数用于从EEPROM中读取密码。通过调用EEPROM.read函数实现。

6)密码验证

1
2
3
4
5
6
7
8
9
10
// 比较密码
bool compare\_password(char\* pass){
for(unsigned char i = 0;i < PASSWORD_LEN;i++){
if(pass[i] != saved_password[i]){
return false;
}
}
return true;
}

compare_password函数用于比较当前输入密码与设定的密码。

7)更新密码

1
2
3
4
5
6
7
8
9
10
// 更新密码
void update\_password(char\* pass){
int addr = PASSWORD_ADDR;
for(unsigned char i = 0;i < PASSWORD_LEN;i++){
EEPROM.write(addr,inited_password[i]);
addr++;
}
Serial.println("password updated");
}

update_password函数用于更新密码。将最新设置的密码写入到EEPROM中。

8)更新密码指定检测

1
2
3
4
bool is\_update\_password(char\* pass){
return(pass[0] == '\*' && pass[1] == '#' && pass[2] == '0' && pass[3] == '1' && pass[4] == '#' && pass[5] == '\*');
}

9)系统初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void setup()
{
Serial.begin(9600); // 初始化串口
init\_password(); // 初始化密码
read\_password(); // 读取密码

Serial.print("inited password:");
for(unsigned char i = 0;i < PASSWORD_LEN;i++){
Serial.print((char)saved_password[i]);
}
Serial.println();
// 初始化LCD1605
lcd.begin(16, 2); // 设置LCD的行和列

// 键盘初始化
jwire->begin();
kpd.begin();

}

10)功能逻辑实现

loop函数实现密码输入、验证、更新逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
unsigned char index = 0; // 当前密码输入索引 
bool is_updating_password = false; // 当前页面是否正在更新密码
void loop()
{
char key = kpd.getKey(); // 扫描键盘输入
if(key){
if(password_cmd == PASSWORD_CMD_COMPARE){ // 密码验证状态输入
current_password[index] = key;
if(index == 0){
lcd.clear();
}
lcd.setCursor(index, 0);
lcd.print('\*');
}else{ // 密码更新状态输入
if(index == 0){
is_updating_password = true;
}
saved_password[index] = key;
current_password[index] = key;
lcd.setCursor(index, 2);
lcd.print((char)key);
}

Serial.print("index:");
Serial.print(index);
Serial.print(",key=");
Serial.println(key);
index++;
}
if(index == 6){
lcd.clear();
lcd.setCursor(0,0);
if(is\_update\_password(current_password)){ // 判断输入密码是否为更新指令
password_cmd = PASSWORD_CMD_UPDATE;
}
if(password_cmd == PASSWORD_CMD_UPDATE){ // 更新密码
if(!is_updating_password){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Update Password:");
}else{ // 更新密码输入完成
is\_update\_password(current_password);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Password Updated");
password_cmd = PASSWORD_CMD_COMPARE;
is_updating_password = false;
}
}else{ // 验证密码
password_cmd = PASSWORD_CMD_COMPARE;
if(compare\_password(current_password)){ // 验证成功
lcd.print("Password Passed");
}else{
lcd.print("Password Failed");
}
}
index = 0;

}

}

3、仿真结果

在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/127881315