前言

这个项目是 Raspberry Pi Pico 的密码锁系统,使用 I2C LCD 1602 显示屏作为显示, 4×4 矩阵键盘作为密码输入装置,继电器模拟门锁开关。

功能特性

  • 密码验证:输入密码后按 * 确认,正确则继电器吸合(模拟开锁)
  • 密码修改:按 # 进入修改流程,需先验证旧密码再设置新密码
  • 密码隐藏:输入时 LCD 第二行以 * 代替实际字符
  • 明文修改:修改密码时新密码以明文显示,便于核对
  • 扩展字符:支持 0-9A-D 作为密码字符(最多 16 位)
  • 默认密码735560

硬件需求

元件 规格 数量
Raspberry Pi Pico RP2040 1
I2C LCD 1602 16×2 字符,PCF8574 转接板 1
4×4 矩阵键盘 16 键薄膜/机械键盘 1
继电器模块 5V/3.3V 继电器 1
杜邦线 公母/母母 若干

引脚接线

外设 信号 Pico GPIO 物理引脚
LCD 1602 SDA GP4 Pin 6
LCD 1602 SCL GP5 Pin 7
LCD 1602 VCC 3.3V Pin 36
LCD 1602 GND GND Pin 38
键盘列 C1 GP18 Pin 24
键盘列 C2 GP19 Pin 25
键盘列 C3 GP20 Pin 26
键盘列 C4 GP21 Pin 27
键盘行 R1 GP10 Pin 14
键盘行 R2 GP11 Pin 15
键盘行 R3 GP12 Pin 16
键盘行 R4 GP13 Pin 17
继电器 控制信号 GP14 Pin 19

接线示意图

键盘布局

┌───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ A │
├───┼───┼───┼───┤
│ 4 │ 5 │ 6 │ B │
├───┼───┼───┼───┤
│ 7 │ 8 │ 9 │ C │
├───┼───┼───┼───┤
│ * │ 0 │ # │ D │
└───┴───┴───┴───┘

按键功能

按键 功能
0-9, A-D 密码字符输入
* 确认/提交密码
# 进入密码修改模式 / 取消返回

使用说明

开机

上电后 LCD 显示:

Enter Password:
█

光标在第二行首位闪烁,等待输入。

输入密码

逐位输入密码字符,LCD 以 * 显示:

Enter Password:
****█

验证密码

输入完毕后按 * 键:

  • 密码正确 → 显示 Successful,继电器吸合 300ms,1.5 秒后返回初始页面
  • 密码错误 → 显示 Wrong Password,1.5 秒后返回初始页面

修改密码

  1. 在初始页面按 # 键,进入旧密码验证:
    Old Password
    █
    
  2. 输入当前密码,按 * 确认:
    • 正确 → 进入新密码设置
    • 错误 → 显示 Wrong Password,返回旧密码页面重试
  3. 新密码设置页面:
    Change Password
    █
    
    输入新密码(明文显示,便于核对),按 * 确认
  4. 显示 Password Changed,2 秒后自动返回初始页面

在修改流程中随时按 # 可取消并返回初始页面。

程序结构

oled.c
├── LCD 1602 I2C 驱动 (PCF8574)
│   ├── lcd_init()            LCD 初始化 (4-bit 模式)
│   ├── lcd_send_byte()       发送字节 (命令/数据)
│   ├── lcd_clear()           清屏
│   ├── lcd_set_cursor()      设置光标位置
│   ├── lcd_char()            输出单个字符
│   └── lcd_string()          输出字符串
│
├── 4×4 矩阵键盘驱动
│   ├── keypad_init()         初始化键盘 GPIO
│   └── keypad_get_key()      扫描并返回按键字符
│
├── 密码系统
│   ├── show_enter_password_page()   初始输入页面
│   ├── show_old_password_page()     旧密码验证页面
│   ├── show_new_password_page()     新密码设置页面
│   ├── show_result()                结果提示页面
│   ├── display_asterisks()          以 * 显示输入
│   ├── display_plaintext()          明文显示输入
│   ├── append_input()               追加输入字符
│   ├── clear_input()                清空输入缓冲
│   └── relay_success()              继电器触发
│
└── main()                   主循环,状态机调度

状态机流程

                 ┌──────────────────────────┐
                 │   STATE_ENTER_PASSWORD   │
                 │  "Enter Password:"       │
                 │  第二行: ****光标          │
                 └─────┬──────────┬─────────┘
                   [*]验证    [#]修改
                    │          │
          ┌────────┴──┐  ┌────┴────────────────┐
          │ Successful │  │ STATE_OLD_PASSWORD  │
          │ 继电器吸合  │  │ "Old Password"      │
          └────────────┘  │ 第二行: ****光标     │
                          └────┬──────┬────────┘
                          [*]验证    [#]取消
                           │         │
                   ┌───────┴──┐  ┌───┴───────────┐
                   │ 验证通过  │  │ 返回初始页面    │
                   └────┬─────┘  └───────────────┘
                        │
               ┌────────┴───────────────┐
               │ STATE_NEW_PASSWORD     │
               │ "Change Password"      │
               │ 第二行: 明文+光标       │
               └────┬────────┬─────────┘
               [*]确认    [#]取消
                │         │
        ┌───────┴──┐  ┌───┴───────────┐
        │Password   │  │ 返回初始页面    │
        │Changed    │  └───────────────┘
        │(2秒后返回) │
        └───────────┘

编译和烧录

前提条件

编译

mkdir build && cd build
cmake ..
make

烧录

  1. 按住 Pico 上的 BOOTSEL 按钮
  2. 通过 USB 连接电脑
  3. 松开 BOOTSEL,Pico 显示为 USB 大容量存储设备
  4. build/oled.uf2 拖入 Pico 磁盘

常见问题

Q: LCD 无显示?

  • 检查 I2C 地址:代码默认 0x27,部分模块为 0x3F,修改 addr 变量
  • 确认 SDA/SCL 接线正确(GP4→SDA, GP5→SCL)

Q: 键盘无响应?

  • 确认行列引脚接线与代码定义一致
  • 行列引脚不能接反(列→GP18-21, 行→GP10-13)

Q: 继电器不动作?

  • 默认使用 GP13,与键盘行 R4 共用,确保接线正确
  • 如需独立引脚,修改 RELAY_SUCCESS_PIN

Github代码

代码参考

更多推荐