本文中所使用库文件
- TM1637库:https://github.com/bremme/arduino-tm1637
- DS3231库:https://github.com/adafruit/RTClib
- LiquidCrystal-I2C库:https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
- 一个很简单的TM1637库:https://github.com/AKJ7/TM1637
参考
DS3231
模块参数:
- 尺寸:38mm(长)*22mm(宽)*14mm(高)
- 重量:8g
- 工作电压:3.3–5.5V
- 时钟芯片:高精度时钟芯片DS3231
- 时钟精度:0-40℃范围内,精度2ppm,年误差约1分钟
- 带2个日历闹钟
- 可编程方波输出
- 实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿
- 芯片内部自带温度传感器,精度为±3℃
- 存储芯片:AT24C32(存储容量32K)
- IIC总线接口,最高传输速度400KHz(工作电压为5V时)
- 可级联其它IIC设备,24C32地址可通过短路A0/A1/A2修改,默认地址为0x57
- 带电池CR2032,保证系统断电后,时钟任然正常走动
接线说明(以Arduino uno r3为例):
- SCL→A5
- SDA→A4
- VCC→5V
- GND→GND
库文件函数
完整代码
准备
1. 修改SevenSegmentExtended
库文件
在bremme/arduino-tm1637的SevenSegmentExtended
库中添加了一个功能
void SevenSegmentExtended::changeColonStatus(uint8_t hour,bool status) {
uint8_t cmd[2];
bool colonWasOn = getColonOn();
setColonOn(status);
cmd[0] = TM1637_COM_SET_ADR | 1;
cmd[1]= encode(int16_t(hour % 10));
cmd[1]|=(_colonOn)?TM1637_COLON_BIT:0;
command(cmd, 2);
// setColonOn(colonWasOn);
};
此函数的功能是为了设置colon的显示状态。此函数应该继续改进,可参考https://github.com/AKJ7/TM1637库中相应功能
代码
#include "Wire.h"
#include "LiquidCrystal_I2C.h" //lcd显示库
#include "RTClib.h" //DS3231产生时间并保持时钟与世界时间同步。
#include "SevenSegmentTM1637.h" //数码管的库
#include "SevenSegmentExtended.h"
#define INTERVAL_TIME 1000000;
#define BAUD 115200 //串口波特率
#define BOARD_LED_PIN 13 //板载led接口
#define TM_CLK 4
#define TM_DIO 5
LiquidCrystal_I2C lcd(0x3f, 16, 2); //我用的1602显示屏I2C地址是0x3f
RTC_DS3231 rtc; //默认地址为0x57
SevenSegmentExtended tm1637(TM_CLK, TM_DIO);
unsigned long prevTime = 0;
unsigned long intervalTime = 1000000; //1000ms
char daysOfTheWeek[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //二维数组,
//int8_t timeDisplay[4] = {0, 0, 0, 0};
bool clockPoint = true;
unsigned char secondOfRtc;
unsigned char minuteOfRtc;
unsigned char hourOfRtc;
unsigned char dayOfRtc;
unsigned char monthOfRtc;
unsigned int yearOfRtc;
unsigned char weekOfRtc;
float temperatureOfRtc = 0;
unsigned long updateDayInterval = 0;
unsigned char updateMinuteInterval = 0;
String dateStr;
String temperatureStr;
void alertBlink(unsigned int t, unsigned long deltms); //让13口led闪烁,
void (*resetFunc)(void) = 0; //控制主控板自动重启
void setup()
{
//#ifndef ESP8266
// while (!Serial)
; //for Leonardo/Micro/Zero
// #endif
Serial.begin(BAUD);
// delay(3000);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)) + TimeSpan(0, 0, 0, 10));
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)) + TimeSpan(0, 0, 0, 10)); //设置rtc芯片的初始时间
}
pinMode(BOARD_LED_PIN, OUTPUT);
lcd.begin();
lcd.backlight();
lcd.print("Hello!");
updateDateTime();
lcdDisplay();
tm1637.begin();
tm1637.setBacklight(100);
tm1637.printTime(hourOfRtc, minuteOfRtc, true);
prevTime = micros();
}
void loop()
{
//这里要注意此等式的写法不能写成micros()>= prevTime + intervalTime
// 具体分析参考:https://blog.csdn.net/acktomas/article/details/88365305
if (micros() - prevTime >= intervalTime) {
updateDayInterval++;
updateMinuteInterval++;
prevTime = micros();
updateDateTime();
if (updateDayInterval > 86400) { //一天86400秒
updateDayInterval = 1;
lcdDisplay();
}
if (updateMinuteInterval > 60) {
updateMinuteInterval = 1;
tm1637.printTime(hourOfRtc, minuteOfRtc, false);
}
clockPoint = !clockPoint;
tm1637.changeColonStatus(hourOfRtc, clockPoint);
// timeDisplay();
// tm1637.printTime(hourOfRtc, minuteOfRtc, false);
Serial.println(clockPoint);
}
}
/**
功能:让板载led以一定的时间间隔闪烁
t:闪烁次数,当t=0时,不闪烁,一直亮。
deltms:闪烁间隔的毫秒数。
*/
void alertBlink(unsigned int t, unsigned long deltms)
{
if (t == 0)
digitalWrite(BOARD_LED_PIN, HIGH);
for (int i = 0; i < t; i++)
{
digitalWrite(BOARD_LED_PIN, HIGH);
delay(deltms);
digitalWrite(BOARD_LED_PIN, LOW);
delay(deltms);
}
}
void updateDateTime() {
DateTime now = rtc.now();
yearOfRtc = now.year();
monthOfRtc = now.month();
dayOfRtc = now.day();
hourOfRtc = now.hour();
minuteOfRtc = now.minute();
secondOfRtc = now.second();
temperatureOfRtc = rtc.getTemperature();
weekOfRtc = now.dayOfTheWeek();
}
String getDateString() {
return String("") + yearOfRtc + "-" + monthOfRtc + "-" + dayOfRtc + " " + daysOfTheWeek[weekOfRtc];
}
String getTemperatureString() {
return String("Temp:") + temperatureOfRtc + " C";
}
void timeDisplay() {
tm1637.changeColonStatus(hourOfRtc, clockPoint);
tm1637.printTime(hourOfRtc, minuteOfRtc, false);
}
void lcdDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(getDateString());
lcd.setCursor(0, 1);
lcd.print(getTemperatureString());
}