我做了一个Arduino时钟,功能就像普通的电子表。有两个按键。
按键1可用来显示日期、秒,在显示日期三秒后,自动返回到时间显示。
按键2可进入调整小时、分钟、月、日状态,在这些状态下,用按键1进行调整数值。
用到的器件:
- Arduino UNO
- 两个按键开关
- TM1637芯片驱动的四位数码管
- 导线若干
我们通常使用1302等时钟芯片做Arduino时钟,其实用系统的millis()
函数就可以计时了,可以从这里下载Arduino时间库,有了这个库,写时钟程序很方便了。TM1637芯片的库文件可以从这里找到。
使用millis()
函数有一个限制,进入外部中断的时候,millis()
会停止计时️,所以不能用中断来处理事件。不过这也不算啥事,而且像Arduino UNO等只有两个中断引脚,要是有多个按键还不够用。
不使用中断要提高响应速度,需要减少delay函数的使用,在读取按键的值的时候delay了50毫秒,时钟闪烁采用轮询。previousMillis
保存前一个的millis()
,和当前millis()
比较,如下:
#define UPDATE_TIME_INTERVAL 500
unsigned long previousMillis = 0;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= UPDATE_TIME_INTERVAL) {
previousMillis = currentMillis;
// 更新时间显示
}
}
Timelib 库的使用很简单
本文用的的有:setTime,month,day,hour,minute,second这几个函数,setTime时间时,年份可以省略前两位,表示2000年之后多少年,本文的0就表示2000年,本时钟不是万年历,年份用任意一个闰年就行。
TM1637库用一个长度为4的数值表示,point表示是否显示分隔符“:”。让某一位不显示,可以给其赋值0x7f
,也可以用clear()
清空屏幕再给其它位赋值。
完整程序如下:
#include <TM1637.h>
#include <TimeLib.h>
#define CLK 12
#define DIO 13
#define SW1 6
#define SW2 7
#define UPDATE_TIME_INTERVAL 500
#define EMPTY 0x7f
#define AUTO_SWITCH_TO_TIME_INTERVAL 3000
int8_t timeDisp[] = {0, 0, 0, 0};
TM1637 tm1637(CLK, DIO);
unsigned long previousMillis = 0;
boolean point = true;
int8_t sw1oldValue = true;
int8_t sw2oldValue = true;
unsigned long enterDateMillis = 0;
int8_t sw1status = 0;
int8_t sw2status = 0;
typedef enum {
Status1Time,
Status1Date,
Status1Second,
Status1AdjustTime
} Switch1Status;
typedef enum {
Status2Normal,
Status2Hour,
Status2Minute,
Status2Month,
Status2Day
} Switch2Status;
void setup() {
// switch setup
pinMode(SW1, INPUT);
digitalWrite(SW1, HIGH);
pinMode(SW2, INPUT);
digitalWrite(SW2, HIGH);
// TM1637 setup
tm1637.set();
tm1637.init();
tm1637.display(timeDisp);
// TimeLib setup
setTime(8, 20, 15, 27, 11, 0); // hour min sec day month year
}
void loop() {
readSwitch();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= UPDATE_TIME_INTERVAL) {
previousMillis = currentMillis;
updateTime();
display();
}
}
void readSwitch() {
int8_t sw1value = digitalRead(SW1);
if (sw1value != sw1oldValue) {
if (sw1value == LOW) {
adjustAction1();
}
sw1oldValue = sw1value;
}
int8_t sw2value = digitalRead(SW2);
if (sw2value != sw2oldValue) {
if (sw2value == LOW) {
adjustAction2();
}
sw2oldValue = sw2value;
}
delay(50);
}
void adjustAction2() {
sw1status = Status1AdjustTime;
sw2status++;
if (sw2status >= 5) {
sw2status = 0;
sw1status = Status1Time;
}
}
void adjustAction1() {
if (sw1status != Status1AdjustTime) {
sw1status++;
if (sw1status >= 3) {
sw1status = 0;
}
if (sw1status == Status1Date) {
enterDateMillis = millis();
}
} else {
if (sw2status == Status2Hour) {
int8_t h = hour();
h++;
if (h == 24) {
h == 0;
}
setTime(h, minute(), second(), day(), month(), 0);
} else if (sw2status == Status2Minute) {
int8_t m = minute();
m++;
if (m == 60) {
m == 0;
}
setTime(hour(), m, second(), day(), month(), 0);
} else if (sw2status == Status2Month) {
int8_t m = month();
m++;
if (m == 13) {
m == 1;
}
setTime(hour(), minute(), second(), day(), m, 0);
} else if (sw2status == Status2Day) {
int8_t d = day();
d++;
int8_t days[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int8_t m = month();
if (d > days[m]) {
d == 1;
}
setTime(hour(), minute(), second(), d, month(), 0);
}
}
}
void updateTime() {
if (sw1status == Status1Time) {
timeDisp[0] = hour() < 10 ? EMPTY : hour() / 10;
timeDisp[1] = hour() % 10;
timeDisp[2] = minute() / 10;
timeDisp[3] = minute() % 10;
} else if (sw1status == Status1Second) {
timeDisp[0] = EMPTY;
timeDisp[1] = EMPTY;
timeDisp[2] = second() / 10;
timeDisp[3] = second() % 10;
} else if (sw1status == Status1Date) {
timeDisp[0] = month() < 10 ? EMPTY : month() / 10;
timeDisp[1] = month() / 10;
timeDisp[2] = day() / 10;
timeDisp[3] = day() % 10;
unsigned long ms = millis();
if (ms - enterDateMillis > 3000) {
sw1status = Status1Time;
}
} else if (sw1status == Status1AdjustTime) {
if (sw2status == Status2Hour) {
timeDisp[0] = hour() < 10 ? EMPTY : hour() / 10;
timeDisp[1] = hour() % 10;
timeDisp[2] = EMPTY;
timeDisp[3] = EMPTY;
} else if (sw2status == Status2Minute) {
timeDisp[0] = EMPTY;
timeDisp[1] = EMPTY;
timeDisp[2] = minute() / 10;
timeDisp[3] = minute() % 10;
} else if (sw2status == Status2Month) {
timeDisp[0] = month() < 10 ? EMPTY : month() / 10;
timeDisp[1] = month() % 10;
timeDisp[2] = EMPTY;
timeDisp[3] = EMPTY;
} else if (sw2status == Status2Day) {
timeDisp[0] = EMPTY;
timeDisp[1] = EMPTY;
timeDisp[2] = day() / 10;
timeDisp[3] = day() % 10;
}
}
}
void display() {
if (sw1status == Status1Time) {
point = !point;
tm1637.point(point);
tm1637.display(timeDisp);
} else if (sw1status == Status1Second) {
tm1637.point(false);
tm1637.display(timeDisp);
} else if (sw1status == Status1Date) {
tm1637.point(false);
tm1637.display(timeDisp);
} else if (sw1status == Status1AdjustTime) {
if (sw2status == Status2Hour || sw2status == Status2Minute) {
point = !point;
tm1637.point(point);
tm1637.display(timeDisp);
} else if (sw2status == Status2Month || sw2status == Status2Day) {
tm1637.point(false);
tm1637.display(timeDisp);
}
}
}
网友评论