Проект 26: Годинник реального часу. Принцип роботи, підключення, приклади
В цьому експерименті ми розглянемо модуль годин реального часу на мікросхемі DS1307.
Необхідні компоненти:
- контролер Arduino UNO R3;
- плата для прототипування;
- модуль годин реального часу DS1307;
- батарейка CR2032 3 В; •РКІ WH1602;
- потенціометр 10 кОм;
- резистор 51 Ом;
- дроти тато-тато.
- зовнішній блок живлення +5 В.
Мікросхема Dallas DS1307 є годинник реального часу з календарем і додатковою пам'яттю NW SRAM (56 байт). Мікросхема підключається до мікроконтролера за допомогою шини I2C. Кількість днів у місяці розраховується з урахуванням високосних років до 2100 р мікросхемі DS1307 є вбудована схема, яка визначає аварійне відключення живлення і автоматично підключає резервну батарейку. При цьому відлік часу продовжується, і після відновлення живлення годинник показує правильний час. Також в цій мікросхемі є програмований генератор прямокутних імпульсів, що дозволяє виробляти одну з чотирьох частот (1 Гц, 4096 Гц, 8192 Гц або 32768 Гц).
Годинники підключаються по протоколу I2C всього двома проводами. SCL і SDA - це виводи інтерфейсу I2C. Необхідно додатково підтягти виводи, до яких підключаються годинник до шини живлення, за допомогою резисторів 2 кОм. SCL і SDA на різних платах розташовані на різних виводах:
- Uno, Nano - A4 (SDA), A5 (SCL);
- Mega2560 - 20 (SDA), 21 (SCL);
- Leonardo - 2 (SDA), 3 (SCL).
вивід SDA годин підключається до виводу SDA контролера. SDL годин - відповідно, до SDL контролера. У нашому експерименті ми будемо виводити дату і час, одержувані з мікросхеми DS1307, на екран LCD індикатора WH1602. Схема підключення показана на рис. 26.1.

Рис. 26.1. Схема підключення модуля DS1307 і WH1602 до Arduino
При написанні скетчу використовуємо бібліотеку Time, яка є «обгорткою» для бібліотеки DS1307, і бібліотеку Wire для роботи з I2C-пристроями. Для роботи з РКІ використовуємо бібліотеку LiquidCrystal. Вміст скетчу показано в лістингу 26.1.
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
// підключення бібліотеки для lcd
#include <LiquidCrystal.h>
// ініціалізація із зазначенням контактів підключення
LiquidCrystal lcd (9, 8, 7, 6, 5, 4);
void setup ()
{
lcd.begin (16, 2); // встановити розмірність дисплея
}
void loop ()
{
tmElements_t tm;
if (RTC.read (tm)) // отримання часу
{
print2digits (tm.Hour, 0,0);
lcd.print ( ":");
print2digits (tm.Minute, 3,0);
lcd.print ( ":");
print2digits (tm.Second, 6,0);
print2digits (tm.Day, 0,1);
lcd.print ( "/");
print2digits (tm.Month, 3,1);
lcd.print ( "/");
lcd.print (tmYearToCalendar (tm.Year));
}
else
{
if (RTC.chipPresent ())
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print ( "DS1307 is stopped");
}
else
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print ( "DS1307 read error");
}
delay (9000);
}
delay (1000);
}
// процедура виведення на дисплей з додаванням до двох цифр
void print2digits (int number, int col, int str)
{
lcd.setCursor (col, str);
if (number> = 0 && number <10)
{Lcd.print ( "0");}
lcd.print (number);
}
Порядок підключення:
- Підключаємо модуль DS1307 і РКІ до плати Arduino за схемою на рис. 26.1.
- Завантажуємо в плату Arduino скетч з лістингу 26.1.
- Дивимося на екрані РКІ мінливий щомиті час і дату. Однак на екрані дисплея ми бачимо невірний час і невірну дату. Справа в тому, що при відсутності живлення значення часу в мікросхемі DS1307 скидається на 00:00:00 01/01/2000. Щоб при відключенні живлення часом не скидалося, передбачено аварійне живлення модуля від батарейки 3 в.Для установки часу в бібліотеці є функція RTC.write (tmElements_t tm). Додамо в скетч можливість установки даних RTC по послідовному порту відправкою такі рядки «dd / mm / YYYY hh: mm: ss» .Содержімое скетчу показано в лістингу 26.2.
лістинг 26.2
// підключення бібліотек для RTC
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
// підключення бібліотеки для lcd
#include <LiquidCrystal.h>
// ініціалізація із зазначенням контактів підключення
LiquidCrystal lcd (9, 8, 7, 6, 5, 4);
// рядок, що збирається з даних, що приходять в послідовний порт
String inputString = "";
boolean stringComplete = false; // прапор комплектності рядки
void setup ()
{
Serial.begin (9600); // запустити послідовний порт
lcd.begin (16, 2); // встановити розмірність дисплея
}
void loop ()
{
tmElements_t tm;
// очікування кінця рядка для аналізу надійшов запиту:
if (stringComplete)
{
tm.Day = (int (inputString [0]) - 48) * 10 + (int (inputString [1]) - 48);
tm.Month = (int (inputString [3]) - 48) * 10 + (int (inputString [4]) - 48);
tm.Year = CalendarYrToTm ((int (inputString [6]) -
48) * 1000 + (int (inputString [7]) - 48) * 100 +
(Int (inputString [8]) - 48) * 10 + (int (inputString [9]) - 48));
tm.Hour = (int (inputString [11]) - 48) * 10 + (int (inputString [12]) - 48);
tm.Minute = (int (inputString [14]) - 48) * 10 + (int (inputString [15]) - 48);
tm.Second = (int (inputString [17]) - 48) * 10 + (int (inputString [18]) - 48);
RTC.write (tm); // записати час в RTC
// очистити рядок
inputString = "";
stringComplete = false;
}
if (RTC.read (tm))
{
print2digits (tm.Hour, 0,0);
lcd.print ( ":");
print2digits (tm.Minute, 3,0);
lcd.print ( ":");
print2digits (tm.Second, 6,0);
print2digits (tm.Day, 0,1);
lcd.print ( "/");
print2digits (tm.Month, 3,1);
lcd.print ( "/");
lcd.print (tmYearToCalendar (tm.Year));
}
else
{
if (RTC.chipPresent ())
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print ( "DS1307 is stopped");
}
else
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print ( "DS1307 read error");
}
delay (9000);
}
delay (1000);
}
// процедура виведення на дисплей з додаванням до двох цифр
void print2digits (int number, int col, int str)
{
lcd.setCursor (col, str);
if (number> = 0 && number <10)
{Lcd.print ( "0");}
lcd.print (number);
}
// отримання даних по послідовному порту
void serialEvent ()
{
while (Serial.available ())
{// отримати черговий байт:
char inChar = (char) Serial.read ();
// додати в рядок
inputString + = inChar;
// / n - кінець передачі
if (inChar == '\ n')
{StringComplete = true;}
}
}
Тепер встановимо час з монітора послідовного порту відправкою рядки «dd / mm / YYYY hh: mm: ss» і побачимо на екрані дисплея відображення вірної дати і часу.