#include <Wire.h> // I2C通信库
#include <LiquidCrystal_I2C.h> // I2C LCD库
#include <Keypad.h> // 矩阵键盘库
// 硬件配置
LiquidCrystal_I2C lcd(0x27, 16, 2); // 初始化LCD,I2C地址0x27,16列2行
// 键盘配置(4x4矩阵)
const byte ROWS = 4, COLS = 4; // 定义键盘4行4列
// 键盘映射表
char keys[ROWS][COLS] = {
{'1','2','3','A'}, // 第一行按键
{'4','5','6','B'}, // 第二行按键
{'7','8','9','C'}, // 第三行按键
{'*','0','#','D'} // 第四行按键
};
// 行引脚连接
byte rowPins[ROWS] = {2,3,4,5};
// 列引脚连接
byte colPins[COLS] = {6,7,8,9};
// 创建键盘对象
Keypad keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// 输入缓冲区配置
#define INPUT_BUFFER_SIZE 32 // 输入缓冲区大小
char inputBuffer[INPUT_BUFFER_SIZE]; // 输入缓冲区
byte bufferIndex = 0; // 当前输入位置索引
// 显示优化
char prevDisplayLine[17] = {0}; // 用于比较前一次显示内容
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率9600
lcd.init(); // 初始化LCD
lcd.backlight(); // 打开背光
lcd.print("Input System"); // 显示启动信息
delay(1000); // 显示1秒
lcd.clear(); // 清屏
}
void loop() {
handleInput(); // 处理键盘输入
refreshDisplay(); // 刷新LCD显示
processDataTransfer(); // 处理数据发送
}
/* 输入处理函数 */
void handleInput() {
char key = keypad.getKey(); // 获取按键
if (!key) return; // 无按键按下则返回
switch(key) {
case 'A': // 确认发送
if (bufferIndex > 0) { // 缓冲区有内容才发送
sendSerialData(); // 发送数据
clearInputBuffer(); // 清空缓冲区
}
break;
case 'B': // 清除输入
clearInputBuffer(); // 清空输入
break;
case '#': // 系统重置
memset(inputBuffer, 0, INPUT_BUFFER_SIZE); // 清空缓冲区
bufferIndex = 0; // 重置索引
lcd.clear(); // 清屏
break;
default: // 字符输入
if (bufferIndex < INPUT_BUFFER_SIZE-1) { // 防止缓冲区溢出
inputBuffer[bufferIndex++] = key; // 存入缓冲区并移动索引
updateCursorDisplay(); // 更新光标位置
}
}
}
/* 显示刷新函数(优化:仅更新变化内容) */
void refreshDisplay() {
char displayLine[17]; // 临时存储当前显示内容
// 格式化显示内容:"Input:"后跟输入内容,左对齐占12位
snprintf(displayLine, 17, "Input:%-12s", inputBuffer);
// 比较当前显示内容与前次内容
if (strcmp(displayLine, prevDisplayLine) != 0) {
lcd.setCursor(0,0); // 定位到第一行开头
lcd.print(displayLine); // 更新显示
strncpy(prevDisplayLine, displayLine, 16); // 保存当前显示内容
}
}
// 清空输入缓冲区
void clearInputBuffer() {
memset(inputBuffer, 0, INPUT_BUFFER_SIZE); // 清空缓冲区
bufferIndex = 0; // 重置索引
lcd.setCursor(6,0); // 定位到输入区域开始
lcd.print(" "); // 清除显示区域(12空格)
}
// 更新光标位置
void updateCursorDisplay() {
lcd.setCursor(6 + bufferIndex, 0); // 光标定位在输入区域当前位置
}
// 发送串口数据
void sendSerialData() {
Serial.print("<INPUT>"); // 发送起始标记
Serial.println(inputBuffer); // 发送缓冲区内容并换行
}
// 自动发送处理(防抖500ms)
void processDataTransfer() {
static unsigned long lastSend = 0; // 上次发送时间
// 如果缓冲区有内容且超过500ms未发送
if (bufferIndex > 0 && millis() - lastSend > 500) {
sendSerialData(); // 发送数据
lastSend = millis(); // 更新最后发送时间
}
}