Проект 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.

// подключение библиотек для RTC
#include
#include
#include
// подключение библиотеки для lcd
#include
// инициализация с указанием контактов подключения
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);
}

Порядок подключения:

1. Подключаем модуль DS1307 и ЖКИ к плате Arduino по схеме на рис. 26.1.
2. Загружаем в плату Arduino скетч из листинга 26.1.
3. Смотрим на экране ЖКИ меняющееся ежесекундно время и дату. Однако на экране дисплея мы видим неверное время и неверную дату. Дело в том, что при отсутствии питания значение времени в микросхеме 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
#include
#include
// подключение библиотеки для lcd
#include
// инициализация с указанием контактов подключения
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» и увидим на экране дисплея отображение верной даты и времени.

Листинги программ скачать





 


Вверх