/* Hello Wokwi! */
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define choose A0 //选择端口
#define add A1 //加
#define minus A2 //减
#define alarm A3 //报警
#define Tone 13 //蜂鸣器端口
#define Chrono 7
int secondc = 0, minutec = 0, hourc = 0;
bool con = false;
int second = 0, minute = 0, hour = 0, day = 25, month = 8, year = 2022; //当前时间
int chose = 0, alarm_choose = 0, ButtonDelay = 100, frequence = 2093;
int alarm_hour = 7, alarm_minute = 30, alarm_second = 0; //闹钟时间
bool alarm_switch = false, point_time_alarm = true;
void setup()
{
lcd.init();
lcd.backlight();
Serial.begin(9600);
for (int i = 2; i <= 13; i++)
pinMode(i, OUTPUT);
pinMode(7, INPUT);
digitalWrite(add, HIGH);
digitalWrite(minus, HIGH);
digitalWrite(choose, HIGH);
digitalWrite(alarm, HIGH);
digitalWrite(Chrono, HIGH);
noInterrupts();
// set timer1 interrupt at 1Hz
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624; // = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
interrupts();
}
void FormatDisplay(int col, int row, int num)
{
lcd.setCursor(col, row);
if (num < 10)
lcd.print("0");
lcd.print(num);
}
/** 计算年份 */
void Year()
{
if (year > 9999)
year %= 9999;
if (year == 0)
year = 9999;
lcd.setCursor(0, 0);
if (year < 1000)
lcd.print("0");
if (year < 100)
lcd.print("0");
if (year < 10)
lcd.print("0");
}
/** 计算月份 */
void Month()
{
if (month == 0)
{
month = 12;
year--;
}
else if (month == 13)
{
month = 1;
year++;
}
}
/** 根据年月计算当月天数 */
int Days(int year, int month)
{
int days = 0;
if (month != 2)
{
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31;
break;
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
}
}
else
{ //闰年
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
days = 29;
else
days = 28;
}
return days;
}
/** 计算当月天数 */
void Day()
{
int days = Days(year, month); //本月天数
int days_up; //上个月天数
if (month == 1)
days_up = Days(year - 1, 12);
else
days_up = Days(year, month - 1);
if (day == days + 1)
{
month++;
day = 1;
}
else if (day == 0)
{
month--;
day = days_up;
}
}
void time()
{
if (second == 60)
{
second = 0;
minute++;
}
else if (second == -1)
{
second = 59;
minute--;
}
if (minute == 60)
{
minute = 0;
hour++;
}
else if (minute == -1)
{
minute = 59;
hour--;
}
if (hour == 24)
{
hour = 0;
day++;
}
else if (hour == -1)
{
hour = 23;
day--;
}
}
void cal()
{
time();
Day();
Month();
Year();
}
void Display()
{
FormatDisplay(6, 1, second);
FormatDisplay(3, 1, minute);
FormatDisplay(0, 1, hour);
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(5, 1);
lcd.print(":");
FormatDisplay(8, 0, day);
FormatDisplay(5, 0, month);
lcd.setCursor(7, 0);
lcd.print('-');
lcd.setCursor(0, 0);
lcd.print(year);
lcd.setCursor(4, 0);
lcd.print('-');
}
/** 显示光标 */
void DisplayCursor(int rol, int row)
{
lcd.setCursor(rol, row);
lcd.cursor();
delay(100);
lcd.noCursor();
delay(100);
}
/** 通过按键设置时间 */
void Set_Time(int rol, int row, int &Time)
{
DisplayCursor(rol, row);
if (digitalRead(add) == LOW)
{
delay(ButtonDelay);
if (digitalRead(add) == LOW)
Time++;
cal();
Display();
}
if (digitalRead(minus) == LOW)
{
delay(ButtonDelay);
if (digitalRead(minus) == LOW)
Time--;
cal();
Display();
}
}
/** 按键选择 */
void Set_Clock()
{
if (digitalRead(choose) == LOW)
{
lcd.setCursor(9, 1);
lcd.print("SetTime");
while (1)
{
if (digitalRead(choose) == LOW)
{
delay(ButtonDelay);
if (digitalRead(choose) == LOW)
chose++;
}
// second = millis() / 1000;
cal();
Display();
if (chose == 1)
Set_Time(1, 1, hour); // SetHour
else if (chose == 2)
Set_Time(4, 1, minute); // SetMinute
else if (chose == 3)
Set_Time(7, 1, second); // SetSecond
else if (chose == 4)
Set_Time(9, 0, day); // SetDay
else if (chose == 5)
Set_Time(6, 0, month); // SetMonth
else if (chose == 6)
Set_Time(3, 0, year); // SetYear
else if (chose >= 7)
{
chose = 0;
lcd.setCursor(9, 1);
lcd.print(" ");
break;
}
}
}
}
/** 设置闹钟小时 */
void Set_Alarm_Hour()
{
DisplayCursor(1, 1);
if (digitalRead(add) == LOW)
{
delay(ButtonDelay);
if (digitalRead(add) == LOW)
{
alarm_hour++;
if (alarm_hour == 24)
alarm_hour = 0;
FormatDisplay(0, 1, alarm_hour);
}
}
if (digitalRead(minus) == LOW)
{
delay(ButtonDelay);
if (digitalRead(minus) == LOW)
{
alarm_hour--;
if (alarm_hour == -1)
alarm_hour = 23;
FormatDisplay(0, 1, alarm_hour);
}
}
}
/** 设置闹钟分钟 */
void Set_Alarm_Minute()
{
DisplayCursor(4, 1);
if (digitalRead(add) == LOW)
{
delay(ButtonDelay);
if (digitalRead(add) == LOW)
{
alarm_minute++;
if (alarm_minute == 60)
alarm_minute = 0;
FormatDisplay(3, 1, alarm_minute);
}
}
if (digitalRead(minus) == LOW)
{
delay(ButtonDelay);
if (digitalRead(minus) == LOW)
{
alarm_minute--;
if (alarm_minute == -1)
alarm_minute = 59;
FormatDisplay(3, 1, alarm_minute);
}
}
}
void Set_Alarm_switch()
{
DisplayCursor(12, 1);
if ((digitalRead(add) == LOW) || (digitalRead(minus) == LOW))
{
delay(ButtonDelay);
if ((digitalRead(add) == LOW) || (digitalRead(minus) == LOW))
{
alarm_switch = !alarm_switch;
lcd.setCursor(10, 1);
if (alarm_switch == true)
lcd.print(" ON");
else
lcd.print("OFF");
}
}
}
void Set_Alarm_point()
{
DisplayCursor(15, 0);
if ((digitalRead(add) == LOW) || (digitalRead(minus) == LOW))
{
delay(ButtonDelay);
if ((digitalRead(add) == LOW) || (digitalRead(minus) == LOW))
{
point_time_alarm = !point_time_alarm;
lcd.setCursor(13, 0);
if (point_time_alarm == true)
lcd.print(" ON");
else
lcd.print("OFF");
}
}
}
/** 进入报警设置 */
void Set_Alarm()
{
if (digitalRead(alarm) == LOW)
{
alarm_hour = hour;
alarm_minute = minute;
// alarm_choose = 1;
lcd.setCursor(0, 0);
lcd.print("Set alarm P");
if (point_time_alarm == true)
lcd.print(" ON");
else
lcd.print(" OFF");
lcd.setCursor(6, 1);
lcd.print("00"); //闹钟秒数
lcd.setCursor(10, 1);
if (alarm_switch == true)
lcd.print(" ON");
else
lcd.print("OFF");
while (1)
{
cal();
if (digitalRead(choose) == LOW)
{
delay(ButtonDelay);
if (digitalRead(choose) == LOW)
alarm_choose++;
}
if (alarm_choose == 1)
Set_Alarm_Hour();
else if (alarm_choose == 2)
Set_Alarm_Minute();
else if (alarm_choose == 3)
Set_Alarm_switch();
else if (alarm_choose == 4)
Set_Alarm_point();
else if (alarm_choose >= 5)
{
alarm_choose = 0;
lcd.setCursor(10, 0);
lcd.print(" ");
lcd.setCursor(10, 1);
lcd.print(" ");
break;
}
}
}
}
/** 正点蜂鸣 */
void Point_Time_Alarm()
{
if (minute == 0 && second == 0 && point_time_alarm == true)
{
tone(Tone, frequence);
delay(500);
noTone(Tone);
}
}
/** 闹钟 指定时间蜂鸣 */
void Clock_Alarm()
{
if (hour == alarm_hour && minute == alarm_minute && second == alarm_second && alarm_switch == true)
{
tone(Tone, frequence);
delay(5000);
noTone(Tone);
}
}
ISR(TIMER1_COMPA_vect)
{
second++;
Serial.println(second);
if (con)
secondc++;
}
void Chronograph()
{
if (digitalRead(Chrono) == LOW)
{
delay(ButtonDelay);
if (digitalRead(Chrono) == LOW)
{
lcd.setCursor(0, 0);
lcd.print("Chronograph");
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(5, 1);
lcd.print(":");
while (1)
{
cal();
if (digitalRead(Chrono) == LOW) //退出
{
delay(ButtonDelay);
if (digitalRead(Chrono) == LOW)
{
lcd.setCursor(10, 0);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print(" ");
break;
}
}
else if (digitalRead(add) == LOW) //暂停、继续
{
delay(ButtonDelay);
if (digitalRead(add) == LOW)
{
con = !con;
}
}
else if (digitalRead(minus) == LOW) //清零
{
delay(ButtonDelay);
if (digitalRead(minus) == LOW)
{
hourc = 0;
minutec = 0;
secondc = 0;
}
}
if (con == true)
{
if (secondc == 60)
{
secondc = 0;
minutec++;
}
if (minutec == 60)
{
minutec = 0;
hourc++;
}
if (hourc == 24)
{
hourc = 0;
minutec = 0;
secondc = 0;
}
}
FormatDisplay(6, 1, secondc);
FormatDisplay(3, 1, minutec);
FormatDisplay(0, 1, hourc);
if (con == false)
{
lcd.setCursor(10, 1);
lcd.print("OFF");
}
else
{
lcd.setCursor(10, 1);
lcd.print(" ON");
}
}
}
}
}
void loop()
{
// second = millis() / 1000;
cal();
Display();
Set_Clock(); //设置时间
Set_Alarm(); //设置闹钟
Point_Time_Alarm(); //正点蜂鸣
Clock_Alarm(); //闹钟时间蜂鸣
Chronograph();
}