<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用實時時鐘IC DS1307制作精確時鐘的方法

科技觀察員 ? 來源:allaboutcircuits ? 作者: Jens Christoffersen ? 2022-04-26 17:23 ? 次閱讀

如何使用實時時鐘 IC DS1307 制作準確的時鐘。時間將顯示在液晶顯示屏上。

要求

運行 Arduino 1.6.5 的計算機

阿杜諾

跳線

面包板

零件清單中的零件

您可以用 ATMEL 的另一個 IC 替換 Arduino,但要確保它具有足夠數量的輸入和輸出引腳以及 I 2 C 功能。我正在使用 ATMega168A-PU。如果你這樣做,你將需要一個程序員。我有 AVR MKII ISP 編程器。

建議讀者熟悉面包板,在Arduino環境下編程,對C編程語言有一定的了解。下面的兩個程序不需要額外的解釋。

介紹

微控制器如何跟蹤時間和日期?普通的微控制器有一個定時器功能,上電時從0(零)開始,然后開始計數。在 Arduino 世界中,我們可以使用 millis() 函數來重置自上電以來經過的毫秒數。當您斷開并重新連接電源時,它會重新開始。這在時鐘和日期方面不太方便。

這就是實時時鐘或 RTC 芯片派上用場的地方。該 IC 帶有 3v 紐扣電池或另一個 3v 電源,可跟蹤時間和日期。時鐘/日歷提供秒、分鐘、小時、星期、日期、月份和年份信息。IC 以 30/31 天和閏年校正月份。通過 I 2 C 總線進行通信。I 2 C 總線將不在這里討論。

如果主電路的 Vcc 低于 Vbat,RTC 會自動切換到低功耗電池備份模式。備用電池通常是連接到 PIN 3 和 GND 的 3v 紐扣電池。通過這種方式,IC 仍會跟蹤時間和日期,當主電路通電時,微控制器會獲取當前時間和日期。

在這個項目中,我們使用的是DS1307。在該 IC 上,引腳 7 是 SQW/OUT 引腳。您可以使用此引腳來閃爍 LED,或為微控制器計時。我們將兩者都做。數據表中的下圖有助于我們了解 SQW/OUT。

poYBAGJnuhWAa37pAADPv5X4qgg177.png

此表可幫助您了解頻率:

頻率BIT7 & BIT6 & BIT5BIT4第 3 位和第 2 位BIT1位0

1赫茲 01 0 0 0

4.096Hz 01 0 0 1

8.192Hz 01 0 1 0

32.768Hz 01 0 1 1

如果將 LED 和電阻連接到 PIN 7,并希望它以 1Hz 頻率閃爍,則將 0b00010000 寫入控制寄存器內存地址。如果你想要 4.096 Hz,你會寫 0b000100001?,F在您需要一臺示波器來查看脈沖,因為 LED 閃爍得如此之快,以至于看起來它一直亮著。我們使用的是 1Hz。

硬件

這是我們想要的框圖。

pYYBAGJnuhWAIxJAAAARmOAmzPM868.png

我們想要:

ISP(在系統編程中)對微控制器進行編程

按鈕設置時間和日期

微控制器通過 I 2 C與 RTC 通信

在 LCD 上顯示時間和日期

示意圖:

poYBAGJnuhaAczFLAAB8-qcwuWQ974.png

點擊圖片為全尺寸。

零件清單

這是 Eagle 的截圖:

pYYBAGJnuheALk2jAAGwMBlGMuc696.png

軟件

我們將在本指南中使用兩種不同的草圖:一種將時間和日期寫入 RTC,另一種從 RTC 讀取時間和日期。我已經這樣做了,因此您將對正在發生的事情有更好的了解。我們將為這兩個程序使用與上述相同的電路。

首先,我們將時間和日期寫入 RTC,這就像在手表上設置時間一樣。

我們使用兩個開關。一種是增加小時、分鐘、日期、月、年和星期幾,另一種是在它們之間進行選擇。該應用程序不會從任何關鍵傳感器讀取值,因此我們使用中斷來檢查是否按下了開關并處理開關彈跳。有關開關彈跳的更多信息, 請閱讀此。

以下代碼將設置值并將它們寫入 RTC:

// Include header files
#include 
#include 

// LCD pin definitions
#define RS 9
#define E 10
#define D4 8
#define D5 7
#define D6 6
#define D7 5

LiquidCrystal lcd(RS, E, D4, D5, D6, D7);

// Interrupt 0 is hardware pin 4 (digital pin 2)
int btnSet = 0;

// Interrupt 1 is hardware pin 5 (digital pin 3)
int btnSel = 1;

// Interrupt state
int togBtnSet = false;
int togBtnSel = false;

// Time and date variables
int tmpHour = 0;
int tmpMinute = 0;
int tmpDate = 0;
int tmpMonth = 0;
int tmpYear = 0;
int tmpDay = 0;
int tmpSecond = 0;

int counterVal = 0;

// Variable to keep track of where we are in the "menu"
int myMenu[6]; // 0=Hour, 1=Minutes, 2=date, 3=MOnth, 4=Year, 5=DOW
int menuCounter = 0;

// A array of the weekday
char* days[] = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" };

void setup() {
  // Interrupt declaration, execute increaseValue/nextItem function
  // when btnXXX is RISING
  attachInterrupt(btnSet, increaseValue, RISING);
  attachInterrupt(btnSel, nextItem, RISING);
  Wire.begin();
  lcd.begin(16,2);
  showWelcome();
}

// Interrupt function
void increaseValue()
{
  // Variables
  static unsigned long lastInterruptTime = 0;
  // Making a timestamp
  unsigned long interruptTime = millis();

  // If timestamp - lastInterruptTime is greater than 200
  if (interruptTime - lastInterruptTime > 200)
  {
    // Toggle the variable
    togBtnSet = !togBtnSet;
    // Increase the counterVal by 1
    counterVal++;
  }
  // Setting lastInterruptTime equal to the timestamp
  // so we know we moved on
  lastInterruptTime = interruptTime; 
}

// Next menuItem Interrupt function
void nextItem()
{
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = millis();

  if (interruptTime - lastInterruptTime > 200)
  {
    togBtnSel = !togBtnSel;
    // Increase the menu counter so we move to next item
    menuCounter++;   
    // Placing the counterVal in the menucounters array position
    myMenu[menuCounter] = counterVal;
    // Reset counterVal, now we start at 0 on the next menuItem
    counterVal = 0;
  }
  lastInterruptTime = interruptTime;
}

// Function that convert decimal numbers to binary
byte decToBCD(byte val)
{
  return ((val/10*16) + (val));
}

// Short welcome message, now we know everything is OK
void showWelcome()
{
  lcd.setCursor(2,0);
  lcd.print("Hello world.");
  lcd.setCursor(3,1);
  lcd.print("I'm alive.");
  delay(500);
  lcd.clear();
}

// Funcion to set the hour
void setHour()
{
  lcd.setCursor(0,0);
  lcd.print("Set hour.       "); 
 // Checks if interrupt has occured = button pressed
 if (togBtnSet)
 {
  // Update array value with counterVal
  myMenu[menuCounter] = counterVal;
  lcd.setCursor(7,1);
  // Print the new value
  lcd.print(myMenu[menuCounter]); lcd.print("  ");
 }
 else
 {
  // Update array value with counterVal
  myMenu[menuCounter] = counterVal;
  lcd.setCursor(7,1);
  // Print the new value
  lcd.print(myMenu[menuCounter]); lcd.print("  ");
 }
}

// Function to set minutes
void setMinute()
{
  lcd.setCursor(0,0);
  lcd.print("Set minute.     ");
  if (togBtnSet)
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
  else
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
}

// Function to set date
void setDate()
{
  lcd.setCursor(0,0);
  lcd.print("Set date.       ");
  if (togBtnSet)
  {
    myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
  else
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }  
}

// Function to set month
void setMonth()
{
  lcd.setCursor(0,0);
  lcd.print("Set month.      ");
  if (togBtnSet)
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
  else
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }  
}

// Function to set year
void setYear()
{
  lcd.setCursor(0,0);
  lcd.print("Set year.       ");
  if (togBtnSet)
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
  else
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }  
}

// Function to set the day of week
void setDOW()
{
  lcd.setCursor(0,0);
  lcd.print("Set day (1=mon).");
  if (togBtnSet)
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }
  else
  {
  myMenu[menuCounter] = counterVal;
    lcd.setCursor(7,1);
    lcd.print(myMenu[menuCounter]); lcd.print("  ");
  }  
}

// Write the data to the RTC
void writeRTC()
{
  Wire.beginTransmission(0x68);
  Wire.write(0); // Start address
  Wire.write(0x00); // seconds
  Wire.write(decToBCD(myMenu[1])); // convert tmpMinutes to BCD and write them
  Wire.write(decToBCD(myMenu[0]));  // convert tmpHour to BCD and write them
  Wire.write(decToBCD(myMenu[5]));  // convert tmpDay to BCD and write them
  Wire.write(decToBCD(myMenu[2]));  // convert tmpDate to BCD and write them
  Wire.write(decToBCD(myMenu[3]));  // convert tmpMonth to BCD and write them
  Wire.write(decToBCD(myMenu[4]));  // convert tmpYear to BCD and write them
  Wire.write(0b00010000); // enable 1Hz Square wave on PIN7
  Wire.endTransmission(); // close the transmission  
}

// Show the time
// You need to use the other program to see the RTC is working
void showTime()
{
  lcd.setCursor(0,0);
    lcd.print("    ");
    lcd.print(myMenu[0]); lcd.print(":"); // hour
    lcd.print(myMenu[1]); lcd.print(":"); lcd.print("00       "); // minute
  lcd.setCursor(3,1);
    lcd.print(days[myMenu[5]]); lcd.print(" "); // DOW   
    lcd.print(myMenu[2]); lcd.print("."); // date
    lcd.print(myMenu[3]); lcd.print("."); // month
    lcd.print(myMenu[4]); lcd.print("   "); // year
// Call the writeRTC function
writeRTC();
}

void loop() 
{
  if (menuCounter == 0)
  {
    setHour();
  }
  if (menuCounter == 1)
  {
    setMinute();
  }
  if (menuCounter == 2)
  {
    setDate();
  }
  if (menuCounter == 3)
  {
    setMonth();
  }
  if (menuCounter == 4)
  {
    setYear();
  }
  if (menuCounter == 5)
  {
    setDOW();
  }
  if (menuCounter == 6)
  {
    showTime();
  }
}

該程序以簡短的歡迎信息開始。此消息告訴您已接通電源,LCD 正在工作,并且程序已開始運行。

要從 RTC 讀取并顯示時間和日期,您必須使用以下程序對微控制器進行編程。程序從 RTC 讀取時間和日期值并將它們顯示在 LCD 上。

// Include header files

#include 
#include 

// LCD pin definitions
#define RS 9
#define E 10
#define D4 8
#define D5 7
#define D6 6
#define D7 5

LiquidCrystal lcd(RS, E, D4, D5, D6, D7);

// Pin that will receive clock pulse from RTC
int clockPin = 0;

// Time and date vaiables
byte second;
byte minute;
byte hour;
byte day;
byte date;
byte month;
byte year;

// A array of the weekday
char* days[] = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" };

// Function run once
void setup() {
  pinMode(clockPin, INPUT); pinMode(clockPin, LOW);
  Wire.begin();
  lcd.begin(16,2);
  showWelcome();
}

// Nice welcome message, then we know LCD is OK
void showWelcome()
{
  lcd.setCursor(2,0);
  lcd.print("Hello world.");
  lcd.setCursor(3,1);
  lcd.print("I'm alive.");
  delay(500);
  lcd.clear();
}

// Doing this forever
void loop() {
  // While clockPin is high
  while (digitalRead(clockPin))
  {
    // start the I2C transmission, at address 0x68
    Wire.beginTransmission(0x68);
    
    // Start at address 0
    Wire.write(0);

    // Close transmission
    Wire.endTransmission();
    
    // Start to read the 7 binary data from 0x68
    Wire.requestFrom(0x68, 7);
    second = Wire.read();
    minute = Wire.read();
    hour = Wire.read();
    day = Wire.read();
    date = Wire.read();
    month = Wire.read();
    year = Wire.read();
 
    // Formatting and displaying time
    lcd.setCursor(4,0);
      if (hour < 10) lcd.print("0");
        lcd.print(hour, HEX); lcd.print(":"); 
      if (minute < 10) lcd.print("0");
        lcd.print(minute, HEX); lcd.print(":"); 
      if (second < 10) lcd.print("0");
        lcd.print(second, HEX);
    lcd.setCursor(2,1);
  
    // Formatting and displaying date
    lcd.print(days[day]); lcd.print(" ");
      if (date < 10) lcd.print("0");
        lcd.print(date, HEX); lcd.print(".");
      if (month < 10) lcd.print("0");
        lcd.print(month, HEX); lcd.print(".");
        lcd.print(year, HEX);  
    } // end while     
}

結論

在本文中,我們研究了 Maxim Integrated 的小型 DS1307 RTC IC。我們制作了一個程序來設置時間和日期,我們制作了另一個程序來讀取時間和日期。為了檢查是否按下了開關,我們使用了中斷。中斷還負責開關彈跳。

圖片

pYYBAGJnuhuAYbpoABWSjmq5wVM827.JPG

點擊圖片為全尺寸。

pYYBAGJnuh-AF1NEAA-cYfVHaxM943.JPG

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 實時時鐘
    +關注

    關注

    4

    文章

    211

    瀏覽量

    65375
  • DS1307
    +關注

    關注

    1

    文章

    34

    瀏覽量

    14026
收藏 人收藏

    評論

    相關推薦

    arduino學習筆記38 - Arduino + DS1307 RTC時鐘模塊與經典總結

    :RTC   芯片標號:1307   表面安裝器件:通孔安裝   輸出數:1 以上是DS1307的要點,寫下來介紹一下它的連接方法。 這個是我的實際產品,采用的是IIC接法方式,和Arduino連接是非
    發表于 10-24 11:13

    帶有ATtiny85/DS1307時鐘開發板

    描述ATtiny85 TinyClock DS1307 DIP帶有 ATtiny85 微控制器、DS1307 實時時鐘和 2032 電池座的時鐘開發板。PCB+展示
    發表于 08-19 07:20

    I2C總線接口時鐘芯片DS1307在坦克半主動懸掛電控單元中

    根據坦克半主動懸掛電控單元對定時的需要,文中給出了采用I2C總線接口實時時鐘芯片進行準確定時的設計原理,提出了實時時鐘芯片DS1307與單片機接口電路的改進辦法,同時給出
    發表于 04-24 15:53 ?55次下載

    實時時鐘電路DS1302的原理及應用

    實時時鐘電路DS1302的原理及應用 現在流行的串行時鐘電路很多,如DS1302、DS1307、PCF8485等。這些電路的接口簡單、
    發表于 01-01 00:19 ?5255次閱讀
    <b class='flag-5'>實時時鐘</b>電路<b class='flag-5'>DS</b>1302的原理及應用

    ds1302實時時鐘

    ds1302實時時鐘 現在流行的串行時鐘電路很多,如DS1302、DS1307、PCF8485等。這些電路的接口簡單、價格低廉、使用方便,
    發表于 10-09 09:34 ?3753次閱讀
    <b class='flag-5'>ds</b>1302<b class='flag-5'>實時時鐘</b>

    基于DS1307的簡易時鐘顯示程序分享

    DS1307是一款低功耗,具有56字節非失性RAM的全BCD碼時鐘日歷實時時鐘芯片,地址和數據通過兩線雙向的串行總線的傳輸,芯片可以提供秒,分,小時等信息,每一個月的天數能自動調整。并且有閏年補償功能
    發表于 01-26 10:08 ?8940次閱讀
    基于<b class='flag-5'>DS1307</b>的簡易<b class='flag-5'>時鐘</b>顯示程序分享

    基于ARM和DS1307實時時鐘系統設計

    DS1307是I2C接口的8引腳實時時鐘芯片,片內含有8個特殊功能寄存器和56bit的SRAM。它是一款按BCD碼存取、低功耗的時鐘/日歷芯片,已被應用到人造板尺寸檢測以及電控單元中。介紹了一個簡單
    發表于 01-26 10:01 ?3017次閱讀
    基于ARM和<b class='flag-5'>DS1307</b>的<b class='flag-5'>實時時鐘</b>系統設計

    基于DS1307的可調實時時鐘系統設計

    DS1307是一款具有I2C總線接口的實時時鐘芯片,要驅動具有I2C總線接口的DS1307芯片,一種辦法是選擇一款帶有I2C總線接口的高檔單片機,然而,在很多小型儀器儀表中以及在單片機的教學環境
    發表于 01-26 16:47 ?1w次閱讀
    基于<b class='flag-5'>DS1307</b>的可調<b class='flag-5'>實時時鐘</b>系統設計

    DS1307串行實時時鐘和AT24C02串行CMOS E2PROM電路原理圖免費下載

    本文檔的主要內容詳細介紹的是DS1307串行實時時鐘和AT24C02串行CMOS E2PROM電路原理圖免費下載。
    發表于 03-22 08:00 ?24次下載
    <b class='flag-5'>DS1307</b>串行<b class='flag-5'>實時時鐘</b>和AT24C02串行CMOS E2PROM電路原理圖免費下載

    dfrobotI2C DS1307 RTC實時時鐘模塊介紹

    DFRobot曾出過一款DS1307 RTC 實時時鐘模塊,它以低廉的價格廣受客戶好評。此次DFRobot特意推出了新一代Gravity: I2C DS1307 RTC實時時鐘模塊。
    的頭像 發表于 12-07 11:02 ?4682次閱讀
    dfrobotI2C <b class='flag-5'>DS1307</b> RTC<b class='flag-5'>實時時鐘</b>模塊介紹

    DS1307 時鐘/定時 - 實時時鐘

    電子發燒友網為你提供Maxim(Maxim)DS1307相關產品參數、數據手冊,更有DS1307的引腳圖、接線圖、封裝手冊、中文資料、英文資料,DS1307真值表,DS1307管腳等資
    發表于 11-21 21:25
    <b class='flag-5'>DS1307</b> <b class='flag-5'>時鐘</b>/定時 - <b class='flag-5'>實時時鐘</b>

    Arduino DS1307 RTC時鐘

    電子發燒友網站提供《Arduino DS1307 RTC時鐘.zip》資料免費下載
    發表于 11-22 09:15 ?4次下載
    Arduino <b class='flag-5'>DS1307</b> RTC<b class='flag-5'>時鐘</b>

    從舊風扇和DS1307 RTC創建POV時鐘

    電子發燒友網站提供《從舊風扇和DS1307 RTC創建POV時鐘.zip》資料免費下載
    發表于 11-23 14:28 ?0次下載
    從舊風扇和<b class='flag-5'>DS1307</b> RTC創建POV<b class='flag-5'>時鐘</b>

    DS1307與兼容8051的微控制器接口

    DS1307串行實時時鐘集成了2線串行接口,可使用兼容8051的微控制器進行控制。本例中的DS1307直接連接到DS5000微控制器上的兩個I/O端口,2線握手由低電平驅動器處理,本應
    的頭像 發表于 03-01 13:52 ?960次閱讀
    <b class='flag-5'>DS1307</b>與兼容8051的微控制器接口

    Arduino篇—實時時鐘

    DS1307時鐘模塊:** DS1307串行實時時鐘(RTC)是低功耗,全二進制編碼的十進制(BCD)時鐘/日歷以及56字節的NV SRAM
    的頭像 發表于 11-01 16:49 ?1168次閱讀
    Arduino篇—<b class='flag-5'>實時時鐘</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>