/*--------------------------------------------------------------------------1--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------本程序所引用库--------------------------------------------------------------------*/
#include <LiquidCrystal.h> // 引入LiquidCrystal库,用于控制液晶显示屏
#include <Keypad.h> // 引入Keypad库,用于处理矩阵键盘输入
#include <MsTimer2.h> // 引入MsTimer2库,用于定时器功能,每秒触发一次回调函数
/*--------------------------------------------------------------------------2--------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------声明定义-----------------------------------------------------------------------*/
/*****************************< 常量声明 >*****************************/
#define Membrane_Debounce_Time 200 // 薄膜按键消抖时间(未使用)
const byte KEYPAD_ROWS = 4; // 键盘的行数
const byte KEYPAD_COLS = 4; // 键盘的列数
/*****************************< 引脚定义 >*****************************/
const int LCD_RS = 12; // LCD RS引脚
const int LCD_EN = 11; // LCD EN引脚
const int LCD_D4 = 10; // LCD D4引脚
const int LCD_D5 = 9; // LCD D5引脚
const int LCD_D6 = 8; // LCD D6引脚
const int LCD_D7 = 7; // LCD D7引脚
const byte rowPins[KEYPAD_ROWS] = { 5, 4, 3, 2 }; // 键盘行引脚连接到Arduino引脚
const byte colPins[KEYPAD_COLS] = { A3, A2, A1, A0 }; // 键盘列引脚连接到Arduino模拟引脚
/******************************变量声明******************************/
// 为键盘上的每个位置赋值
const char Key_Map[KEYPAD_ROWS][KEYPAD_COLS] = {
{ '1', '2', '3', '+' }, // 第一行的按键
{ '4', '5', '6', '-' }, // 第二行的按键
{ '7', '8', '9', '*' }, // 第三行的按键
{ '.', '0', '=', '/' } // 第四行的按键
};
// 时间变量
int hours = 0; // 小时变量
int minutes = 0; // 分钟变量
int seconds = 0; // 秒钟变量
bool settingTime = false; // 是否正在设置时间的标志
bool Set_FG = false; // 设置完成标志
/*****************************< 对象声明 >*****************************/
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // 创建LiquidCrystal对象并初始化
Keypad keypad = Keypad(makeKeymap(Key_Map), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS); // 创建Keypad对象并初始化
/*--------------------------------------------------------------------------3--------------------------------------------------------------------------*/
/*-------------------------------------------------------------------setup()程序初始化------------------------------------------------------------------*/
void setup() {
/*******************************< LCD初始化 >*******************************/
lcd.begin(16, 2); // 初始化LCD显示屏,设置显示屏为16列2行
lcd.clear(); // 清除显示屏
display_Welcome("HuangZhongYang", "201806140205"); // 显示欢迎信息
/*******************************< 设置时间 >*******************************/
while (!Set_FG) { // 在时间未设置完成之前一直循环
char key = keypad.getKey(); // 获取键盘按键
if (key) { // 如果按键被按下
if (settingTime) { // 如果正在设置时间
setTime(key); // 调用setTime函数处理按键输入
} else {
if (key == '+') { // 如果按下'+'键,开始设置时间
settingTime = true; // 设置标志为真
lcd.clear(); // 清除显示屏
lcd.print("Set Time:"); // 显示“Set Time:”
lcd.setCursor(0, 1); // 设置光标到第二行起始位置
lcd.print("HH:MM:SS"); // 显示时间格式
}
}
}
}
/******************************< 设置定时器 >******************************/
MsTimer2::set(1000, updateTime); // 设置定时器,每秒调用一次updateTime函数
MsTimer2::start(); // 启动定时器
}
/*--------------------------------------------------------------------------4--------------------------------------------------------------------------*/
/*-------------------------------------------------------------------loop()基础循环体-------------------------------------------------------------------*/
void loop() {
// 主循环为空,显示操作在定时器中完成
}
/*--------------------------------------------------------------------------5--------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------函数定义-----------------------------------------------------------------------*/
/*****************************************************************************************************
* 函数:setTime(char key)
* 作用:从键盘输入设置时间,并在LCD上显示
* 参数:
* - key: 键盘输入的字符
* 返回值:无
*****************************************************************************************************/
void setTime(char key) {
static int pos = 0; // 记录输入位置
static int pos2 = 0; // 实际在LCD上的位置
static int newHours = 0; // 临时存储新的小时
static int newMinutes = 0; // 临时存储新的分钟
static int newSeconds = 0; // 临时存储新的秒钟
if (pos < 2) pos2 = pos; // 根据输入位置计算实际显示位置
else if (pos < 4) pos2 = pos + 1;
else if (pos < 6) pos2 = pos + 2;
lcd.setCursor(pos2, 1); // 设置光标到指定位置
lcd.print(key); // 显示输入的字符
if (key >= '0' && key <= '9') { // 如果输入的是数字字符
if (pos < 2) {
newHours = newHours * 10 + (key - '0'); // 累积小时
} else if (pos < 4) {
newMinutes = newMinutes * 10 + (key - '0'); // 累积分钟
} else if (pos < 6) {
newSeconds = newSeconds * 10 + (key - '0'); // 累积秒钟
}
if (pos < 6) pos++; // 增加输入位置
}
if (pos == 6) { // 当所有时间输入完成
if (newHours >= 24) newHours = 0; // 如果小时大于等于24,重置为0
if (newMinutes >= 60) newMinutes = 0; // 如果分钟大于等于60,重置为0
if (newSeconds >= 60) newSeconds = 0; // 如果秒钟大于等于60,重置为0
hours = newHours; // 设置全局小时变量
minutes = newMinutes; // 设置全局分钟变量
seconds = newSeconds; // 设置全局秒钟变量
settingTime = false; // 重置设置标志
Set_FG = true; // 设置完成标志为真
pos = 0; // 重置输入位置
newHours = 0; // 重置临时小时变量
newMinutes = 0; // 重置临时分钟变量
newSeconds = 0; // 重置临时秒钟变量
displayTime(); // 显示当前时间
}
}
/*****************************************************************************************************
* 函数:updateTime()
* 作用:更新时间,处理秒钟、分钟和小时的增加与重置,并在LCD上显示当前时间
* 参数:无
* 返回值:无
*****************************************************************************************************/
void updateTime() {
if (!settingTime) { // 如果没有在设置时间
seconds++; // 增加秒钟
if (seconds == 60) { // 如果秒钟等于60
seconds = 0; // 重置秒钟
minutes++; // 增加分钟
if (minutes == 60) { // 如果分钟等于60
minutes = 0; // 重置分钟
hours++; // 增加小时
if (hours == 24) { // 如果小时等于24
hours = 0; // 重置小时
}
}
}
displayTime(); // 显示当前时间
}
}
/*****************************************************************************************************
* 函数:display_Welcome(const char* name, const char* id)
* 作用:在 LCD 显示屏上居中名字和 ID
* 参数:
* name - 指向名字字符串的指针
* id - 指向 ID 字符串的指针
* 返回值:无
*****************************************************************************************************/
void display_Welcome(const char* name, const char* id) {
lcd.clear(); // 清除显示屏
int nameLen = strlen(name); // 获取名字长度
int idLen = strlen(id); // 获取ID长度
int nameStart = (16 - nameLen) / 2; // 计算名字起始位置
int idStart = (16 - idLen) / 2; // 计算ID起始位置
lcd.setCursor(nameStart, 0); // 设置光标到名字起始位置
lcd.print(name); // 显示名字
lcd.setCursor(idStart, 1); // 设置光标到ID起始位置
lcd.print(id); // 显示ID
}
/*****************************************************************************************************
* 函数:displayTime()
* 作用:在 LCD 显示屏上显示当前时间
* 参数:无
* 返回值:无
*****************************************************************************************************/
void displayTime() {
lcd.clear(); // 清除显示屏
lcd.setCursor(0, 0); // 设置光标到第一行起始位置
lcd.print("Time:"); // 显示"Time:"
lcd.setCursor(0, 1); // 设置光标到第二行起始位置
if (hours < 10) lcd.print("0"); // 如果小时小于10,显示前导零
lcd.print(hours); // 显示小时
lcd.print(":"); // 显示冒号
if (minutes < 10) lcd.print("0"); // 如果分钟小于10,显示前导零
lcd.print(minutes); // 显示分钟
lcd.print(":"); // 显示冒号
if (seconds < 10) lcd.print("0"); // 如果秒钟小于10,显示前导零
lcd.print(seconds); // 显示秒钟
}