本帖最后由 singz 于 2015-5-21 10:07 编辑
菜鸟刚入Arduino的坑,参照大神们的教程,试着用 1602液晶屏 和 DS3231时钟模块 搭建了个可调时钟。
1602和DS3231都用I2C总线连接,1602用转接板接I2C总线,闹铃是拆机得来的1只无源蜂鸣器。
有3个按键,Set键选择设置项目,Adj键调整数字,Reset键重启(中断闹钟)。
接线如模拟图所示(DS3231时钟模块是用555表示的,不要在意这些细节~):
运行效果见视频(没有找到合适的按键,用薄膜键盘凑合下,同样不要在意这些细节~):
可以用按键设置时钟的年、月、日、星期、时、分、秒,以及闹钟1的时、分、秒、开关,闹钟开关的状态在屏幕上用铃铛的符号表示。
DS3231时钟模块可以设定2个闹钟,并且可以自定义按 月、日、星期、时等周期循环,感觉用处不大就没有写入(其实是懒...)。
12/24小时切换也没写,原因同上 ^_^ (还有就是因为1602的屏幕上没有富余地方了,不显示温度的话应该可以)。
代码如下:
为了避免按键不灵敏,时间函数用的都是millis,仅在清屏和蜂鸣器上用了delay(按键消抖用的也是millis),没有用中断库,因为没学会 ...而且中断消抖好麻烦。
看起来好多行的样子,其实大多是无意义的空白,
菜鸟 VB省二级 考了6次,至今未及格,C语言完全是零基础,学习Arduino刚十几天,代码写得很渣,望诸位轻拍 ~~
- #include <Wire.h>
- #include <DS3231.h>
- #include <LiquidCrystal_I2C.h>
- DS3231 Clock;
- bool h12, PM, Century=false;
- byte year, month, date, DoW, hour, minute, second;
- bool ADy, A12h, Apm;
- byte A1Day, A1Hour, A1Minute, A1Second, A1Bits;
- uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4}; // 绘制闹钟标志
- LiquidCrystal_I2C lcd(0x27,16,2);
- const byte Set=2; // 按键
- const byte Adj=3;
- byte button[2] = {Set, Adj};
- void setup()
- {
- Wire.begin();
- lcd.init();
- lcd.backlight();
- lcd.createChar(0, bell); // 自定义闹钟标志
- pinMode(Set,INPUT); // 按键针脚
- pinMode(Adj,INPUT);
- pinMode(12,OUTPUT); // 蜂鸣器针脚
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 显示时间 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void Pritime()
- {
- int second,minute,hour,date,month,year,dow,temperature;
- second=Clock.getSecond();
- minute=Clock.getMinute();
- hour=Clock.getHour(h12, PM);
- date=Clock.getDate();
- month=Clock.getMonth(Century);
- year=Clock.getYear();
- dow=Clock.getDoW();
- temperature=Clock.getTemperature();
- lcd.setCursor(0, 0);
- lcd.print("20"); // 显示20世纪
- if (year>=10) // 显示年份
- {
- lcd.print(year,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(year,DEC);
- }
- lcd.print('-');
- lcd.setCursor(5, 0);
- if (month>=10) // 显示月份
- {
- lcd.print(month,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(month,DEC);
- }
- lcd.print('-');
- lcd.setCursor(8, 0);
- if (date>=10) // 显示日期
- {
- lcd.print(date,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(date,DEC);
- }
- lcd.setCursor(11, 0);
- switch (dow) // 显示星期
- {
- case 1: // 当dow等于1时,执行以下语句
- lcd.print("Mon");
- break;
- case 2: // 当dow等于2时,执行以下语句
- lcd.print("Tue");
- break;
- case 3:
- lcd.print("Wed");
- break;
- case 4:
- lcd.print("Thu");
- break;
- case 5:
- lcd.print("Fri");
- break;
- case 6:
- lcd.print("Sat");
- break;
- case 7:
- lcd.print("Sun");
- break;
- }
- lcd.setCursor(0, 1); //光标移至第2行
- if (hour>=10) // 显示小时
- {
- lcd.print(hour,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(hour,DEC);
- }
- lcd.print(':');
- lcd.setCursor(3, 1);
- if (minute>=10) // 显示分钟
- {
- lcd.print(minute,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(minute,DEC);
- }
- lcd.print(':');
- lcd.setCursor(6, 1);
- if (second>=10) // 显示秒钟
- {
- lcd.print(second,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(second,DEC);
- }
- lcd.setCursor(9, 1);
- if (Clock.checkAlarmEnabled(1)) // 显示闹钟标识
- {
- lcd.write(0x00);
- }
- else
- {
- lcd.print(' ');
- }
- lcd.setCursor(12, 1);
- lcd.print(temperature); // 显示温度
- lcd.write(0xdf); // 显示温度单位
- lcd.print("C");
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 时间冒号闪烁 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void Tictime()
- {
- lcd.setCursor(2, 1);
- lcd.print(' ');
- lcd.setCursor(5, 1);
- lcd.print(' ');
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 显示设置时间 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void PritimeSet(byte syear,byte smonth,byte sdate,byte sdow,byte shour,byte sminute,byte ssecond)
- {
- lcd.setCursor(0, 0);
- lcd.print("20"); // 显示20世纪
- if (syear>=10) // 显示年份
- {
- lcd.print(syear,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(syear,DEC);
- }
- lcd.print('-');
- lcd.setCursor(5, 0);
- if (smonth>=10) // 显示月份
- {
- lcd.print(smonth,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(smonth,DEC);
- }
- lcd.print('-');
- lcd.setCursor(8, 0);
- if (sdate>=10) // 显示日期
- {
- lcd.print(sdate,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(sdate,DEC);
- }
- lcd.setCursor(11, 0);
- switch (sdow) // 显示星期
- {
- case 1: // 当dow等于1时,执行一些语句
- lcd.print("Mon");
- break;
- case 2: // 当dow等于2时,执行一些语句
- lcd.print("Tue");
- break;
- case 3:
- lcd.print("Wed");
- break;
- case 4:
- lcd.print("Thu");
- break;
- case 5:
- lcd.print("Fri");
- break;
- case 6:
- lcd.print("Sat");
- break;
- case 7:
- lcd.print("Sun");
- break;
- }
- lcd.setCursor(0, 1); //光标移至第2行
- if (shour>=10) // 显示小时
- {
- lcd.print(shour,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(shour,DEC);
- }
- lcd.print(':');
- lcd.setCursor(3, 1);
- if (sminute>=10) // 显示分钟
- {
- lcd.print(sminute,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(sminute,DEC);
- }
- lcd.print(':');
- lcd.setCursor(6, 1);
- if (ssecond>=10) // 显示秒钟
- {
- lcd.print(ssecond,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(ssecond,DEC);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 时间设置位闪烁 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void TicSet(byte c,byte l)
- {
- lcd.setCursor(c,l);
- lcd.print(" ");
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 显示闹钟 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void PriA1()
- {
- lcd.setCursor(0, 0); // 光标移至第1行
- lcd.print("Alarm1 ");
- if (Clock.checkAlarmEnabled(1)) // 显示闹钟状态
- {
- lcd.print("On");
- }
- else
- {
- lcd.print("Off");
- }
- Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
- lcd.setCursor(0, 1); // 光标移至第2行
- if (A1Hour>=10) // 显示小时
- {
- lcd.print(A1Hour,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(A1Hour,DEC);
- }
- lcd.print(':');
- lcd.setCursor(3, 1);
- if (A1Minute>=10) //显示分钟
- {
- lcd.print(A1Minute,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(A1Minute,DEC);
- }
- lcd.print(':');
- lcd.setCursor(6, 1);
- if (A1Second>=10) // 显示秒钟
- {
- lcd.print(A1Second,DEC);
- }
- else
- {
- lcd.print("0");
- lcd.print(A1Second,DEC);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 按键检测 ~~~~~~~~~~~~~~~~~~~~~~~ */
- unsigned long LastP;
- boolean buttonPress(byte button)
- {
- if(digitalRead(button)==HIGH) // 检测按键是否按下
- {
- unsigned long NowP = millis();
- unsigned long buttonChange=NowP-LastP; // 与上次按键按下的时间进行对比
- if (buttonChange>500) //按键间隔是否大于500ms
- {
- LastP = millis(); // 记录按键按下的时间
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 时间设置 ~~~~~~~~~~~~~~~~~~~~~~~ */
- void SetTime()
- {
- bool h12, PM, Century=false;
- byte syear, smonth, sdate, sdow, shour, sminute, ssecond;
- if(buttonPress(Set))
- {
- lcd.clear();
- delay(200);
- Clock.getTime(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- bool SetY=true;
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入年份设置状态 ~~~~~~~~~~~~~~~~~~~~~~~ */
- while(SetY)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500) // 每500ms闪烁1次
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- lcd.setCursor(0,0);
- lcd.print(" ");
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置年份 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- syear=syear+1;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入月份设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetMon=true;
- while(SetMon)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- TicSet(5,0);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置月份 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- smonth=smonth+1;
- if(smonth>12)
- {
- smonth=1;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入日期设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetD=true;
- while(SetD)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- TicSet(8,0);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置日期 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- sdate=sdate+1;
- if(sdate>31)
- {
- sdate=1;
- }
- }
-
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入星期设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetW=true;
- while(SetW)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- lcd.setCursor(11,0);
- lcd.print(" ");
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置星期 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- sdow=sdow+1;
- if(sdow>7)
- {
- sdow=1;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入小时设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- long AdjP=0;
- bool SetH=true;
- while(SetH)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- TicSet(0,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置小时 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- AdjP=AdjP+1;
- shour=shour+1;
- if(shour>23)
- {
- shour=0;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入分钟设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetMin=true;
- while(SetMin)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- TicSet(3,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置分钟 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- AdjP=AdjP+1;
- sminute=sminute+1;
- if(sminute>59)
- {
- sminute=0;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入秒钟设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetS=true;
- while(SetS)
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500)
- {
- PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
- }
- else
- {
- TicSet(6,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置秒钟 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- AdjP=AdjP+1;
- ssecond=ssecond+1;
- if(ssecond>59)
- {
- ssecond=0;
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 保存并退出时间设置 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- Clock.setYear(syear);
- Clock.setMonth(smonth);
- Clock.setDate(sdate);
- Clock.setDoW(sdow);
- if (AdjP>0)
- {
- Clock.setHour(shour);
- Clock.setMinute(sminute);
- Clock.setSecond(ssecond);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入闹钟小时设置状态 ~~~~~~~~~~~~~~~~~~~~~~~ */
- lcd.clear();
- delay(200);
- bool SetA1H=true;
- while(SetA1H)
- {
- unsigned long RA1=millis()%1000;
- if(RA1<500) // 每500ms闪烁一次
- {
- PriA1();
- }
- else
- {
- TicSet(0,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置闹钟小时 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
- A1Hour=A1Hour+1;
- if(A1Hour<24)
- {
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm); // 设置闹钟每天响一次
- }
- else
- {
- A1Hour=0;
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入闹钟分钟设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetA1M=true;
- while(SetA1M)
- {
- unsigned long RA1=millis()%1000;
- if(RA1<500)
- {
- PriA1();
- }
- else
- {
- TicSet(3,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置闹钟分钟 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
- A1Minute=A1Minute+1;
- if(A1Minute<60)
- {
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
- }
- else
- {
- A1Minute=0;
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入闹钟秒钟设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetA1S=true;
- while(SetA1S)
- {
- unsigned long RA1=millis()%1000;
- if(RA1<500)
- {
- PriA1();
- }
- else
- {
- TicSet(6,1);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置闹钟秒钟 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
- A1Second=A1Second+1;
- if(A1Second<60)
- {
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
- }
- else
- {
- A1Second=0;
- Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 进入闹钟开关设置状态 ~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- bool SetA1R=true;
- while(SetA1R)
- {
- unsigned long RA1=millis()%1000;
- if(RA1<500)
- {
- lcd.setCursor(0, 0);
- PriA1();
- }
- else
- {
- lcd.setCursor(7, 0);
- lcd.print(" ");
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 设置闹钟开关 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Adj))
- {
- digitalWrite(Adj,LOW);
-
- if(Clock.checkAlarmEnabled(1))
- {
- Clock.turnOffAlarm(1);
- }
- else
- {
- Clock.turnOnAlarm(1);
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~ 退出闹钟设置 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- if(buttonPress(Set))
- {
- lcd.clear();
- delay(200);
- goto exit;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- exit: ;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~ 闹钟响 ~~~~~~~~~~~~~~~~~~~~~ */
- void Alarm()
- {
- if(Clock.checkIfAlarm(1))
- {
- long Rdt;
- do
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500) // 每500ms闪烁一次
- {
- Pritime();
- delay(100); // 延迟100ms
- tone(12,2000,50); // 在12号端口输出频率2000Hz,维持50ms
- delay(100);
- tone(12,2000,50);
- delay(100);
- tone(12,2000,50);
- delay(100);
- tone(12,2000,50);
- delay(100);
- }
- else
- {
- Tictime();
- }
- Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
- Clock.getTime(year, month, date, DoW, hour, minute, second);
- if (hour==0)
- {
- hour=24;
- }
- Rdt=hour*3600+minute*60+second-A1Hour*3600-A1Minute*60-A1Second;
- }
- while(Rdt>=0&&Rdt<300); // 闹钟响300s
- }
- else
- {
- digitalWrite(12,LOW);
- }
- }
- void loop()
- {
- unsigned long Rt=millis()%1000;
- if(Rt<500) // 每500ms闪烁一次
- {
- Pritime();
- }
- else
- {
- Tictime();
- }
- SetTime();
- Alarm();
- }
复制代码
最后附上 1602液晶屏 和 DS3231时钟模块 的库
|