Tiny rtc i2c modules подключение arduino nano. Подключение часов реального времени ds1302 к Arduino. Соединение с Arduino Uno

  • Отличительные особенности:
  • Подсчет реального времени в секундах, минутах, часах, датах месяца, месяцах, днях недели и годах с учетом высокосности текущего года вплоть до 2100 г.
  • Дополнительное ОЗУ 31 x 8 для хранения данных
  • Последовательный ввод – вывод информации для сокращения выводов микросхемы
  • Выполнение всех функций при напряжении питания 2.0-5.5 В
    - выполнение всех функций при напряжении 2.0-5.5 В на дополнительном выводе питания
  • Потребление не более 300 нA при 2.5 В питания
  • Чтение и запись информации по одному байту или потоком
  • Исполнение в 8-ми выводном корпусе DIP, а также по заказу в 8-ми выводном SOIC корпусе для поверхностного монтажа
  • Простой 3-проводной интерфейс
  • Совместимость с TTL-микросхемами (Vcc= 5V)
  • Возможность поставки в промышленном диапазоне температур: от -40°C до+85°C
  • Совместимость с DS1202
  • Отличия от DS1202:
    возможность подключения встроенной цепи подзарядки к выводу Vcc1
    два вывода питания для подключения основного и резервного источника питания
    увеличено ОЗУ на 7 байт

Описание выводов:

X1, X2 подключение кварцевого резонатора 32.768 кГц
GND общий
RST сброс
I/O ввод - вывод данных
SCLK синхронизация последовательной связи
VCC1, VCC2 выводы питания

Структурная схема DS1302:

Общее описание:

Микросхема DS1302 содержит часы реального времени с календарем и 31 байт статического ОЗУ. Она общается с микропроцессором через простой последовательный интерфейс. Информация о реальном времени и календаре представляется в секундах минутах, часах, дне, дате, месяце и годе. Если текущий месяц содержит менее 31 дня, то микросхема автоматически определит количество дней в месяце с учетом высокосности текущего года. Часы работают или в 24-часовом или 12-часовом формате с индикатором AM/PM (до полудня/ после полудня). Подключение DS1302 к микропроцессу упрощено за счет синхронной последовательной связи. Для этого требуется только 3 провода: (1) RST (сброс), (2) I/O (линия данных) и (3) SCLK (синхронизация последовательной связи). Данные могут передаваться по одному байту или последовательностью байтов до 31. DS1302 разработан, чтобы потреблять малую мощность и сохранять данные и информацию часов при потреблении менее 1 мкВт. DS1302 - преемник DS1202. В дополнение к основным функциям хранения времени DS1202, DS1302 имеет два вывода питания для подключения основного и резервного источника питания, возможность подключения программируемой цепи заряда к выводу VCC1 и семь дополнительных байтов ОЗУ.

Подключение:

Подключение DS1307 к Arduino:

RTC DS1307 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Подключение DS1302 к Arduino:

RTC DS1302 Arduino UNO
GND GND
VCC +5V
RST 6 (Можно изменить на другие в скетче)
CLK 7 (Можно изменить на другие в скетче)
DAT

(Можно изменить на другие в скетче)

Подключение DS3231 к Arduino:

RTC DS3231 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Модуль DS1302 часы реального времени на Алиэкспресс http://ali.pub/1br52w

Код программы для модуля 1302 и дисплей 1602 I2C

В зависимости от того какой модуль Вы подключаете, необходимо в программе указать

Для DS1302 :

time . begin (RTC_DS1302 , 10 , 13 , 12 );

#include

virtuabotixRTC myRTC(6, 7, 8); //CLK, DAT, RST

Программа

#include

#include

LiquidCrystal_I2C lcd(0x3F ,2,1,0,4,5,6,7,3, POSITIVE);

void setup() {

lcd.begin(16,2);

//myRTC.setDS1302Time(00,04, 12, 06, 18, 04, 2017);

void loop() {

myRTC.updateTime();

lcd.setCursor(0, 0);

lcd.print("date: ");

lcd.print(myRTC.dayofmonth);

lcd.print("/");

lcd.print(myRTC.month);

lcd.print("/");

lcd.print(myRTC.year);

lcd.print(" ");

lcd.setCursor(0, 1);

lcd.print("time: ");

lcd.print(myRTC.hours);

lcd.print(":");

lcd.print(myRTC.minutes);

lcd.print(":");

lcd.print(myRTC.seconds);

lcd.println(" ");

Так же не забываем о экономии при покупке товаров на Алиєкспресс с помощью кэшбэка

Преимущества библиотеки:

Библиотека имеет внутренние функции аппаратной обработки протоколов передачи данных I2C и SPI, а следовательно не требует подключения дополнительных библиотек, но и не конфликтует с ними, если таковые всё же подключены.

Библиотека имеет внутренние функции программой обработки протокола передачи данных 3-Wire

Для инициализации модуля необходимо вызвать функцию begin с названием модуля.

Подключение модулей осуществляется к аппаратным выводам arduino используемой шины (за исключением 3-Wire)

Простота установки и чтения времени функциями settime и gettime

функция settime может устанавливать дату и время, как полностью, так и частично (например только минуты, или только день, и т.д.)

функция gettime работает как функция date в php, возвращая строку со временем, но если её вызвать без параметра, то функция ничего не вернёт, а время можно прочитать из переменных в виде чисел.

Библиотека расширяемая, то есть для того, чтоб она работала с новым модулем, нужно указать параметры этого модуля в уже существующих массивах файла RTC.h (тип шины, частота шины в кГц, режимы работы, адреса регистров и т.д.), как всё это сделать, описано в файле extension.txt

Таким образом добавив новый модуль в библиотеку, мы лишь увеличим область занимаемой динамической памяти на ~ 36 байт, при этом не затронув область памяти программ.

При вызове функции begin, библиотека читает флаги регистров модуля и при необходимости устанавливает или сбрасывает их так, чтоб модуль мог работать от аккумуляторной батареи, а на программируемом выводе меандра (если таковой у модуля есть) установилась частота 1Гц, тогда этот вывод можно использовать в качестве внешнего посекундного прерывания.

При работе с модулем DS1302 не нужны никакие резисторы на выводе GND (которые нужны для его работы с другими библиотеками этого модуля), это достигнуто тем, что для шины 3-Wire указана конкретная частота 10кГц, не зависимо от частоты CPU arduino.

В библиотеке реализована еще одна не обязательная функция period, принимающая в качестве единственного аргумента - количество минут (от 1 до 255)

если в течении указанного времени была вызвана функция gettime несколько раз, то запрос к модулю по шине будет отправлено только в первый раз, а ответом на все остальные запросы будет сумма времени последнего ответа модуля и времени прошедшего с этого ответа.

Функцию period достаточно вызвать один раз.

Подробное описание:

} // ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: // // Подключение библиотеки: // #include // iarduino_RTC time(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); // если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC time(RTC_DS3231); // если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC time(RTC_DS1305,22); // если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC time(RTC_DS1302, 1, 2, 3); // RST, CLK, DAT // // Для работы с модулями, в библиотеке реализованы 5 функции: // инициировать модуль begin(); // указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); // получить время gettime("строка с параметрами"); // мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень) // разгрузить шину period (минуты); // // Функция begin(): // функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. // // Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): // записывает время в модуль // год указывается без учёта века, в формате 0-99 // часы указываются в 24-часовом формате, от 0 до 23 // день недели указывается в виде числа от 0-воскресенье до 6-суббота // если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение // пример: settime(-1, 10); установит 10 минут, а секунды, часы и дату, оставит без изменений // пример: settime(0, 5, 13); установит 13 часов, 5 минут, 0 секунд, а дату оставит без изменений // пример: settime(-1, -1, -1, 1, 10, 15); установит дату 01.10.2015 , а время и день недели оставит без изменений // // Функция gettime("строка с параметрами"): // функция получает и выводит строку заменяя описанные ниже символы на текущее время // пример: gettime("d-m-Y, H:i:s, D"); ответит строкой "01-10-2015, 14:00:05, Thu" // пример: gettime("s"); ответит строкой "05" // указанные символы идентичны символам для функции date() в PHP // s секунды от 00 до 59 (два знака) // i минуты от 00 до 59 (два знака) // h часы в 12-часовом формате от 01 до 12 (два знака) // H часы в 24-часовом формате от 00 до 23 (два знака) // d день месяца от 01 до 31 (два знака) // w день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота) // D день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun) // m месяц от 01 до 12 (два знака) // M месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) // Y год от 2000 до 2099 (четыре знака) // y год от 00 до 99 (два знака) // a полдень am или pm (два знака, в нижнем регистре) // A полдень AM или PM (два знака, в верхнем регистре) // строка не должна превышать 50 символов // // если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных // seconds секунды 0-59 // minutes минуты 0-59 // hours часы 1-12 // Hours часы 0-23

Часы реального времени - модуль, который хранит текущую дату и не сбрасывает её при отключении питания благодаря встроенной батарейке. Вы могли слышать о часах на основе чипа DS1307. Этот чип отличается крайне низкой точностью хода часов. Отставание на один час в сутки - это слишком. Рекомендую использовать модуль на основе высокоточного чипа DS3231, который снабжён термометром для корректирования хода часов в зависимости от температуры. Точность хода часов этого чипа находится на уровне хороших наручных часов и составляет 2ppm при температуре окружающей среды 0°-40°. При этом, модуль совместим со всеми библиотеками, написанными для модуля на основе чипа DS1307. Статья рассказывает о подключении модуля к Arduino и взаимодействии с ними с помощью библиотеки Time. Купить такой модуль у проверенного мной продавца вы можете .

Подключение часов реального времени

Часы подключаются по протоколу I2C всего двумя проводами. Необходимо дополнительно подтянуть выводы, к которым подключаются часы к рельсе питания с помощью резисторов 2 КОм. Выводы часов выглядят так:

Выводы 32К и SQW можно игнорировать. Их назначение не рассматривается в этой статье. SCL и SDA - это выводы интерфейса I2C. Их и нужно подключать к контроллеру. VCC и GND - +5 В и земля соответственно.

SCL и SDA на разных платах расположены на разных выводах:

Uno, Nano A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)

Вывод SDA часов подключается к выводу SDA контроллера. SDL часов, соответственно, к SDL контроллера. После подключения проводов, должна получиться такая картина:

Работать с модулем часов реального времени удобней всего с помощью библиотеки. Наиболее удобная в этом плане, так и называется: Time (англ. время ).
Библиотека является «обёрткой» для другой популярной библиотеки для работы с модулем часов: DS1307RTC. Несмотря на то, что библиотека разработана для чипа DS1307, она прекрасно работает и с DS3231, так как протоколы взаимодействия совместимы.

Скачайте обе библиотеки.

После скачивания, поместите содержимое архивов в папку libraries, которая находится в папке со средой разработки Arduino. Запустите среду Arduino IDE и откройте стандартный пример библиотеки: Примеры->Time->TimeRTC
Или просто скопируйте этот код:

#include #include #include void setup() { Serial.begin(9600); while (!Serial) ; // wait until Arduino Serial Monitor opens setSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()!= timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time"); } void loop() { if (timeStatus() == timeSet) { digitalClockDisplay(); } else { Serial.println("The time has not been set. Please run the Time"); Serial.println("TimeRTCSet example, or DS1307RTC SetTime example."); Serial.println(); delay(4000); } delay(1000); } void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print("0"); Serial.print(digits); }

#include

#include

#include

void setup () {

Serial . begin (9600 ) ;

while (! Serial ) ; // wait until Arduino Serial Monitor opens

setSyncProvider (RTC . get ) ; // the function to get the time from the RTC

if (timeStatus () != timeSet )

Serial . println ("Unable to sync with the RTC" ) ;

else

Serial . println ("RTC has set the system time" ) ;

void loop ()

if (timeStatus () == timeSet ) {

digitalClockDisplay () ;

} else {

Serial . println ("The time has not been set. Please run the Time" ) ;

Serial . println ("TimeRTCSet example, or DS1307RTC SetTime example." ) ;

Serial . println () ;

delay (4000 ) ;

delay (1000 ) ;

void digitalClockDisplay () {

// digital clock display of the time

Serial . print (hour () ) ;

printDigits (minute () ) ;

printDigits (second () ) ;

Serial . print (" " ) ;

Serial . print (day () ) ;

Serial . print (" " ) ;

Serial . print (month () ) ;

Serial . print (" " ) ;

Serial . print (year () ) ;

Serial . println () ;

void printDigits (int digits ) {

// utility function for digital clock display: prints preceding colon and leading 0

Serial . print (":" ) ;

if (digits < 10 )

Serial . print ("0" ) ;

Serial . print (digits ) ;

После загрузки скетча в плату запустите монитор порта (Сервис->монитор порта). Вы увидите сообщения от библиотеки. Отображаемое время будет неверным, либо библиотека вовсе пожалуется на не настроенные часы. Для настройки часов загрузите в плату пример из библиотеки DS1307RTC «SetTime» (Примеры->DS1307RTC->SetTime). Загрузите этот пример в плату. После загрузки часы окажутся настроенными на время компиляции скетча . Задержка между компиляцией и полной загрузкой составит совсем немного, чего окажется достаточно для точно настроенных часов. Но если вы отключите и заново подключите питание платы, даже через несколько часов, время в часах всё равно будет заново установлено на время компиляции и окажется неверным. Поэтому, используйте этот пример только для настройки, после настройки отключите часы или загрузите в плату другой скетч.

Сегодня мы попробуем с помощью библиотеки HAL поработать с шиной I2C .

Заранее определимся, что по данной шине мы подключим микросхему часов реального времени DS3231 .

Сначала немного поговорим о самой шине I2C.

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

Шина I2C — это шина, управляемая по двум проводам и по определённому протоколу.

Первый провод — SDA (Serial DAta)) , а второй — SCL (Serial CLock) . Данные в основном передаются по проводу SDA. Второй провод в основном для тактирования,

Передача всегда начинается с формирования ведущим устройством условия СТАРТ на данной шине. Оно формируется формированием отрицательного фронта на шине SDA, а затем отрицательного фронта на шине SCL

В конце любой полной посылки генерируеся условие СТОП , которое, наоборот, сначала требует положительного фронта на SCL, а затем на SDA.

На шину I2C можно теоретически навешать до 127 устойств за счёт того, что у каждого устройства существует свой 7-битный адрес, который после условия СТОП Мастер (ведущий) передает в шину. И на этот адрес уже откликается только то SLAVE (ведомое) устройство, адрес которого был передан. После адреса передаётся бит. определяющий каким именно образом мы собираемся общаться с ведомым устройством, то есть читать данные мы с него будем или в него писать. Дальше уже Мастер ждёт подтверждение от ведомого, ведомый должен опустить шину SDA на низкий уровень, и, если это передача, то начинает соответствующим образом данные передавать, а если приём, то принимать.

Как именно и в каком порядке побайтно и побитно осуществляется приём и передача, мы, как правило, смотрим уже в технической документации на устройство, которое мы подключаем. Там могут быть ещё адреса ячеек памяти и регистров, они могут быть 16 и 8 битные и много ещё чего.

Также стоит упомянуть о том, что провода данной шины, можно сказать, висят в воздухе, так как используется открытый коллектор, и их, поэтому, необходимо подтянуть к шине питания через резистор сопротивлением 4,7 — 10 килоом. Также можно это сделать и программно. Причем данного номинала мы должны придерживаться не на каждом устройстве, если их несколько, а на всей шине. То есть, если мы подключили 10 устройств с разными адресами, то подтягивающие резисторы мы оставим только на одном из них, а на остальных придётся их выпаять, чтобы они не параллелились.

Преждем чем перейти именно к разбору микросхемы 3231, мы ещё должны знать, как именно организована шина I2C на нашем контроллере.

Во первых, частота передачи данных или битрейт поддерживается контроллером 100 кГц и 400 кГц. Какую именно выбирать, мы уже решаем исходя из возможностей подключаемого девайза и из наших требований к передаче данных.

Ну и конечно же стоит подчеркнуть, что шина I2C организована само собой у нашего контроллера STM32F4 аппаратно, причём их там несколько.

Вот блок-схема

Здесь мы видим наши провода SDA и SCL, также существуют регистры, которые мы настраиваем для работы, регистр данных, адресный регистр, также регистр двойного адреса, который поддерживает уже 16-битный адрес, два управляющих регистра — CR1 и CR2, регистры статуса — SR1 и SR2, а также регистр, задающий частоту передачи данных или скорость.

Но, так как мы собрались использовать библиотеку HAL, то нам не придется париться по поводу программирования битов данных регистров и когда именно заносить в регистр адреса и данных те самые данные, и данное бремя библиотека HAL обещает взять на себя.

Поэтому нам необходимо и достаточно лишь только знать, какие именно функции нам и как использовать из этой самой библиотеки.

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

Тем более нам нет смысла рассматривать функции инициализации и деинициализации, так как этим всем занимается кодогенератор Cube MX и, как показала практика, вполне справляется.

А функции, которые нам потребуются в сегодняшнем занятии, мы разберём по мере их написания в коде.

Теперь, собственно, микросхема DS3231. Данная микросхема — это часы реального времени, разработанные компанией Dallas , как я считаю, являющейся самой распространённой у пользователей подобных микросхем.

Данные часы реального времени работают подобно предшественнику DS1307, только очень сильно усовершенствованы. Кварцевый резонатор уже находится внутри и поэтому мы уже его не припаиваем, также здесь реализована очень хорошая термокомпенсация, поэтому точность данных часов просто удивляет. Хотя и есть здесь ещё регистр для поправки хода, но я им никогда не пользовался, так как и без него микросхема обеспечивает прекрасную точность хода.

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

Ну и так же как и все современные RTC, у данной микросхемы очень хорошо организована энергонезависимость от внешних источников. Для этого есть два контакта для подключения резервной литиевой батареи на 3,7 вольт, которая обеспечивает продолжение хода часов при отключении питания. Малое энергопотребление в режиме питания от баттареи обеспечивается тем, что почти весь фукнционал кроме хода часов не работает.

Скорость обмена данными поддерживается данной микросхемой и 100 кГц и 400 кГц.

Теперь про регистры микросхемы. Это о том, что именно может хранить в себе данная микросхема

Вот их сколько, этих регистров.

00h — секунды. Секунды хранятся в двоично-десятичном виде. То есть в младших 4 битах хранятся единицы секунд, а в более старших трёх — десятки.

01h — минуты. Хранятся аналогично.

02h — более универсальный регистр. Здесь хранятся часы. В четырех младших битах — единицы чаов, в следующих более старших двух — десятки, в следующем 6 бите — флаг того, после полудня сейчас время или до полудня, в 7 бите — режим хранения — 12- часовой или 24-часовой.

03h — день недели. Хранится в младших 3 битах, остальные биты не используются.

04h — здесь хранится день месяца, также в двоично-десятичном формате. В четыреё малдших битах — единицы, в двух следующих постарше — десятки, следующий бит не используется.

05h — номер месяца в году — хранится в двоично-десятичном формате точно также, как и часы. Самый последний бит автоматически установится, когда закончатся последние сутки века и начнётся следующий век. Смех да и только. Я думаю в нём можно хранить единицу, она будет говорить о том что у нас на дворе 21 век.

06h — номер года, причём не полный четырёхзначный, а только двузначный. В младших четырех битах — единицы, в старших — десятки. А какой век подразумевать, можно хранить в 7 бите месяца.

Вот этими семью регистрами мы и будем пользоваться. Дальше идут регистры будильников, а последние два регистра — это температура, измеряемая на термодатчике, который установлен в микросхему. По идее, можно данным регистром воспользоваться, чтобы выводить показания температуры, хотя это и температура микросхемы. Но термокомпенсация так устроена, что если вдруг микросхема начнет греться, то в ней начнут работать технологии, предотвращающие это, и она остынет. Я пробовал считывать данный регистр, и. в принципе это была температура окружающего воздуха.

Также существуют ещё два регистра управления и статусов. В рамках данного занятия мы ими пользоваться не будем, но техническую документацию на микросхему я прикреплю на странице внизу и вы, скачав её, можете почитать и воспользоваться битами данных регистров.

Теперь, собственно, передача данных:

Это передача данных.

Сначала СТАРТ, затем 7-битный адрес, затем 0, который означает, что мы будем писать в данную микросхему, затем бит подтверждение, затем адрес регистра, которые мы рассмотрели только что выше, опять подтверждение, зтем сами данные, причем можно передавать сразу несколько. Подтверждения ждём после каждого переданного байта, а в конце условие СТОП. Так что мы спокойно можем при установке времени, передать сразу байты всех семи регистров, передав перед этим байт самого первого из них, то есть 0x00.

Теперь чтение

Вообще, это документация для самого ведущего устройства, у ведомого немного не так.

Перед тем как воспользоваться этой диаграммой, мы сначала делаем СТАРТ, затем адрес устройства, затем бит записи, именно записи, затем адрес регистра, затем повторный СТАРТ, затем опять адрес устройсва, затем бит чтения или 1, затем уже ждём данные с подтверждениями, а чёрточка над буквой A после последнего принятого байта означает, что мы подтверждения не ждем или ждём условия «Нет подтверждения», то есть шина SDA установится в высокое состояние и в конце СТОП.

Вот так. Конечно библиотека HAL лишит нас удовольствия поиграться с данными алгоритмами приема и передачи, так как она это будет делать сама. Но, я думаю, мы уже наигрались с этим в уроках по AVR и с микросхемой EEPROM и с микросхемой DS1307.

Вот типовая схема подключения данной микросхемы к контроллеру

Здесь мы видим, что восемь ножем соединяются с корпусом, также есть ножки SDA и SCL, ножки питания VCC и GND, RST для перезагрузки микросхемы, мы данной ножкой не пользуемся. Ещё есть ножка для подключения батарейки VBAT, выход SQW для того, чтобы мы могли брать импульсы определенной частоты с данной микросхемы для какой-нибудь синхронизации, мы эту ножку как правила используем для мигания двоеточия. Также частотой на данной ножке можно управлять определенными битами в определенном регистре. А также ещё выход 32 кГц.

Чуть не забыли про адрес, по которому бы обязаны будем обращаться к устройству. Не зная его, мы не сможем общаться с микросхемой, так как она нам просто не ответит

Адрес у нас получается 0b1101000 . Соответственно, в функциях мы его будем использовать в сдвинутом на 1 бит влево состоянии, то есть сразу с прицепленным нулём. означающим запись, причем в функциях. предназначенных для чтения мы также будем использовать бит 0, а функция там сама всё как надо сдвинет, так уж они устроены, эти функции HAL. То есть адрес у нас будет 0xD0 .

Вот схема подключения (нажмите на картинку для увеличения изображения)

Здесь несколько другая микросхема, но подключение ничем не отличается. Просто не нашел я именно такую микросхему в программе-редакторе электронных схем.

Также ещё скажу, что у меня не просто микросхема, а именно готовый модуль, причем сразу с батарейкой и со всеми выведенными наружу контактами, ссылка на продавца есть под видеоверсией урока в описании.

Модуль выглядит вот так

Точно также как и раньше проект создаем из предыдущего. Новый проект называется MYDS3231

Запускаем его в Cube. Включаем там шину I2C1 вот таким вот образом

Мы также увидим справа в виртуальном контроллере. что у нас появились задействованные ножки портов

Купил я на Aliexpress плату Tiny RTC I2C Modules за 30 рублей.


Очень полезным девайсом оказалась плата Tiny RTC I2C Modules. Как только представлю картину с подключением на макетной плате двух микросхем с обвязкой, то становится немного не по себе от количества ненадежных соединений. Плату Tiny RTC I2C Modules очень удобно использовать для работы с микросхемой ds1307Z часов реального времени с последовательным интерфейсом I2C, микросхемой памяти 24С32 с последовательным интерфейсом I2C, возможностью установить датчик температуры ds18b20. Так же можно получить точные прямоугольные импульсы c 7-го вывода микросхемы ds1307Z, на разъёме он отмечен буквами SQ. На схеме платы Tiny RTC I2C Modules трудно увидеть, что седьмой вывод микросхемы ds1307Z соединен с седьмым контактом разъёма Р1.
Схема платы Tiny RTC I2C Modules:


Перед покупкой я поискал информацию в сети интернет. Узнал, что плата изготовлялась для работы литиевым аккумулятором, который трудно купить. Покупатели платы Tiny RTC I2C Modules устанавливали в плату вместо аккумулятора литиевую батарею, и плата работала неправильно. Микросхема потребляет очень мало энергии, поэтому плату вполне можно использовать с литиевой батареей. Для этого надо выпаять с платы Tiny RTC I2C Modules следующие радиодетали: диод D1, резистор R4, а в место R6 запаять перемычку. Я удалил еще и резистор R7, ознакомившись с типовой схемой включения микросхемы ds1307.


Типовая схема включения микросхемы ds1307:


Подробнее о доработке платы Tiny RTC I2C Modules вы можете узнать из видео, записанного и опубликованного в сети товарищем Алексеем Букреевым.
Даташит на микросхему ds1307:
Я соединил плату Arduino Pro Mini с платой Tiny RTC I2C Modules и плату Arduino Pro Mini с платой USB serial adapter CH340G.




Запускаем код для определения адресов микросхем ds1307 и 24С32. Код опубликован на странице:
http://adatum.ru/skaner-shiny-i2c-dlya-arduino.html
Сам код:
#include String stringOne; void setup() { Wire.begin(); Serial.begin(9600); while (!Serial); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { String stringOne = String(address, HEX); Serial.print("0x"); Serial.print(stringOne); Serial.print(" - "); if(stringOne=="0A") Serial.println(""Motor Driver""); if(stringOne=="0F") Serial.println(""Motor Driver""); if(stringOne=="1D") Serial.println(""ADXL345 Input 3-Axis Digital Accelerometer""); if(stringOne=="1E") Serial.println(""HMC5883 3-Axis Digital Compass""); if(stringOne=="5A") Serial.println(""Touch Sensor""); if(stringOne=="5B") Serial.println(""Touch Sensor""); if(stringOne=="5C") Serial.println(""BH1750FVI digital Light Sensor" OR "Touch Sensor"); if(stringOne=="5D") Serial.println(""Touch Sensor""); if(stringOne=="20") Serial.println(""PCF8574 8-Bit I/O Expander" OR "LCM1602 LCD Adapter" "); if(stringOne=="21") Serial.println(""PCF8574 8-Bit I/O Expander""); if(stringOne=="22") Serial.println(""PCF8574 8-Bit I/O Expander""); if(stringOne=="23") Serial.println(""PCF8574 8-Bit I/O Expander" OR "BH1750FVI digital Light Sensor""); if(stringOne=="24") Serial.println(""PCF8574 8-Bit I/O Expander""); if(stringOne=="25") Serial.println(""PCF8574 8-Bit I/O Expander""); if(stringOne=="26") Serial.println(""PCF8574 8-Bit I/O Expander""); if(stringOne=="27") Serial.println(""PCF8574 8-Bit I/O Expander" OR "LCM1602 LCD Adapter ""); if(stringOne=="39") Serial.println(""TSL2561 Ambient Light Sensor""); if(stringOne=="40") Serial.println(""BMP180 barometric pressure sensor""); if(stringOne=="48") Serial.println(""ADS1115 Module 16-Bit""); if(stringOne=="49") Serial.println(""ADS1115 Module 16-Bit" OR "SPI-to-UART""); if(stringOne=="4A") Serial.println(""ADS1115 Module 16-Bit""); if(stringOne=="4B") Serial.println(""ADS1115 Module 16-Bit""); if(stringOne=="50") Serial.println(""AT24C32 EEPROM""); if(stringOne=="53") Serial.println(""ADXL345 Input 3-Axis Digital Accelerometer""); if(stringOne=="68") Serial.println(""DS3231 real-time clock""); if(stringOne=="7A") Serial.println(""LCD OLED 128x64""); if(stringOne=="76") Serial.println(""BMP280 barometric pressure sensor""); if(stringOne=="77") Serial.println(""BMP180 barometric pressure sensor" OR "BMP280 barometric pressure sensor""); if(stringOne=="78") Serial.println(""LCD OLED 128x64""); nDevices++; } else if (error==4) { Serial.print("Unknow error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); }

После запуска Arduino IDE, выбора модели платы arduino, установки последовательного порта (com31 у меня), а скопировал выше - расположенный код в окно с заменой текста. Запустил компиляцию, при этом Arduino IDE попросит сохранить папку скетча. Нажимаем на сохранение, и Arduino IDE выполнит компиляцию. Запишем программу в плату arduino и в мониторе последовательного порта увидим следующее:


Итак, мы убедились в правильности подключения плат.
Теперь для работы с микросхемой реального времени (ds1307) надо установить библиотеку «Универсальная библиотека iarduino_RTC.zip»
Файл: Универсальная библиотека iarduino_RTC.zip:
После установки библиотеки и перезагрузки Arduino IDE запускаем пример gettime:

Подсчет реального времени в секундах, минутах, часах, датах месяца, месяцах, днях недели и годах с учетом высокосности текущего года вплоть до 2100 г.

56 байт энергонезависимого ОЗУ для хранения данных

2-х проводной последовательный интерфейс

Программируемый генератор прямоугольных импульсов. Может выдавать 1 ГЦ, 4.096 кГЦ, 8,192 кГЦ и 32,768 кГц.

Автоматическое определение отключения основного источника питания и подключение резервного

24-х часовой и 12-ти часовой режим

Потребление не более 500 нA при питании от резервной батареи питания при температуре 25C°

Микросхема выпускается в восьмипиновых DIP и SOIC корпусах. Распиновка для всех одинакова. Далее приведу строки из даташита для полноты картины.

Документация на микросхему (datasheet)

Назначение выводов:

. X1, X2 - Служат для подключения 32.768 кГц кварцевого резонатора

. Vbat - Вход для любой стандартной трёхвольтовой литиевой батареи или другого источника энергии. Для нормальной работы DS1307 необходимо, чтобы напряжение батареи было в диапазоне 2.0 ... 3.5 В. Литиевая батарея с ёмкостью 48 мА/ч или более при отсутствии питания будет поддерживать DS1307 в
течение более 10 лет при температуре 25°C.

. GND - общий минус

. Vcc - Это вход +5 В. Когда питающее напряжение выше 1.25 * VBAT, устройство полностью,доступно, и можно выполнять чтение и запись данных. Когда к устройству подключена батарея на 3 В, и Vcc ниже, чем 1.25 * VBAT, чтение и запись запрещены, однако функция отсчёта времени продолжает работать. Как только Vcc падает ниже VBAT, ОЗУ и RTC переключаются на батарейное питание VBAT.

. SQW/OUT - Выходной сигнал с прямоугольными импульсами.

. SCL - (Serial Clock Input - вход последовательных синхроимпульсов) - используется для синхронизации данных по последовательному интерфейсу.

. SDA - (Serial Data Input/Output - вход/выход последовательных данных) - вывод входа/выхода для двухпроводного последовательного интерфейса.

Работа с выводом SQW/OUT .

Для начала рассмотрим структуру регистров DS1307.

Структура регистров микросхемы DS1307

Нас интересует "Управляющий регистр" находящийся по адресу 0x7, т.к. он определяет работу вывода SQW/OUT.

Если бит SQWE = 1. то начинается формирование прямоугольных импульсов, если SQWE = 0, то на выходе вывода будет значение бита OUT.

За частоту импульсов отвечают биты RS0 и RS1, а именно:

RS0 RS1 Частота
0 0 1 Гц
0 1 4.096 кГц
1 0 8.192 кГц
1 1 32.768 кГц

Приведем пример:

Если нам нужно начать формирование прямоугольных импульсов с частотой 1 Гц, то необходимо в 0x7 регистр микросхемы, которая имеет адрес 0x68 отправить байт 00010000 или 0x10 в шестнадцатиричной системе счисления.

При помощи библиотеки Wire.h , это можно сделать следующим образом:

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

Подключение к Arduino:

Выводы отвечающие за интерфейс I2C на платах Arduino на базе различных контроллеров разнятся.

Необходимые библиотеки:

для работы с DS1307: http://www.pjrc.com/teensy/td_libs_DS1307RTC.html
для работы со временем: http://www.pjrc.com/teensy/td_libs_Time.html

Установка времении

. Вручную в коде

Время задается вручную в программном коде и заливается в плату Arduino. Данный способ не самый точный т.к. время на компиляцию и загрузку может занимать различный временной промежуток.

Пример программного кода

#include #include void setup () { Serial .begin (9600); while (!Serial ) ; // Только для платы Leonardo // получаем время с RTC Serial //синхронизация не удаласть else Serial .println ("RTC has set the system time" ); //установим вручную 16.02.2016 12:53 TimeElements te; te.Second = 0; //секунды te.Minute = 53; //минуты te.Hour = 12; //часы te.Day = 16; //день te.Month = 2; // месяц te.Year = 2016 - 1970; //год в библиотеке отсчитывается с 1970 time_t timeVal = makeTime(te); RTC .set (timeVal); setTime (timeVal); } void loop () { digitalClockDisplay(); //вывод времени delay (1000); } void digitalClockDisplay() { Serial Serial .print (" " ); Serial .print (day ()); Serial .print (" " ); Serial .print (month ()); Serial .print (" " ); Serial .print (year ()); Serial //выводим время через ":" Serial .print (":" ); if (digits < 10) Serial .print ("0" ); Serial .print (digits); }

. Установкой из "Монитора порта"

Более точный вариант установки времени. Время задается через "монитор порта" по ходу работы контроллера.

Открываем монитор, вводим данные в нужном формате, смотрим на эталонные часы, подлавливаем момент и шелкаем "отправить".

Пример программного кода

//формат указания текущего времени "ДД.ММ.ГГ чч:мм:сс" //где ДД - день, ММ - месяц, ГГ - год, чч - часы, мм - минуты, сс - секунлы //ГГ - от 00 до 99 для 2000-2099 годов #include #include bool isTimeSet = false ; //флаг, указывающий на то, была ли уже задана дата void setup () { Serial .begin (9600); while (!Serial ) ; // Только для платы Leonardo setSyncProvider (RTC .get ); // получаем время с RTC if (timeStatus () != timeSet) Serial .println ("Unable to sync with the RTC" ); //синхронизация не удаласть else Serial .println ("RTC has set the system time" ); } void loop () { if (Serial .available ()) { //поступила команда с временем setTimeFromFormatString(Serial .readStringUntil ("\n" )); isTimeSet = true ; //дата была задана } if (isTimeSet) //если была задана дата { digitalClockDisplay(); //вывод времени } delay (1000); } void digitalClockDisplay() { Serial .print (hour ()); printDigits(minute ()); printDigits(second ()); Serial .print (" " ); Serial .print (day ()); Serial .print (" " ); Serial .print (month ()); Serial .print (" " ); Serial .print (year ()); Serial .println (); } void printDigits(int digits) { //выводим время через ":" Serial .print (":" ); if (digits < 10) Serial .print ("0" ); Serial .print (digits); } void setTimeFromFormatString(String time) { //ДД.ММ.ГГ чч:мм:сс int day = time.substring(0, 2).toInt(); int month = time.substring(3, 5).toInt(); int year = time.substring(6, 8).toInt(); int hours = time.substring(9, 11).toInt(); int minutes = time.substring(12, 14).toInt(); int seconds = time.substring(15, 17).toInt(); TimeElements te; te.Second = seconds; te.Minute = minutes; te.Hour = hours; te.Day = day ; te.Month = month ; te.Year = year + 30; //год в библиотеке отсчитывается с 1970. Мы хотим с 2000 time_t timeVal = makeTime(te); RTC .set (timeVal); setTime (timeVal); }