Rtc ds3231

Бумажные кристаллики

Что необходимо

  • компьютер с установленной Arduino IDE;
  • плата Arduino;
  • микросхема DS1307 или модуль RTC на ее основе;
  • перемычки;
  • макетная плата;
  • комплектующие из списка элементов.

Вы можете заменить плату Arduino на контроллер Atmel, но убедитесь, что у него достаточно входных и выходных выводов и есть аппаратная реализация интерфейса I2C. Я использую ATMega168A-PU. Если вы будете использовать отдельный микроконтроллер, то вам понадобится программатор, например, AVR MKII ISP.

Предполагается, что читатель знаком с макетированием, программированием в Arduino IDE и имеет некоторые знания языка программирования C. Обе программы, приведенные ниже, не нуждаются в дополнительном разъяснении.

Исходный код программы

Arduino

#include <Wire.h>
#include «RTClib.h»
#include <TimerOne.h>
RTC_DS1307 RTC;
int temp,inc,hours1,minut,add=11;
#define d1 12
#define d2 11
#define d3 10
#define d4 9
#define d5 8
#define d6 7
#define r1 6
#define r2 5
#define r3 4
#define r4 3
int HOUR,MINUT,SECOND; //переменные для хранения значения часов, минут и секунд
volatile int count=0;
void Clear(int d)
{
digitalWrite(d1, HIGH);
digitalWrite(d2, HIGH);
digitalWrite(d3, HIGH);
digitalWrite(d4, HIGH);
digitalWrite(d5, HIGH);
digitalWrite(d6, HIGH);
}
void callback()
{
digitalWrite(13, digitalRead(13) ^ 1);
count++;
if(count>=7)
count=1;
switch(count%7)
{
case 1:
Clear(d1);
temp=SECOND%10;
show(temp);
digitalWrite(d1, LOW);
break;
case 2:
Clear(d2);
temp=SECOND/10;
show(temp);
digitalWrite(d2, LOW);
for(int i=0;i<10000;i++)
{
}
break;

case 3:
Clear(d3);
temp=MINUT%10;
show(temp);
digitalWrite(d3, LOW);
for(int i=0;i<10000;i++)
{
}
break;
case 4:
Clear(d4);
temp=MINUT/10;
show(temp);
digitalWrite(d4, LOW);
for(int i=0;i<10000;i++)
{
}
break;
case 5:
Clear(d5);
temp=HOUR%10;
show(temp);
digitalWrite(d5, LOW);
for(int i=0;i<10000;i++)
{
}
break;
case 6:
Clear(d6);
temp=HOUR/10;
show(temp);
digitalWrite(d6, LOW);
for(int i=0;i<10000;i++)
{
}
break;
}
}
void show(int d)
{
for(int i=0;i<1;i++)
{
digitalWrite(r4, !((temp>>0)&1));
digitalWrite(r3, !((temp>>1)&1));
digitalWrite(r2, !((temp>>2)&1));
digitalWrite(r1, !((temp>>3)&1));
// delay(1);
for(int i=0;i<1000;i++);
}
}

void setup()
{
Wire.begin();
Serial.begin(9600);
RTC.begin();
digitalWrite(next, HIGH);
digitalWrite(set_mad, HIGH);
digitalWrite(INC, HIGH);
pinMode(14, OUTPUT);
for(int i=2;i<=12;i++)
{
pinMode(i, OUTPUT);
digitalWrite(i, HIGH);
}

if(!RTC.isrunning())
{
RTC.adjust(DateTime(__DATE__,__TIME__));
}
Timer1.initialize(1000);
Timer1.attachInterrupt(callback);
}

void loop()
{
int temp=0,val=1,temp4;
DateTime now = RTC.now();
HOUR=now.hour();
MINUT=now.minute();
SECOND=now.second();
Serial.print(HOUR);
Serial.print(«:»);
Serial.print(MINUT);
Serial.print(«:»);
Serial.println(SECOND);
delay(200);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

#include <Wire.h>
#include «RTClib.h»
#include <TimerOne.h>

RTC_DS1307RTC;

inttemp,inc,hours1,minut,add=11;

#define d1 12
#define d2 11
#define d3 10
#define d4 9
#define d5 8
#define d6 7
#define r1 6
#define r2 5
#define r3 4
#define r4 3

intHOUR,MINUT,SECOND;//переменные для хранения значения часов, минут и секунд

volatileintcount=;

voidClear(intd)

{

digitalWrite(d1,HIGH);

digitalWrite(d2,HIGH);

digitalWrite(d3,HIGH);

digitalWrite(d4,HIGH);

digitalWrite(d5,HIGH);

digitalWrite(d6,HIGH);

}

voidcallback()

{

digitalWrite(13,digitalRead(13)^1);

count++;

if(count>=7)

count=1;

switch(count%7)

{

case1

Clear(d1);

temp=SECOND%10;

show(temp);

digitalWrite(d1,LOW);

break;

case2

Clear(d2);

temp=SECOND10;

show(temp);

digitalWrite(d2,LOW);

for(inti=;i<10000;i++)

{

}

break;

case3

Clear(d3);

temp=MINUT%10;

show(temp);

digitalWrite(d3,LOW);

for(inti=;i<10000;i++)

{

}

break;

case4

Clear(d4);

temp=MINUT10;

show(temp);

digitalWrite(d4,LOW);

for(inti=;i<10000;i++)

{

}

break;

case5

Clear(d5);

temp=HOUR%10;

show(temp);

digitalWrite(d5,LOW);

for(inti=;i<10000;i++)

{

}

break;

case6

Clear(d6);

temp=HOUR10;

show(temp);

digitalWrite(d6,LOW);

for(inti=;i<10000;i++)

{

}

break;

}

}

voidshow(intd)

{

for(inti=;i<1;i++)

{

digitalWrite(r4,!((temp>>)&1));

digitalWrite(r3,!((temp>>1)&1));

digitalWrite(r2,!((temp>>2)&1));

digitalWrite(r1,!((temp>>3)&1));

// delay(1);

for(inti=;i<1000;i++);

}

}
 

voidsetup()

{

Wire.begin();

Serial.begin(9600);

RTC.begin();

digitalWrite(next,HIGH);

digitalWrite(set_mad,HIGH);

digitalWrite(INC,HIGH);

pinMode(14,OUTPUT);

for(inti=2;i<=12;i++)

{

pinMode(i,OUTPUT);

digitalWrite(i,HIGH);

}

if(!RTC.isrunning())

{

RTC.adjust(DateTime(__DATE__,__TIME__));

}

Timer1.initialize(1000);

Timer1.attachInterrupt(callback);

}

voidloop()

{

inttemp=,val=1,temp4;

DateTimenow=RTC.now();

HOUR=now.hour();

MINUT=now.minute();

SECOND=now.second();

Serial.print(HOUR);

Serial.print(«:»);

Serial.print(MINUT);

Serial.print(«:»);

Serial.println(SECOND);

delay(200);

}

Преимущества подземной проводки

Прокладка кабеля под землёй имеет есть ряд преимуществ перед наземной:

  1. Уменьшение шанса на повреждение сети. При соблюдении всех норм укладки кабель будет сложно передавить или переехать, а также на его состояние не будут влиять погодные условия и деревья. 
  2. Проще определить длину провода. Если выбирается кабель для подземной прокладки, то во время выбора требуется учёт сечения и длины всей линии. Для воздушного кабеля необходимо было бы вычислять вес и силу натяжения, чтобы не было перегрузки. 
  3. Меньшие затраты. Для подключения необходим только устройство принудительного отключения сети, а также небольшие траты на проект. 
  4. Меньше риск возникновения пожара. 
  5. Также уменьшается воздействие электромагнитных волн и грозы. 
  6. Эстетичность. Так как провода находятся под землёй, участок можно использовать по своим предпочтениям. Главное – помнить, где располагается провод, чтобы при посадке деревьев не возникло неприятностей.  

Участок перед закапыванием траншеиИсточник s00.yaplakal.com

Что за идея

Ранее мы делали один сложный проект с цифровыми часами, о котором мы расскажем в следующих уроках, и нашли в процессе несколько проблем. После этого мы решили поделиться этой проблемой со всеми. Основная проблема в том как оценивается длительность секунды.

По факту — сделать правильную секунду в цифровых часах не так просто. Нужно правильно работать с циклами. Мы нашли много комментариев на англоязычных сайтах:

На скриншоте выше видно, что код реализован таким образом, что теперь инкремент s будет выполняться каждую 1 секунду и не больше, в зависимости от времени выполнения цикла loop{}.

В связи с этим резисторы и потенциометры мы полностью удалили.

Кнопки настройки времени вы можете использовать встроенные в микросхему ATmega328P.

pinMode(hs, INPUT_PULLUP) избегает использования внешнего Pullup. Подробнее о INPUT_PULLUP читайте в нашем Справочнике программиста Ардуино.

Избегайте потенциометра ЖК-дисплея.

Контрастность ЖК-дисплея может быть установлена с помощью сигнала PWM (Широтно-импульсная модуляция (ШИМ, англ. pulse-width modulation (PWM))) Arduino.

То же самое для подсветки, которая питается сигналом ШИМ (PWM) Arduino, поэтому её можно установить как вкл/выкл с помощью Arduino.

Код из видео:

#include <Wire.h>
#include <OLED_I2C.h>

OLED  myOLED(SDA, SCL, 8);

extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
 
   
 ///// часы ..
byte decToBcd(byte val){
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val){
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(0x68);
   Wire.write(0);
   Wire.write(decToBcd(second));    
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(0x68);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(0x68, 7);

  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f); 
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}
  
///// температура ..
float get3231Temp(){
  byte tMSB, tLSB; 
  float temp3231;

  Wire.beginTransmission(0x68);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(0x68, 2);

  if(Wire.available()) {
    tMSB = Wire.read(); //2's complement int portion
    tLSB = Wire.read(); //fraction portion

    temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  else {
    //oh noes, no data!
  }

  return temp3231;
}


void setup()
{
  Serial.begin(9600);
  myOLED.begin();
  Wire.begin();
 

 /*  // установка часов
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  second = 30;
  minute = 0;
  hour = 14;
  dayOfWeek = 3; // день недели
  dayOfMonth = 1; // день
  month = 4;
  year = 14;

  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
 */
}

void loop(){
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  char week = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
 
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  char time;
  char data;
  
  snprintf(time, sizeof(time),"%02d:%02d:%02d",           
           hour, minute, second);
           
  snprintf(data, sizeof(data), "%02d/%02d/%02d",            
            dayOfMonth, month, year);
  
  myOLED.setFont(SmallFont);
 
  myOLED.print(time, LEFT, 0);
  myOLED.print(data, LEFT, 15);
  myOLED.printNumF(get3231Temp(), 2, LEFT, 30);
  myOLED.print("C", 32, 30);
  myOLED.update();

 delay(1000);
}

////// конец
 

Важные страницы

  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макро, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту (alex@alexgyver.ru)

Масляный обогреватель

Пример проекта с i2C модулем часов и дисплеем

Проект представляет собой обычные часы, на индикатор будет выведено точное время, а двоеточие между цифрами будет мигать с интервалом раз в одну секунду. Для реализации проекта потребуются плата Arduino Uno, цифровой индикатор, часы реального времени (в данном случае вышеописанный модуль ds1307), шилд для подключения (в данном случае используется Troyka Shield), батарейка для часов и провода.

В проекте используется простой четырехразрядный индикатор на микросхеме TM1637. Устройство обладает двухпроводным интерфейсом и обеспечивает 8 уровней яркости монитора. Используется только для показа времени в формате часы:минуты. Индикатор прост в использовании и легко подключается. Его выгодно применять для проектов, когда не требуется поминутная или почасовая проверка данных. Для получения более полной информации о времени и дате используются жидкокристаллические мониторы.

Модуль часов подключается к контактам SCL/SDA, которые относятся к шине I2C. Также нужно подключить землю и питание. К Ардуино подключается так же, как описан выше: SDA – A4, SCL – A5, земля с модуля к земле с Ардуино, VCC -5V.

Индикатор подключается просто – выводы с него CLK и DIO подключаются к любым цифровым пинам на плате.

Скетч. Для написания кода используется функция setup, которая позволяет инициализировать часы и индикатор, записать время компиляции. Вывод времени на экран будет выполнен с помощью loop.


#include <Wire.h>

#include "TM1637.h"

#include "DS1307.h" //нужно включить все необходимые библиотеки для работы с часами и дисплеем.

char compileTime[] = __TIME__; //время компиляции.

#define DISPLAY_CLK_PIN 10

#define DISPLAY_DIO_PIN 11 //номера с выходов Ардуино, к которым присоединяется экран;

void setup()

{

display.set();

display.init(); //подключение и настройка экрана.

clock.begin(); //включение часов.

byte hour = getInt(compileTime, 0);

byte minute = getInt(compileTime, 2);

byte second = getInt(compileTime, 4); //получение времени.

clock.fillByHMS(hour, minute, second); //подготовка для записывания в модуль времени.

clock.setTime(); //происходит запись полученной информации во внутреннюю память, начало считывания времени.

}

void loop()

{

int8_t timeDisp; //отображение на каждом из четырех разрядов.

clock.getTime();//запрос на получение времени.

timeDisp = clock.hour / 10;

timeDisp = clock.hour % 10;

timeDisp = clock.minute / 10;

timeDisp = clock.minute % 10; //различные операции для получения десятков, единиц часов, минут и так далее.

display.display(timeDisp); //вывод времени на индикатор

display.point(clock.second % 2 ? POINT_ON : POINT_OFF);//включение и выключение двоеточия через секунду.

}

char getInt(const char* string, int startIndex) {

return int(string - '0') * 10 + int(string) - '0'; //действия для корректной записи времени в двухзначное целое число. В ином случае на экране будет отображена просто пара символов.

}

После этого скетч нужно загрузить и на мониторе будет показано время.

Программу можно немного модернизировать. При отключении питания выше написанный скетч приведет к тому, что после включения на дисплее будет указано время, которое было установлено при компиляции. В функции setup каждый раз будет рассчитываться время, которое прошло с 00:00:00 до начала компиляции. Этот хэш будет сравниваться с тем, что хранятся в EEPROM, которые сохраняются при отключении питания.

Для записи и чтения времени в энергонезависимую память или из нее нужно добавить функции EEPROMWriteInt и EEPROMReadInt. Они нужны для проверки совпадения/несовпадения хэша с хэшем, записанным в EEPROM.

Можно усовершенствовать проект. Если использовать жидкокристаллический монитор, можно сделать проект, который будет отображать дату и время на экране. Подключение всех элементов показано на рисунке.

В результате в коде нужно будет указать новую библиотеку (для жидкокристаллических экранов это LiquidCrystal), и добавить в функцию loop() строки для получения даты.

Алгоритм работы следующий:

  • Подключение всех компонентов;
  • Загрузка скетча;
  • Проверка – на экране монитора должны меняться ежесекундно время и дата. Если на экране указано неправильное время, нужно добавить в скетч функцию RTC.write (tmElements_t tm). Проблемы с неправильно указанным временем связаны с тем, что модуль часов сбрасывает дату и время на 00:00:00 01/01/2000 при выключении.
  • Функция write позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.

Подключение DS3231 к Ардуино

Общение с DS3231 осуществляется по линиям I2C. Схема подключения RTC модуля на DS3231 к Ардуино Уно приведена ниже.

Подключение DS3231 к Ардуино для работы с будильником

Если бы нас интересовало только текущее время, то достаточно было бы подключить VCC, GND, SCL и SDA модуля к соответствующим выводам Ардуино. В данном же случае нам нужен ещё вывод INT/SQW. На нём будет генерироваться сигнал запроса прерывания для пробуждения микроконтроллера. Поэтому проще всего подключить его к входу внешнего прерывания, для УНО это D2 и D3. Хотя можно использовать и другие выводы, разрешив на них PCINT.

Кстати, на моём модуле не было вывода INT/SQW. При этом в штыревом разъеме один из выводов был не задействован. Я подпаял его к третьей ножке микросхемы DS3231 (это и есть INT/SQW) и получил нужный мне вывод на штыревом разъеме модуля.

Добавление недостающего вывода INT/SQW на модуле DS3231

Шаг 10. Программируем

Если вы этого еще не сделали — скачайте и установите Arduino IDE.

Добавить поддержку Sparkfun Pro Micro

Следуйте инструкциям по установке, чтобы добавить поддержку плат Sparkfun: https://github.com/sparkfun/Arduino_Boards

После установки поддержки не забудьте выбрать правильную плату в Arduino IDE:

Сервис -> Плата -> SparkFun Pro Micro (Tools -> Board -> SparkFun Pro Micro)

Сервис -> Процессор -> ATmega32U4 (3,3 В, 8 МГц) (Tools -> Processor -> ATmega32U4 (3.3V, 8MHz))

Библиотека Adafruit RTClib

Используйте Arduino IDE Library Manager для установки RTClib: https://www.arduino.cc/en/guide/libraries

Библиотека Arduino GFX

Добавьте библиотеку Arduino_GFX в Arduino IDE: https://github.com/moononournation/Arduino_GFX.git

Если вы никогда этого не делали, то просто добавьте библиотеку из GitHub, — нажмите зеленую кнопку «Клонировать или скачать», а затем «Скачать ZIP». Далее в Arduino IDE выберите меню: Эскиз -> Включить библиотеку -> Добавить библиотеку .ZIP … -> выберите загруженный файл ZIP (англ.: Sketch -> Include Library -> Add .ZIP Library… -> ZIP).

Библиотека LowPower

Добавьте библиотеку Arduino_GFX в Arduino IDE: https://github.com/rocketscream/Low-Power.git

Установка такая же, как описано выше.

Основной код часов Arduino  — Watch Core

Пожалуйста, используйте Arduino IDE, скомпилируйте и загрузите RTClibSetRTC.ino, чтобы инициализировать время в RTC. А затем скомпилируйте и загрузите Arduino_Watch.ino.

Код

Код проекта вы можете скачать или скопировать ниже. Код содержит комментарии. Обычно мы рекомендуем копировать код из скачанного файла, т.к. при копировании могут выявляться некоторые ошибки.

Также не забываем, что мы в самом начале подключаем библиотеку LiquidCrystal, которую вы можете скачать в разделе Библиотеки на нашем сайте.

/*
 ###  Самые простые часы на Arduino UNO ###

 Для проекта часов нужны только жк-дисплей 16х2 LCD и 2 кнопки
 Никаких потенциометров для контраса, никаких резисторов 
 Функции кнопок:
 
 - короткое нажатие одной из кнопок включает подсветку на 30 с
 
 Настройка времени
 - Нажмите H для увеличения Часов
 - Нажмите M для увеличения Минут и сброса секунд
*/

#include "LiquidCrystal.h"

// Определяем соединение ЖК-дисплея с цифровыми контактами
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// Настройка контрастности ЖК
int cs=9;// пин 9 для контраста ШИМ
const int contrast = 100;// контраст по умолчанию

// Начальное отображение времени 12:59:45 PM
int h=12;
int m=59;
int s=45;
int flag=1; //PM

// Кнопки установки времени
int button1;
int button2;

// Определение пинов для Кнопок установки времени
int hs=0;// pin 0 для настройки Часов
int ms=1;// pin 1 для настройки Минут

// Тайм-аут подсветки 
const int Time_light=150;
int bl_TO=Time_light;// Тайм-аут подсветки
int bl=10; // Пин подсветки
const int backlight=120; // НЕ БОЛЕЕ 7mA !!!

// Для точного считывания времени используйте часы реального времени Arduino, а не только задержку delay()
static uint32_t last_time, now = 0; // RTC

void setup()
{
  lcd.begin(16,2);
  pinMode(hs,INPUT_PULLUP);// избегать внешних Pullup резисторов для кнопки 1
  pinMode(ms,INPUT_PULLUP);// и кнопки 2
  analogWrite(cs,contrast);// Настроить контрастность VO
  analogWrite(bl,backlight);// Включить подсветку 
  now=millis(); // читать начальное значение RTC  
}

void loop()
{ 
  lcd.begin(16,2);// каждую секунду
// Обновить ЖК-дисплей
// Вывести время TIME в Hour, Min, Sec + AM/PM (часы, минуты, секунды)
 lcd.setCursor(0,0);
 lcd.print("Time ");
 if(h<10)lcd.print("0");// всегда 2 цифры
 lcd.print(h);
 lcd.print(":");
 if(m<10)lcd.print("0");
 lcd.print(m);
 lcd.print(":");
 if(s<10)lcd.print("0");
 lcd.print(s);

 if(flag==0) lcd.print(" AM");
 if(flag==1) lcd.print(" PM");
 
 lcd.setCursor(0,1);// для Line 2
 lcd.print("Precision clock");

// улучшенная замена delay(1000) 
// гораздо лучшая точность, менее зависимая от времени выполнения цикла

for ( int i=0 ;i<5 ;i++)// сделать 5-кратный цикл 200 мс, для более быстрого ответа кнопок
{
  while ((now-last_time)<200) //задержка delay 200ms
  { 
    now=millis();
  }
 // внутренний цикл 200ms
 last_time=now; // готовим следующий цикл 

 // read Setting Buttons (читаем кнопки настройки)
 button1=digitalRead(hs);// Read Buttons
 button2=digitalRead(ms);

 //Время подсветки 
 bl_TO--;
 if(bl_TO==0)
 {
  analogWrite(bl,0);// ВЫКЛ подсветки
  bl_TO++;
 }
 
 // Нажмите что-либо, чтобы активировать подсветку 
 if(  ((button1==0)|(button2==0)) & (bl_TO==1)  )
 {
  bl_TO=Time_light;
  analogWrite(bl,backlight);
  // дождитесь отпускания кнопки
  while ((button1==0)|(button2==0))
  {
   button1=digitalRead(hs);// Read Buttons
   button2=digitalRead(ms);
  }
 }
 else
 // Поведение Кнопки 1 или Кнопки 2 пока подсветка ВКЛ 
 {
  if(button1==0){
   h=h+1;
   bl_TO=Time_light;
   analogWrite(bl,backlight);
  }

 if(button2==0){
  s=0;
  m=m+1;
  bl_TO=Time_light;
  analogWrite(bl,backlight);
  }

/* ---- управлять секундами, минутами, часами am / pm ----*/
 if(s==60){
  s=0;
  m=m+1;
 }
 if(m==60)
 {
  m=0;
  h=h+1;
 }
 if(h==13)
 {
  h=1;
  flag=flag+1;
  if(flag==2)flag=0;
 }

 if((button1==0)|(button2==0))// Обновить дисплей, если нажата кнопка
 {
  // Обновить ЖК
  // Вывести время TIME в часах, минутах, секундах + AM/PM
  lcd.setCursor(0,0);
  lcd.print("Time ");
  if(h<10)lcd.print("0");// всегда 2 цифры
  lcd.print(h);
  lcd.print(":");
  if(m<10)lcd.print("0");
  lcd.print(m);
  lcd.print(":");
  if(s<10)lcd.print("0");
  lcd.print(s);

  if(flag==0) lcd.print(" AM");
  if(flag==1) lcd.print(" PM");
 
  lcd.setCursor(0,1);// для Line 2
  lcd.print("Precision clock");
 }

 } // end if else
}// end for

// outer 1000ms loop (завершение цикла)
 s=s+1; //увеличение секунд
        
// ---- управлять секундами, минутами, часами + am/pm ----
 if(s==60){
  s=0;
  m=m+1;
 }
 if(m==60)
 {
  m=0;
  h=h+1;
 }
 if(h==13)
 {
  h=1;
  flag=flag+1;
  if(flag==2)flag=0;
 }  
// Loop end (конец цикла)
}

Микросхема M41T56

Микросхема M41T56 представляет собой часы реального времени, с последовательным интерфейсом I2C и низким энергопотреблением с 56 байтами энергонезависимой памяти. Встроенный генератор с частотой 32768 Гц (или же внешний стабилизированный кварцевый) и первые 8 байт ОЗУ используются для временных/календарных функций. Конфигурирование осуществляется в двоично-десятичном формате. Адреса и данные передаются последовательно по двухпроводной двунаправленной шине. Встроенный адресный регистр инкрементируется автоматически после каждой операции WRITE или READ для байта данных.

Часы реального времени M41T56 часы имеют встроенную схему контроля для обнаружения сбоев питания и автоматически переключается на питание от батарей во время сбоя внешнего питания. Энергия, необходимая для поддержания работоспособности оперативной памяти и часов может быть обеспечена при использовании небольшого литиевого элемента питания.

Типичное время хранения данных превышает 10 лет с 50 мА·ч, 3 В литиевым элементом. M41T56 поставляется в 8-выводном пластиковом SOIC-корпусе.

Расположение и назначение выводов

  • OSCI — вход кварца
  • OCSO — выход кварца
  • FT/OUT — тест частоты/выходной драйвер (с открытым стоком)
  • SDA — адресная линия вход/выход
  • SCL — выход данных
  • VBAT — питание от батареи
  • VCC — внешний источник питания
  • VSS — земля

Блок-схема MT41T56

Операции

Часы реального времени M41T56 работают как ведомое устройство на последовательной шине. Доступ получается реализацие условия запуска, за которым следует правильный адрес ведомого (D0h). К 64 байтам памяти, имеющимся в устройстве, можно получить последовательно доступ в следующем порядке:

  1. Регистр секунд
  2. Регистр минут
  3. Регистр век/часы
  4. Регистр дня недели
  5. Регистр даты
  6. Регистр месяца
  7. Регистр года
  8. Управляющий регистр
  9. ОЗУ

Микросхема постоянно отслеживает VCC на выход за допустимые пределы. Если VCC падает ниже VPFD, устройство прекращает дальнейший доступ и сбрасывает адрес счетчика. Входы устройства не будут признаны в это время, для предотвращения записи ошибочных данных на устройство с отказом от системы допуска. Когда VCC падает ниже VBAT, устройство автоматически переключается на аккумулятор в режим с пониженным энергопотреблением для экономии заряда аккумулятора. После подключения внешнего питания, устройство переключается с батарейного питания VBAT на VCC и считывает входы при превышении VCC в вольтах над VPFD.

В микросхеме имеется программируемый генератор прямоугольных импульсов, позволяющий вырабатывать одну из четырех частот (1 гц, 4096 Гц, 8192 Гц или 32768 Гц).

Полная версия datasheet на M41T56

Datasheet M41T56 datasheet_M41T56.pdf
478.2 KiB 469 Downloads

Datasheet RTC M41T56

Category: Documents
Date: 21.02.2015

Функции счёта времени

Данные функции возвращают время, прошедшее с момента запуска микроконтроллера, так называемый аптайм (англ. uptime). Таких функций у нас две:

  • – Возвращает количество миллисекунд, прошедших с запуска. Возвращает , от 1 до 4 294 967 295 миллисекунд (~50 суток), имеет разрешение 1 миллисекунда, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0
  • – Возвращает количество микросекунд, прошедших с запуска. Возвращает , от 4 до 4 294 967 295 микросекунд (~70 минут), имеет разрешение в 4 микросекунды, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0

Functions for setting and reading the time

get(void)

Description

Reads the current date and time from the RTC and returns it as a time_t value. Returns zero if an I2C error occurs (RTC not present, etc.).

None.

Current date and time (time_t)

Example
time_t myTime;
myTime = RTC.get();

set(time_t t)

Description

Sets the RTC date and time to the given time_t value. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.

t: The date and time to set the RTC to (time_t)

Example
//this example first sets the system time (maintained by the Time library) to
//a hard-coded date and time, and then sets the RTC from the system time.
//the setTime() function is part of the Time library.
setTime(23, 31, 30, 13, 2, 2009);   //set the system time to 23h31m30s on 13Feb2009
RTC.set(now());                     //set the RTC from the system time

read(tmElements_t &tm)

Description

tm: Address of a tmElements_t structure to which the date and time are returned.

I2C status (byte). Returns zero if successful. The date and time read from the RTC are returned to the tm parameter.

Example
tmElements_t tm;
RTC.read(tm);
Serial.print(tm.Hour, DEC);
Serial.print(':');
Serial.print(tm.Minute,DEC);
Serial.print(':');
Serial.println(tm.Second,DEC);
Description

Sets the RTC to the date and time given by a tmElements_t structure. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.

Example
tmElements_t tm;
tm.Hour = 23;             //set the tm structure to 23h31m30s on 13Feb2009
tm.Minute = 31;
tm.Second = 30;
tm.Day = 13;
tm.Month = 2;
tm.Year = 2009 - 1970;    //tmElements_t.Year is the offset from 1970
RTC.write(tm);            //set the RTC from the tm structure

Шаг 3. Код проекта

Я просто использую примерный эскиз из библиотеки, который будет содержать множество комментариев:

// DS3231_Serial_Easy
// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
// web: http://www.RinkyDinkElectronics.com/
//
// A quick demo of how to use my DS3231-library to 
// quickly send time and date information over a serial link
//
// To use the hardware I2C (TWI) interface of the Arduino you must connect
// the pins as follows:
//
// Arduino Uno/2009:
// ----------------------
// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
//
// Arduino Leonardo:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
//
// Arduino Mega:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
//
// Arduino Due:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
//
// The internal pull-up resistors will be activated when using the 
// hardware I2C interfaces.
//
// You can connect the DS3231 to any available pin but if you use any
// other than what is described above the library will fall back to
// a software-based, TWI-like protocol which will require exclusive access 
// to the pins used, and you will also have to use appropriate, external
// pull-up resistors on the data and clock signals.
//

#include 

// Init the DS3231 using the hardware interface
DS3231  rtc(SDA, SCL);

void setup()
{
  // Setup Serial connection
  Serial.begin(115200);
  // Uncomment the next line if you are using an Arduino Leonardo
  //while (!Serial) {}
  
  // Initialize the rtc object
  rtc.begin();
  
  // The following lines can be uncommented to set the date and time
  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
}

void loop()
{
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.println(rtc.getTimeStr());
  
  // Wait one second before repeating :)
  delay (1000);
}

Оцените статью
Рейтинг автора
5
Материал подготовил
Илья Коршунов
Наш эксперт
Написано статей
134
Добавить комментарий