/*
* ESP32-S3 + 4x4 矩阵键盘 + SSD1306 OLED 显示屏
* 功能:按键后将按键值显示到 OLED 屏幕上
*
* 接线说明:
* ── OLED (I2C) ──────────────────────
* GND → ESP32-S3 GND
* VCC → ESP32-S3 3.3V
* SCL → ESP32-S3 GPIO 9
* SDA → ESP32-S3 GPIO 8
*
* ── 4x4 矩阵键盘 ────────────────────
* 键盘共8根线(从左到右):
* R1 → GPIO 4
* R2 → GPIO 5
* R3 → GPIO 6
* R4 → GPIO 7
* C1 → GPIO 15
* C2 → GPIO 16
* C3 → GPIO 17
* C4 → GPIO 18
*
* 所需库:
* - Adafruit SSD1306
* - Adafruit GFX Library
* - Keypad (by Mark Stanley)
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>
// ─── OLED 配置 ───────────────────────────────────────────────
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // 无复位引脚
#define SCREEN_ADDRESS 0x3C // SSD1306 默认 I2C 地址
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ─── I2C 引脚(ESP32-S3 自定义) ─────────────────────────────
#define SDA_PIN 8
#define SCL_PIN 9
// ─── 矩阵键盘配置 ────────────────────────────────────────────
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {4, 5, 6, 7}; // 行引脚
byte colPins[COLS] = {15, 16, 17, 18}; // 列引脚
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ─── 全局变量 ────────────────────────────────────────────────
String inputBuffer = ""; // 存储已输入的按键序列
const int MAX_CHARS = 20; // 最多显示字符数(超出自动清空)
// ─── 函数:刷新 OLED 显示内容 ───────────────────────────────
void updateDisplay(char lastKey) {
display.clearDisplay();
// 标题栏
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("[ Keypad Monitor ]");
// 分隔线
display.drawLine(0, 10, SCREEN_WIDTH - 1, 10, SSD1306_WHITE);
// 最后按下的按键(大字体显示在中央)
display.setTextSize(4);
display.setTextColor(SSD1306_WHITE);
// 计算居中位置(每个字符宽约 24px,高约 32px)
int charX = (SCREEN_WIDTH - 24) / 2;
int charY = 16;
display.setCursor(charX, charY);
if (lastKey != NO_KEY) {
display.print(lastKey);
} else {
display.print("-");
}
// 底部:输入历史
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 56);
display.print("Log: ");
// 只显示最后 15 个字符
if (inputBuffer.length() > 15) {
display.print(inputBuffer.substring(inputBuffer.length() - 15));
} else {
display.print(inputBuffer);
}
display.display();
}
// ─── Setup ───────────────────────────────────────────────────
void setup() {
Serial.begin(115200);
// 初始化 I2C(指定 SDA/SCL 引脚)
Wire.begin(SDA_PIN, SCL_PIN);
// 初始化 OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println("SSD1306 初始化失败!请检查接线。");
while (true); // 停止运行
}
// 开机画面
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println(" ESP32-S3 Keypad");
display.setCursor(20, 35);
display.println(" Ready...");
display.display();
delay(1500);
// 显示初始界面
updateDisplay(NO_KEY);
Serial.println("系统就绪,等待按键输入...");
}
// ─── Loop ────────────────────────────────────────────────────
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
Serial.print("按键: ");
Serial.println(key);
// 特殊功能键处理
if (key == '*') {
// * 键:清空输入缓冲区
inputBuffer = "";
Serial.println("缓冲区已清空");
} else if (key == '#') {
// # 键:换行(模拟回车,这里仅记录)
inputBuffer += key;
Serial.println("回车");
} else {
inputBuffer += key;
}
// 超出最大字符数自动清空
if (inputBuffer.length() > MAX_CHARS) {
inputBuffer = String(key); // 只保留最新按键
}
// 刷新显示
updateDisplay(key);
}
}