Arduino:利用DS3231RTC芯片、TM1637數碼管、LCD1602 製作時鐘

本文中所使用庫文件

參考

  1. Arduino使用TM1637四位數碼管

DS3231

在這裏插入圖片描述

模塊參數:

  1. 尺寸:38mm(長)*22mm(寬)*14mm(高)
  2. 重量:8g
  3. 工作電壓:3.3–5.5V
  4. 時鐘芯片:高精度時鐘芯片DS3231
  5. 時鐘精度:0-40℃範圍內,精度2ppm,年誤差約1分鐘
  6. 帶2個日曆鬧鐘
  7. 可編程方波輸出
  8. 實時時鐘產生秒、分、時、星期、日期、月和年計時,並提供有效期到2100年的閏年補償
  9. 芯片內部自帶溫度傳感器,精度爲±3℃
  10. 存儲芯片:AT24C32(存儲容量32K)
  11. IIC總線接口,最高傳輸速度400KHz(工作電壓爲5V時)
  12. 可級聯其它IIC設備,24C32地址可通過短路A0/A1/A2修改,默認地址爲0x57
  13. 帶電池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());
}

說明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章