Часы на DS1307 от идеи к реализации. Русское описание DS1307 Микросхема ds1307 описание
Отзывы об этих часах в интернете самые противоречивые. Кто-то говорит что часы замечательные, а кто-то называет их убогой поделкой Далласа. И вот я, дабы развеять все недостоверные слухи, достал микруху из загашника начала экспериментировать.
Особенности:
- Очень маленькое энергопотребление. Производитель обещает 10 лет работы часов от одной стандартной батарейки CR2032
- 56 байт памяти для хранения пользовательских данных. Думаю не особо нужная опция, но может кому-то и пригодится.
- Программируемый вывод для тактирования внешних устройств. Может выдавать 1 Гц, 4.096 кГц, 8.192 кГц и 32.768 кГц.
- 24-х часовой и 12-ти часовой режим
Распиновка
Выводы часов расположены следующим образом:
X1, X2
— Выводы для подключения кварцевого резонатора на частоту 32.768 кГц
VBAT
— Вывод для подключения 3-х вольтовой батареи резервного питания
GND
— Земля
SDA
— линия данных шины i2c
SCL
— линия тактовых импульсов шины i2c
SQW/OUT
– выходной сигнал для тактирования внешних устройств
VCC
— питание 5 вольт
Подключение к контроллеру
Обвязка минимальна. Потребуется кварц 32.768 кГц, пара резисторов для работы шины i2c и батарейка на три вольта.
Правильная разводка платы
Точность хода да и вообще работоспособность часов, зависит от разводки печатной платы. Даллас в своем даташите рекомендует сократить до минимума длинну проводников от микросхемы до кварцевого резонатора и окружить эти проводники прямоугольником подключенным к земле. Кроме этого для надежности я припаял к корпусу кварца проводок идущий к земле и параллельно питанию поставил конденсатор на 0.1 мкф.
Кстати может работать и без кварца. Для этого на ногу X1 подают внешний тактовый сигнал с частотой 32.768 кГц, а X2 остаётся висеть в воздухе.
Организация памяти часов
Данная микруха наделена 64 байтами памяти. Первые восемь байт — рабочие. В них хранится время, дата, день недели. Остальные выделены под нужды пользователя. В них можно хранить например какие-нибудь настройки или еще что-нибудь. Естественно, когда резервное питание пропадает, вся информация в этой памяти разрушается. Вся работа с часами (чтение и установка времени/даты) сводится к тому, чтобы читать и записывать нужные ячейки памяти.
Все числа в памяти хранятся в двоично-десятичном формате. Это значит что в одном байте может хранится сразу две цифры. Например число 0x23 — содержит в себе цифру 2 и цифру 3. На каждую цифру выделяется по 4 бита. Зачем так сделано? Для удобства и экономии памяти. Кроме времени и даты в памяти хранятся несколько бит настроек:
- Clock Halt
— управляет часами. Когда бит установлен то часы стоят. Чтобы запустить ход часов необходимо записать в этот бит 0. После подключения батареи резервного питания, этот бит уставлен и часы не считают время! Об этом нужно помнить. - 24/12
— этот бит выбора режима часов. Когда этот бит равен единице то используется 12-ти часовой режим. В противном случае 24-х часовой. Если используется 12-ти часовой режим то пятый бит показывает AM или PM сейчас. Если бит равен 1 то значит PM. В 24-х часовом режиме этот бит используется для хранения десятков часов совместно с битом 4. - Output
— управляет состоянием ноги SQW/OUT. Бит установлен — на ноге лог 1. Сброшен — на ноге 0. Для управления таким образом, бит SQWE
должен быть сброшен. - SQWE
— когда бит установлен, на ноге SQW/OUT появляются прямоугольные импульсы. - RS1, RS0
— этими битами задается частота импульсов. Зависимость частоты от комбинации бит находится в таблице ниже:
Софт
Для работы с часами DS1307 была написана нехитрая библиотека содержащая следующие базовые функции:
DS_start
— запускает часы. Запустить часы можно так же установив время.
DS_stop
— останавливает часы
DS_set_time —
Установка времени. Перед вызовом процедуры нужно поместить в tmp1 — секунды в tmp2 — минуты и в tmp3-часы. Часы в 24-х часовом формате.
DS_get_time: —
считывание времени из часов. секунды будут записаны в tmp1, минуты в tmp2, часы в tmp3
DS_get_date:
— считывание даты из часов. День будет записан в tmp1, месяц в tmp2, год в tmp3
DS_set_date: —
установка даты. Перед вызовом процедуры нужно поместить в tmp1 — день в tmp2 — месяц и в tmp3-год (последние 2 цифры)
Процедуры установки/чтения времени и даты могут воспринимать/возвращать входные данные в двоично-десятичном формате и в десятичном. Для выбора желаемого формата нужно закомментировать или раскомментировать по три строчки в каждой процедуре (в коде есть примечания по этому поводу).
Тестовая программа позволяет управлять часами через UART (скорость 9600, контроллер работает на частоте 8 мГц). При запуске сразу выдаются время, дата и приглашение ввести команду от 1 до 3. При выборе варианта 1 происходит повторное считывание времени/даты. Вариант 2 позволяет установить время, а вариант 3 дату. Если хочется попробовать поиграть с часами в то в архив с исходником включён файл для симуляции.
Точность
Тут очень многое зависит от применяемого кварца и разводки платы. Даташит сообщает что емкость кварца должна быть 12.5 пф. Говорят, что лучше всего применять кварцы от материнских плат. Для коррекции хода можно подпаять к резонатору подстроечный конденсатором и при помощи него в небольших пределах менять частоту. Лично у меня эти часы работают вторые сутки и отстали на 3 секунды. Что-то мне подсказывает, что дело в ёмкости кварца, попробую другой отпишусь.
Вывод
Неплохие часы. Для любительского применения идеальный вариант. Хотя некоторые пишут о глюках, но я пока не столкнулся.
DS1307
– микросхема часов реального времени с интерфейсом I2C(TWI)
. Часы / календарь хранят следующую информацию: секунды, минуты, часы, день, дату, месяц и год. Конец месяца автоматически подстраивается для месяцев, в которых менее 31 дня, включая поправку для високосного года. Часы работают в 24-часовом или 12-часовом формате с индикатором AM/PM. DS1307 имеет встроенную схему контроля питания, которая обнаруживает пропадание питания и автоматически переключает схему на питание от батареи.
Vbat
– вход батареи для любого стандартного 3 Вольтового литиевого элемента или другого источника энергии. Для нормальной работы напряжение батареи должно поддерживаться между 2.5 и 3.5 В. Уровень, при котором запрещён доступ к часам реального времени и пользовательскому ОЗУ, установлен внутренней схемой равным 1.25 x Vbat. Литиевая батарея ёмкостью 35 mAh или больше достаточна для питания DS1307 в течение более чем 10 лет при отсутствии питания.
SCL
(Последовательный Тактовый Вход) – SCL используется, чтобы синхронизировать передачу данных через последовательный интерфейс.
SDA
(Вход/Выход Последовательных Данных) – SDA – вход / выход данных для 2-проводного последовательного интерфейса. Это выход с открытым стоком, который требует внешнего притягивающего резистора.
SQW/OUT
(Меандр / Выходной Драйвер) – Когда бит SQWE установлен в 1, на выходе SQW/OUT вырабатываются импульсы в форме меандра одной из четырех частот: 1 Гц., 4 кГц., 8 кГц., 32 кГц. Вывод SQW/OUT – с открытым стоком, требует внешнего притягивающего резистора.
X1, X2
– выводы для подключения стандартного кристалла кварца 32.768 кГц. Внутренняя схема генератора рассчитана на работу с кристаллом, имеющим номинальную емкость (CL) 12.5 пФ.
GND
– Земля.
VCC
– питание 5 вольт.
DS1307
работает как ведомое устройство на последовательной шине. Для доступа к нему надо установить состояние START
и передать код идентификации устройства, сопровождаемый адресом регистра. К последующим регистрам можно обращаться последовательно, пока не установлено состояние STOP
. Когда VСС
падает ниже 1.25 x Vbat, устройство прекращает связь и сбрасывает адресный счетчик. В это время оно не будет реагировать на входные сигналы, чтобы предотвратить запись ошибочной информации. Когда VСС
падает ниже Vbat, устройство переключается в режим хранения с низким потреблением. При включении питания устройство переключает питание с батареи на VСС
, когда напряжение питания превысит Vbat + 0.2V, и реагирует на входные сигналы, когда VСС
станет более 1.25 x Vbat. Когда питание находится в пределах нормы, устройство полностью доступно, и данные могут быть записаны и считаны. Когда к устройству подключена трёхвольтовая батарея и VСС ниже 1.25 x Vbat, чтение и запись запрещены. Однако отсчёт времени при этом работает. Когда VСС
падает ниже Vbat, питание ОЗУ и отсчёта времени переключается на внешнюю батарею 3 В.
Информацию о времени и дате получают, считывая соответствующие регистры. Регистры часов показаны в таблице ниже. Время и календарь устанавливаются или инициализируются путём записи байтов в соответствующие регистры. Содержание регистров времени и календаря хранится в двоично-десятичном (BCD)
формате, поэтому перед выводом информации на LCD дисплей или семисегментный индикатор необходимо преобразовать двоично-десятичный код в двоичный или ANSII – код.
Бит 7 регистра 0 – это бит остановки хода часов (Clock Halt). Когда этот бит установлен в 1, генератор остановлен. Когда сброшен в ноль, генератор работает, а часы считают время.
DS1307 может работать в 12-часовом или 24-часовом режиме. Бит 6 регистра часов задаёт один из этих режимов. Когда он равен 1, установлен 12-часовой режим. В 12-часовом режиме высокий уровень бита 5 сообщает о послеполуденном времени. В 24-часовом режиме бит 5 – второй бит 10 часов (20-23 часа).
Регистр управления DS1307 предназначен для управления работой вывода SQW/OUT
. Бит OUT
– управление выходом. Этот бит управляет выходным уровнем на выводе SQW/OUT
, когда генерация меандра запрещена. Если SQWE = 0, логический уровень на выводе SQW/OUT
равен 1, если OUT
= 1, и 0 – если OUT
= 0. SQWE
– Разрешение меандра. Когда этот бит установлен в 1, разрешается генерация меандра. Частота меандра зависит от значений битов RS0 и RS1. Эти биты управляют частотой меандра, когда его генерация разрешена. В таблице ниже показаны частоты, которые могут быть заданы RS битами.
DS1307 поддерживает двунаправленные 2-проводную шину и протокол передачи данных. Устройство, которое посылает данные на шину, называется передатчиком, а устройство, получающее данные – приемником. Устройство, которое управляет передачей, называется ведущим. Устройства, которые управляются ведущим – ведомые. Шина должна управляться ведущим устройством, которое вырабатывает последовательные такты (SCL), управляет доступом к шине, и генерирует состояния СТАРТ и СТОП. DS1307 работает как ведомое на 2-х проводной шине.
Для работы с DS1307 необходимо организовать функцию чтения из микросхемы и функцию записи.
1. Режим записи в DS1307
. Последовательные данные и такты получены через SDA и SCL. После передачи каждого байта передаётся подтверждающий бит ASK
. Состояния START
и STOP
опознаются как начало и конец последовательной передачи. Распознавание адреса выполняется аппаратно после приема адреса ведомого и бита направления. Байт адреса содержит семибитный адрес DS1307, равный 1101000, сопровождаемым битом направления (R/W), который при записи равен 0. После получения и расшифровки байта адреса DS1307 выдаёт подтверждение ASK
на линии SDA. После того, как DS1307 подтверждает адрес ведомого и бит записи, ведущий передает адрес регистра DS1307. Тем самым будет установлен указатель регистра в DS1307. Тогда ведущий начнет передавать байты данных в DS1307, который будет подтверждать каждый полученный байт. По окончании записи ведущий сформирует состояние STOP
.
2. Режим чтения из DS1307
. Первый байт принимается и обрабатывается как в режиме ведомого приёмника. Однако в этом режиме бит направления укажет, что направление передачи изменено. Последовательные данные передаются по SDA от DS1307, в то время как последовательные такты – по SCL в DS1307. Состояния START
и STOP
опознаются как начало и конец последовательной передачи. Байт адреса – первый байт, полученный после того, как ведущим сформировано состояние START
. Байт адреса содержит семибитный адрес DS1307, равный 1101000, сопровождаемым битом направления (R/W), который при чтении равен 1. После получения и расшифровки байта адреса DS1307 выдаёт подтверждение ASK
на линии SDA. Тогда DS1307 начинает передавать данные, начинающиеся с адреса регистра, на которые указывает указатель регистра. Если указатель регистра не записан перед инициированием режима чтения, то первый адрес, который читается – это последний адрес, оставшийся в указателе регистра. DS1307 должен получить неподтверждение NOASK
, чтобы закончить чтение.
Рассмотрим особенности работы с DS1307 на примере простых часов, которые будут показывать часы, минуты и секунды. Данные будут выводиться на LCD дисплей 16х2. Две кнопки “Часы+” и “Минуты+” позволят подвести нужное время. Микроконтроллер Atmega 8 тактируется от внутреннего генератора частотой 1 MHz, поэтому не забудьте поменять фьюзы. Ниже представлена схема подключения.
Управляющая программа включает в себя наборы функций работы с шиной TWI, часами DS1307, LCD дисплеем.
I2CInit – инициализация шины;
I2CStart – передача условия START;
I2CStop – передача условия STOP;
I2CWriteByte – запись данных;
I2CReadByte – чтение данных;
DS1307Read – функция чтения данных из DS1307;
DS1307Write – Функция записи данных в DS1307;
lcd_com – передача команды в LCD;
lcd_data – передача данных в LCD;
lcd_string – функция вывода строки в LCD;
lcd_num_to_str – функция вывода символа типа int;
lcd_init – инициализация LCD.
Ниже представлен код программы:
#include
#include
// Функция инициализация шины TWI
void I2CInit(void)
{
TWBR = 2; // Настройка частоты шины
TWSR = (1 > 4)*10)+(temp & 0x0F);
DS1307Read(0x01,&temp); // Чтение регистра минут
minute = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
DS1307Read(0x02,&temp); // Чтение регистра часов
hour = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
lcd_com(0xC4);
lcd_num_to_str(hour, 2); // Выводим на экран часы
lcd_com(0xC7);
lcd_num_to_str(minute, 2); // Выводим на экран минуты
lcd_com(0xCA);
lcd_num_to_str(second, 2); // Выводим на экран секунды
if((PINC & (1 23) hour = 0;
// Преобразуем из двоичной системы в BCD и записываем в DS1307
uint8_t temp;
temp = ((hour/10) 59) minute = 0;
// Преобразуем из двоичной системы в BCD и записываем в DS1307
uint8_t temp;
temp = ((minute/10)
Тема часов на микросхеме DS1307 довольно актуальна — это простое, но в то же время интересное устройство. Кроме того, оно может реально пригодиться. Но описывать отдельно микросхему смысла нет, поэтому я решил собрать себе подобное устройство, заодно рассказать о том, какие шишки набил при этом. Сам процесс разработки и сборки буду описывать, по мере прохождения некоторых этапов готовности девайса.
Update 17.10.2015
Вначале это была серия статей, целью которых было рассказать про создание устройства с нуля до состояния готовности, но внезапно у меня появилась аллергия на все что называется «часы», поэтому я слил все в одну статью. Устройство закончено на 99.9%, (осталось закрутить винты), но сделать это ой как не просто 🙂 Как только аллергия пройдет появится окончательная фотка.
Начнем с того, что пока нам ничего не известно про ds1307 кроме того, что с ее помощью делают часы. Поэтому качаем документацию, на эту микросхему и читаем список «вкусностей», которыми она обладает. Итак, из первого абзаца в целом понятно, что она обладает низким энергопотреблением, информация передается по I2C, можно узнать дату и время, 12 и 24 часовой формат, автоматическая подстройка даты. Но самое интересное это схема (TYPICAL OPERATING CIRCUIT).
Курим даташит и пытаемся разобраться что к чему. Идем слева направо, CPU — микроконтроллер (то есть наша atmega), два резистора, написано pull up — значит подтягивающие (можно взять по 10к), кварц на 32768Гц, сама микросхема и батарейка. Выход SQW/OUT может дрыгаться с частотой 1Hz, 4kHz, 8kHz, 32kHz, пока нам это не интересно. Пожалуй, этой информации пока достаточно, хочется уже чего нибудь накодить 🙂
Создаем проект в CodeVision, в разделе I2C находим ds1307 и включаем его в проект. Хорошо бы еще выводить куда нибудь информацию, например на LCD и пара кнопок не помешает.
Все что нужно это LCD настроить на порт D и три кнопки с подтяжкой на вход. Далее нужно вывести на LCD время, для этого заглянем в мануал CodeVision и возьмем оттуда пример. Оказывается все просто — есть функция устанавливающая время:
rtc_set_time(3,0,0); //установить 03:00:00
т.е. после вызова данной функции в переменных h, m, s будут находиться часы(h), минуты(m) и секунды(s). Осталось вывести их на экран. Уж это мы умеем делать)
Итоговый код будет выглядеть так:
#include #include #include #include .equ #include char void { char PORTC= DDRC= // I2C Bus initialization i2c_init() rtc_init(0 // LCD module initialization lcd_init(16 rtc_set_time(3 while { rtc_get_time(& lcd_clear() lcd_gotoxy(0 sprintf lcd_puts(lcd_buf) delay_ms(500 } } |
#include
#include
#include
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include
char lcd_buf;
void main(void)
{
char hour,min,sek;
PORTC=0x07;
DDRC=0x00;
// I2C Bus initialization
i2c_init();
// DS1307 Real Time Clock initialization
rtc_init(0,0,0);
// LCD module initialization
lcd_init(16);
rtc_set_time(3,0,0);
while (1)
{
rtc_get_time(&hour,&min,&sek);
lcd_clear();
lcd_gotoxy(0,0);
sprintf(lcd_buf,”%2d:%02d:%02dn”,hour,min,sek);
lcd_puts(lcd_buf);
delay_ms(500);
};
}
Собираем и тестируем в протеусе:
Схема и прошивка
Продолжим модернизировать нашу прошивку. Начнем со следующей задумки: у DS1307 есть выход SQW/OUT, который может генерировать несколько частот. Если настроить этот выход на 1Гц, и подать этот сигнал на вход внешнего прерывания, то получится, что раз в секунду 1307 будет дергать «за хвост» нашу atmega8. Для меги это будет сигналом к тому, что пора обновлять время. Это позволит не нагружать микроконтроллер постоянным обновлением времени, информация о текущем времени будет обновляться ровно раз в секунду.
Добавим в проект внешнее прерывание по низкому уровню (low level) на ножке Int1 и включим подтяжку. Выход DS1307 настроим на частоту 1Гц. Кстати, читать мануалы полезно, нашел интересную особенность — подтягивающие резисторы на ножках SCL, SDA должны быть 3,3k — 4,7k. Учтем это.
Получившийся код будет выглядеть так:
interrupt [ EXT_INT1] void ext_int1_isr(void ) { time_flag= } |
interrupt void ext_int1_isr(void)
{
time_flag=1;
}
В прерывании выставляем флаг, разрешающий вывод времени, в основном цикле, если флаг выставлен, то показываем время, если не выставлен ничего не делаем.
if (time_flag== 1 ) { rtc_get_time(& lcd_gotoxy(0 sprintf lcd_puts(lcd_buf) } |
if(time_flag==1)
{
rtc_get_time(&hour,&min,&sek);
lcd_gotoxy(0,0);
sprintf(lcd_buf,”%02d:%02d:%02dn”,hour,min,sek);
lcd_puts(lcd_buf);
}
Теперь перейдем к следующему вопросу, на сколько эффективно использовать sprintf? Чтобы не разводить пустых разговоров, приведу 2 куска кода, которые выполняют одно и тоже — выводят информацию о времени на дисплей.
Первый вариант, уже нам известный:
sprintf (lcd_buf, “%02d:%02d:%02dn ” , hour, min, sek) ; lcd_puts(lcd_buf) |
sprintf(lcd_buf,”%02d:%02d:%02dn”,hour,min,sek);
lcd_puts(lcd_buf);
Согласитесь просто в использовании и наглядно. Теперь вариант номер 2:
lcd_putchar(hour/ 10 + 0x30 ) ; lcd_putchar(hour% lcd_putchar(“:” lcd_putchar(min/ lcd_putchar(min% lcd_putchar(“:” lcd_putchar(sek/ lcd_putchar(sek% |
lcd_putchar(hour/10+0x30);
lcd_putchar(hour%10+0x30);
lcd_putchar(“:”);
lcd_putchar(min/10+0x30);
lcd_putchar(min%10+0x30);
lcd_putchar(“:”);
lcd_putchar(sek/10+0x30);
lcd_putchar(sek%10+0x30);
Не очень наглядно, но разобраться можно. Как мы их будем сравнивать? Делается это очень просто — запускаем отладчик AVR STUDIO и смотрим количество тактов затраченных на их выполнение. Итак, «барабанная дробь», результаты… Первый кусок кода выполнялся 16 466 тактов, что равносильно 2 058,25 мкс, при рабочей частоте в 8МГц, для второго куска кода эта цифра составила 12 278 тактов или 1 534,75 мкс. Согласитесь, снизить время выполнения, а значит и разгрузить микроконтроллер на ~25% достаточно весомая причина, чтобы не использовать sprintf. Выкидываем sprintf из нашего проекта, в след за ним можно выкинуть stdio.h и lcd_buf.
Некрасиво, когда в основном цикле мешанина из кода, поэтому вывод информации можно засунуть в функцию. В основном цикле останется
while (1 ) { if { show_time() } |
while (1)
{
if(time_flag==1)
{
show_time(); //показать информацию о текущем времени
}
};
Объявление самой функции будет выглядеть так:
void show_time() { rtc_get_time(& lcd_gotoxy(0 lcd_putchar(hour/ lcd_putchar(hour% lcd_putchar(“:” lcd_putchar(min/ lcd_putchar(min% lcd_putchar(“:” lcd_putchar(sek/ lcd_putchar(sek% time_flag= } |
void show_time()
{
rtc_get_time(&hour,&min,&sek);
lcd_gotoxy(0,0);
lcd_putchar(hour/10+0x30);
lcd_putchar(hour%10+0x30);
lcd_putchar(“:”);
lcd_putchar(min/10+0x30);
lcd_putchar(min%10+0x30);
lcd_putchar(“:”);
lcd_putchar(sek/10+0x30);
lcd_putchar(sek%10+0x30);
time_flag=0;
}
Теперь в нашу прошивку, нужно добавить вывод даты. Установка даты, производится следующей функцией:
rtc_set_date(6,13,10,13); //6- день недели, 13 – день, 10 – месяц, 13 – год
rtc_get_date(&week_day,&day,&month,&year); //день недели, день, месяц, год
Вывод даты можно организовать, пока что в основном цикле, рядом со временем, полный исходный код получился такой:
#include // I2C Bus functions #asm .equ .equ #endasm #include // Alphanumeric LCD functions #include char bit time_flag= char // External Interrupt 1 service routine { time_flag= } void { rtc_get_time(& rtc_get_date(& lcd_gotoxy(0 lcd_putchar(hour/ lcd_putchar(hour% lcd_putchar(“:” lcd_putchar(min/ lcd_putchar(min% lcd_putchar(“:” lcd_putchar(sek/ lcd_putchar(sek% lcd_gotoxy(0 lcd_putchar(day/ lcd_putchar(day% lcd_putchar(“/” lcd_putchar(month/ lcd_putchar(month% lcd_putchar(“/” lcd_putchar(year/ lcd_putchar(year% time_flag= } void { PORTC= DDRC= PORTD= DDRD= // I2C Bus initialization i2c_init() // DS1307 Real Time Clock initialization rtc_init(0 // External Interrupt(s) initialization // INT1: On // INT1 Mode: Low level GICR|= MCUCR= GIFR= // LCD module initialization lcd_init(16 rtc_set_time(12 rtc_set_date(6 #asm(“sei”) while { if { show_time() } } } |
#include
// I2C Bus functions
#asm
.equ __i2c_port=0x18 ;PORTB
.equ __sda_bit=0
.equ __scl_bit=1
#endasm
#include
// DS1307 Real Time Clock functions
#include
// Alphanumeric LCD functions
#include
char hour=0,min=0,sek=0,day=0,month=0,year=0,week_day=0;
bit time_flag=0;
char menu=0;
// External Interrupt 1 service routine
interrupt void ext_int1_isr(void)
{
time_flag=1;
}
void show_time()
{
rtc_get_time(&hour,&min,&sek);
rtc_get_date(&week_day,&day,&month,&year);
lcd_gotoxy(0,0);
lcd_putchar(hour/10+0x30);
lcd_putchar(hour%10+0x30);
lcd_putchar(“:”);
lcd_putchar(min/10+0x30);
lcd_putchar(min%10+0x30);
lcd_putchar(“:”);
lcd_putchar(sek/10+0x30);
lcd_putchar(sek%10+0x30);
lcd_gotoxy(0,1);
lcd_putchar(day/10+0x30);
lcd_putchar(day%10+0x30);
lcd_putchar(“/”);
lcd_putchar(month/10+0x30);
lcd_putchar(month%10+0x30);
lcd_putchar(“/”);
lcd_putchar(year/10+0x30);
lcd_putchar(year%10+0x30);
time_flag=0;
}
void main(void)
{
PORTC=0x0F;
DDRC=0x00;
PORTD=0x08;
DDRD=0x00;
// I2C Bus initialization
i2c_init();
// DS1307 Real Time Clock initialization
// Square wave output on pin SQW/OUT: On
// Square wave frequency: 1Hz
rtc_init(0,1,0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Low level
GICR|=0x80;
MCUCR=0x00;
GIFR=0x80;
// LCD module initialization
lcd_init(16);
rtc_set_time(12,0,0);
rtc_set_date(6,13,10,13);
#asm(“sei”)
while (1)
{
if(time_flag==1)
{
show_time();
}
};
}
Результат:
Схема и прошивка:
Перейдем к организации меню. Самый главный вопрос состоял в том, как оно все должно выглядеть, т.е. нужно было сформулировать техническое задание(т.з.).
Мне хотелось, чтобы это были отдельные экраны:
-главный экран;
-экран настройки времени;
-экран настройки даты;
-экран настройки будильника.
При этом обойтись четырьмя кнопками — вверх, вниз, влево, вправо. Переход между экранами должен осуществляться кнопками вверх и вниз. Настройка производится на соответствующем экране. Применяемый микроконтроллер atmega8. Вот такое примитивное т.з.
То что размер кода будет достаточно большой было понятно изначально. При этом нужно было его разбить на логически связанные части. С частями все понятно — обработка одного экрана одна часть кода. Поэтому начал с того, что основной цикл разбил на четыре части, переключения между которыми производится оператором switch. Внутрь засунул функции — пустышки. Кнопки 0(вверх) и 3(вниз) порта C позволяют изменить переменную menu. Таким образом мы скачем между менюшками. Но пока такая прошивка еще работать не могла, ибо функции еще не определены.
while (1 ) { switch { case show_time() break case set_time() break case set_date() break case set_alarm() break } } |
while (1)
{
switch(menu)
{
case 0:
show_time();
break;
case 1:
set_time();
break;
case 2:
set_date();
break;
case 3:
set_alarm();
break;
}
};
Следующий шаг определение этих функций, изначально я нарисовал статичные названия, вроде lcd_puts(«Set time»); функции получились, такими.
void set_alarm()
{
////////просмотр настроек будильника
lcd_gotoxy(0,0);
lcd_puts(“Set alarm”);
}
void set_time()
{
////////просмотр настроек времени
lcd_gotoxy(0,0);
lcd_puts(“Set time”);
}
Теперь это уже была рабочая прошивка, в которой можно было переключаться между менюшками и смотреть статичные надписи. Настало время оживить эти надписи. С главным экраном проблем не было, вывод времени/даты аналогичен предыдущему уроку.
Встал следующий вопрос: как организовать сам процесс настройки? Поразмыслив, мне показалась интересной следующая идея: переходим кнопками вверх/вниз в интересующее нас меню, нажимаем вправо, появляется курсор, говорящий нам о том, что идет процесс настройки. Кнопками вверх/вниз мы изменяем величину, влево/вправо скачем курсором между настраиваемыми параметрами. Когда курсор находится под последним параметром, повторное нажатие кнопки вправо позволяет выйти из настройки. Курсор при этом скрывается, что говорит о том что мы вышли из настройки и можем снова переключаться между менюшками.
Но есть небольшие проблемы, например, кнопка вверх должна изменять параметры и при этом, переключать следующий экран. Т.е. логику кнопок внутри одного экрана, пришлось разделить. Из за этого код здорово разросся. Например, на экране будильника, вводим подпрограмму настройки(sub_alarm), соответственно кнопки внутри подпрограммы обрабатываются одним образом, а вне другим.
void set_alarm() //Функция обработки будильника
{
//режим отображения меню настроек будильника
if(sub_alarm==0)
{
if(PINC.0==0) //кнопка вверх – смена экрана меню
{
menu=0;
…..
}
}
//подменю настройки будильника
if(sub_alarm==1)
{
if(PINC.0==0) //кнопка вверх – увеличить величину
{
a_hour++;
….
}
}
Есть еще такой момент, когда зашли в подменю настройки одна и таже кнопка (возьмем опять в качестве примера кнопку вверх), может менять часы, а может минуты. Поэтому была введена еще одна переменная subProgram.
Например:
if(PINC.0==0) //кнопка вверх
{
if(subProgram==1) //subProgram=1 – изменяем часы
{
a_hour++;
…
}
if(subProgram==2) //subProgram=2 – изменяем минуты
{
a_min++;
…
}
if(subProgram==3) //subProgram=3 изменяем флаг будильника
{
…
}
}
Единственное о чем стоит упомянуть это спецсимвол, который выводится на главном экране, когда будильник включен.
Пример взят из примеров в папке CodeVisionexampleslcd char.
typedef unsigned char byte; //переопределяем тип flash byte char_table[ 8 ] = { //рисуем свой символ 0b10000000 , 0b10000100 0b10001110 0b10001110 0b10001110 0b10011111 0b10100100 0b11000000 // function used to define user characters { byte i, address= while { lcd_putchar(0 |
typedef unsigned char byte; //переопределяем тип
flash byte char_table={ //рисуем свой символ
0b10000000,
0b10000100,
0b10001110,
0b10001110,
0b10001110,
0b10011111,
0b10100100,
0b11000000};
// function used to define user characters
void define_char(byte flash *pc,byte char_code)
{
byte i,address;
address=(char_code
Рисовать можно символ 5х7, единичка — пиксел закрашен, ноль — не закрашен. Получился символ колокольчика.
Прошивка
Следующий шаг, это продумывание внешнего вида устройства. В моем представлении это будет жк экран и четыре кнопки на лицевой части, внутри будет печатная плата на которой будут все остальные элементы. Питание будет от блока питания, аналогично тому что сделан из китайской зарядки.
Начнем с печатной платы, для этого требуется программа, которая позволяет рисовать печатки. Существует множество подобных программ: P-cad, Altium, Sprint layout… Мне нравится Альтиум, только потому, что для него куча готовых библиотек с элементами, ибо тратить время на набивку собственной библиотеки элементов, на мой взгляд не дело. Общий смысл всех подобных программ одинаков — сначала рисуется электрическая схема.
В трассировщике все элементы уже знают, какой с каким должен соединяться, благодаря электрической схеме.
Остается только удобно расположить элементы и соединить их проводниками.
DS1307 это небольшой модуль, предназначенный для подсчета времени. Собранный на базе микросхемы DS1307ZN с реализацией питания от литиевой батарейки (LIR2032), что позволяет работать автономно в течение длительного времени. Также на модуле, установлена энергонезависимая память EEPROM объемом 32 Кбайт (AT24C32). Микросхема AT24C32 и DS1307ZN связаны обшей шиной интерфейсом I2C.
Технические параметры
Напряжение питания: 5В
Рабочая температура: – 40℃ … + 85℃
Память: 56 байт (энергонезависимая)
Батарейка:
LIR2032 (автоматическое определение источника питания)
Интерфейса: I2C
Габариты: 28мм х 25мм х 8 мм
Общие сведения
Использовании модуля DS1307 зачастую очень оправдано, например, когда данные считываются редко, интервалом более недели, использовать собственные ресурсы контроллера, неоправданно или невозможно. Обеспечивание бесперебойное питание, например платы Arduino, на длительный срок дорого, даже при использовании батареи.
Благодаря собственной памяти и автономностью, можно регистрировать события, (при автономном питании) например изменение температуры и так далее, данные сохраняются в памяти их можно считать из памяти модуля. Так что модуль DS1307 часто используют, когда контроллерам Arduino необходимо знать точное время, для запуска какого то события и так далее.
Обмен данными с другими устройствами осуществляется по интерфейсу I2C с выводов SCL и SDA. Конденсаторы С1 и С2 необходимы для снижения помех по линию питания. Чтобы обеспечить надлежащего уровня сигналов SCL и SDA установлены резисторы R2 и R3 (подтянуты к питанию). Для проверки работоспособности модуля, на вывод 7 микросхему DS1307Z, подается сигнал SQ, прямоугольной формы с частотой 1 Гц. Элементы R4, R5, R6, VD1 необходимы для подзарядку литиевой батарейки. Так же, на плате предусмотрено посадочное место (U1), для установки датчика температуры DS18B20 (при необходимости можно впаять его), считывать показания, можно с вывода DS, который подтянут к пиатнию, через резистор R1 сопротивлением 3.3 кОм. Принципиальную схему и назначение контактов можно посмотреть на рисунках ниже.
На плате расположено две группы контактов, шагом 2.54 мм, для удобного подключения к макетной плате, буду использовать штырьевые разъемы, их необходимо впаять.
Первая группа контактов:
DS: вывод DS18B20 (1-wire)
VCC: «+» питание модуля
GND: «-» питание модуля
Вторая группа контактов:
SQ: вход 1 МГц
DS: вывод DS18B20 (1-wire)
SCL: линия тактирования (Serial CLock)
SDA: линия данных (Serial Dфta)
VCC: «+» питание модуля
GND:«-» питание модуля
BAT:
Подзарядка батареи
Как описывал ваше модуль может заряжать батарею, реализовано это, с помощью компонентов R4, R5, R6 и диода D1. Но, данная схема имеет недостаток, через резистор R4 и R6 происходит разряд батареи (как подметил пользователь ALEXEY, совсем не большой). Так как модуль потребляем незначительный ток, можно удалить цепь питания, для этого убираем R4, R5, R6 и VD1, вместо R6 поставим перемычку (после удаления компонентов, можно использовать обычную батарейку CR2032).
Подключение DS1307 к Arduino
Необходимые детали:
Arduino UNO R3 x 1 шт.
Провод DuPont, 2,54 мм, 20 см x 1 шт.
Кабель USB 2.0 A-B x 1 шт.
Часы реального времени RTC DS1307 x 1 шт.
Подключение:
Для подключения часы реального времени DS1307, необходимо впаять впаять штыревые разъемы в первую группу контактов. Далее, подключаем провода SCL (DS1307) к выводу 4 (Arduino UNO) и SDA (DS1307) к выводу 5 (Arduino UNO), осталось подключить питания VCC к +5V и GND к GND. Кстати, в различных платах Arduino вывода интерфейса I2C отличаются, назначение каждого можно посмотреть ниже.
Установка времени DS1307
Первым делом, необходимо скачать и установить библиотеку «DS1307RTC» и «TimeLib» в среду разработки IDE Arduino, далее необходимо настроить время, открываем пример из библиотеки DS1307RTC «Файл» —> «Примеры» —> «DS1307RTC» —> «SetTime» или копируем код снизу.
const char *monthName = {
“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”,
“Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”
};
tmElements_t tm;
void setup() {
bool parse=false;
bool config=false;
// get the date and time the compiler was run
if (getDate(__DATE__) && getTime(__TIME__)) {
parse = true;
// and configure the RTC with this info
if (RTC.write(tm)) {
config = true;
}
}
Serial.begin(9600);
while (!Serial) ; // wait for Arduino Serial Monitor
delay(200);
if (parse && config) {
Serial.print(“DS1307 configured Time=”);
Serial.print(__TIME__);
Serial.print(“, Date=”);
Serial.println(__DATE__);
} else if (parse) {
Serial.println(“DS1307 Communication Error:-{“);
Serial.println(“Please check your circuitry”);
} else {
Serial.print(“Could not parse info from the compiler, Time=””);
Serial.print(__TIME__);
Serial.print(“”, Date=””);
Serial.print(__DATE__);
Serial.println(“””);
}
}
void loop() {
}
bool getTime(const char *str)
{
int Hour, Min, Sec;
if (sscanf(str, “%d:%d:%d”, &Hour, &Min, &Sec) != 3) return false;
tm.Hour = Hour;
tm.Minute = Min;
tm.Second = Sec;
return true;
}
bool getDate(const char *str)
{
char Month;
int Day, Year;
uint8_t monthIndex;
if (sscanf(str, “%s %d %d”, Month, &Day, &Year) != 3) return false;
for (monthIndex = 0; monthIndex = 12) return false;
tm.Day = Day;
tm.Month = monthIndex + 1;
tm.Year = CalendarYrToTm(Year);
return true;
}
Скачать скетч
Загружаем данную скетч в контроллер Arduino (время берется с ОС), открываем «Мониторинг порта»
Программа
В библиотеке есть еще один пример, открыть его можно DS1307RTC «Файл» —> «Примеры» —> «DS1307RTC» —> «ReadTest»
/*
Тестирование производилось на Arduino IDE 1.6.12
Дата тестирования 23.11.2016г.
*/
#include
#include
#include
void setup() {
Serial.begin(9600); // Устанавливаем скорость передачи данных
while (!Serial) ; // Ожидаем подключение последовательного порта. Нужно только для Leonardo
delay(200); // Ждем 200 мкс
Serial.println(“DS1307RTC Read Test”); // Выводим данные на последовательный порт
Serial.println(“——————-“); // Выводим данные на последовательный порт
}
void loop() {
tmElements_t tm;
if (RTC.read(tm)) {
Serial.print(“Ok, Time = “);
print2digits(tm.Hour);
Serial.write(“:”);
print2digits(tm.Minute);
Serial.write(“:”);
print2digits(tm.Second);
Serial.print(“, Date (D/M/Y) = “);
Serial.print(tm.Day);
Serial.write(“/”);
Serial.print(tm.Month);
Serial.write(“/”);
Serial.print(tmYearToCalendar(tm.Year));
Serial.println();
} else {
if (RTC.chipPresent()) {
Serial.println(“The DS1307 is stopped. Please run the SetTime”);
Serial.println(“example to initialize the time and begin running.”);
Serial.println();
} else {
Serial.println(“DS1307 read error! Please check the circuitry.”);
Serial.println();
}
delay(9000);
}
delay(1000);
}
void print2digits(int number) {
if (number >= 0 && number
Скачать скетч
Загружаем данную код в контроллер Arduino, открываем «Мониторинг порта»
Далее переведено Д.С. Иоффе (dsioffe
@
da
.
ru
) с другом
Stylus
ом исключительно для собственного понятия. Никакие претензии не принимаются.
Описание
DS1307 – часы реального времени с последовательным интерфейсом – низкая потребляемая мощность, полный BCD календарь, часы плюс 56 байтов энергонезависимого статического ОЗУ. Адрес и данные передаются последовательно через 2-проводную двунаправленную шину. Часы / календарь хранят следующую информацию: секунды, минуты, часы, день, дату, месяц и год. Конец месяца автоматически подстраивается для месяцев, в которых менее 31 дня, включая поправку для високосного года. Часы работают в 24-часовом или 12-часовом формате с индикатором AM/PM. DS1307 имеет встроенную схему контроля питания, которая обнаруживает пропадание питания и автоматически переключает схему на питание от батареи.
Работа
DS1307 работает как ведомое устройство на последовательной шине. Для доступа к нему надо установить состояние START и передать код идентификации устройства, сопровождаемый адресом регистра. К последующим регистрам можно обращаться последовательно, пока не установлено состояние STOP. Когда Vсс падает ниже 1.25 x Vbat, устройство прекращает связь и сбрасывает адресный счетчик. В это время оно не будет реагировать на входные сигналы, чтобы предотвратить запись ошибочной информации. Когда Vcc падает ниже Vbat, устройство переключается в режим хранения с низким потреблением. При включении питания устройство переключает питание с батареи на Vcc, когда напряжение питания превысит Vbat + 0. 2V, и реагирует на входные сигналы, когда Vcc станет более 1.25 x Vbat. Функциональная схема на рисунке 1 показывает главные элементы часов реального времени с последовательным интерфейсом. Следующие параграфы описывают функцию каждого вывода.
Рисунок 1.
Функциональная схема
DS1307
Описания сигналов
Vcc, GND
– постоянное напряжение питания. Vcc = + 5 вольт. Когда питание находится в пределах нормы, устройство полностью доступно, и данные могут быть записаны и считаны. Когда к устройству подключена трёхвольтовая батарея и Vcc ниже 1.25 x Vbat, чтение и запись запрещены. Однако отсчёт времени при этом работает. Когда Vcc падает ниже Vbat, питание ОЗУ и отсчёта времени переключается на внешнюю батарею 3 В.
Vbat
– вход батареи для любого стандартного 3 вольтового литиевого элемента или другого источника энергии. Для нормальной работы напряжение батареи должно поддерживаться между 2.5 и 3.5 В. Уровень, при котором запрещён доступ к часам реального времени и пользовательскому ОЗУ,установлен внутренней схемой равным 1.25 x Vbat. Литиевая батарея ёмкостью 35 mAh или больше достаточна для питания DS1307 в течение более чем 10 лет при отсутствии питания.
SCL
(Последовательный Тактовый Вход) – SCL используется, чтобы синхронизировать передачу данных через последовательный интерфейс.
SDA
(Вход/Выход Последовательных Данных) – SDA – вход / выход данных для 2-проводного последовательного интерфейса. Это выход с открытым стоком, который требует внешнего притягивающего резистора.
SQW/OUT
(Меандр / Выходной Драйвер) – Когда бит SQWE установлен в 1, на выходе SQW/OUT вырабатываются импульсы в форме меандра одной из четырех частот: 1 Hz, 4 КГЦ, 8 КГЦ, 32 КГЦ. Вывод SQW/OUT – с открытым стоком, требует внешнего притягивающего резистора.
X1, X2
– выводы для подключения стандартного кристалла кварца 32.768 КГЦ. Внутренняя схема генератора рассчитана на работу с кристаллом, имеющим номинальную емкость (CL) 12.5 pF.
Адресное пространство часов и ОЗУ
Карта адресов для RTC и регистров ОЗУ DS1307 показана на рисунке 2. Регистры RTC расположены по адресам от 00h до 07h. Регистры ОЗУ расположены по адресам от 08h до 3Fh. Во время многобайтового доступа, когда указатель адреса достигает 3Fh, конца пространства ОЗУ, он возвращается к 00h, началу пространства часов.
Примечание переводчика:
Состояния регистров
DS
1307 при включении питания (числа двоичные):
(установлено экспериментально при помощи внутрисхемного эмулятора микропроцессора)
seconds
10000000 – значит, при включении питания часы стоят!
minutes0
hours0
day1
date1
month1
year
0
control11
Часы и календарь
Информацию о времени и дате получают, считывая соответствующие регистры. Регистры часов показаны на рисунке 3. Время и календарь устанавливаются или инициализируются путём записи байтов в соответствующие регистры. Содержание регистров времени и календаря хранится в двоично-десятичном (BCD) формате. Бит 7 Регистра 0 – это бит остановки часов (CH). Когда этот бит установлен в 1, генератор остановлен. Когда сброшен в ноль, генератор работает.
DS1307 может работать в 12-часовом или 24-часовом режиме. Бит 6 регистра часов задаёт один из этих режимов. Когда он равен 1, установлен 12-часовой режим. В 12-часовом режиме высокий уровень бита 5 сообщает о послеполуденном времени. В 24-часовом режиме бит 5 – второй бит 10 часов (20-23 часа).
Регистр управления
Регистр управления DS1307 предназначен для управления работой вывода SQW/OUT.
OUT
(управление выходом): Этот бит управляет выходным уровнем на выводе SQW/OUT, когда генерация меандра запрещена. Если SQWE = 0, логический уровень на выводе SQW/OUT равен 1, если OUT = 1, и 0 – если OUT = 0.
SQWE
(Разрешение меандра): Когда этот бит установлен в 1, разрешается генерация меандра. Частота меандра зависит от значений битов RS0 и RS1.
RS
(Выбор частоты): эти биты управляют частотой меандра, когда его генерация разрешена. В таблице 1 показаны частоты, которые могут быть заданы RS битами.
2-проводная последовательная шина
DS1307 поддерживает двунаправленные 2-проводную шину и протокол передачи данных. Устройство, которое посылает данные на шину, называется передатчиком, а устройство, получающее данные – приемником. Устройство, которое управляет передачей, называется ведущим. Устройства, которые управляются ведущим – ведомые. Шина должна управляться ведущим устройством, которое вырабатывает последовательные такты (SCL), управляет доступом к шине, и генерирует состояния СТАРТ и СТОП. DS1307 работает как ведомое на 2-проводной шине. Типичная конфигурация шины, использующая этот 2-проводной протокол, показана на рисунке 4.
Определен следующий протокол шины:
Передача данных может быть начата только тогда, когда шина не занята.
В течение передачи данных сигнал на линии данных должен оставаться постоянным всегда, когда на линии тактов высокий уровень. Изменения на линии данных в то время, когда на линии тактов высокий уровень, будут интерпретироваться как сигналы управления.
Соответственно, были определены следующие состояния шины:
Шина свободна
.
На обеих линиях: данных и тактов высокий уровень.
Начало передачи данных:
переход линии данных от высокого уровня к низкому при высоком уровне на линии тактов определяет условие СТАРТ.
Остановка передачи данных
:
переход линии данных от низкого уровня к высокому, в то время как на линии тактов высокий уровень, определяет условие СТОП.
Правильные данные
:
линия считается находящейся в состоянии передачи данных, когда после состояния СТАРТ уровень на линии данных не изменяется во время высокого уровня на линии тактирования. Он должен изменяться только во время низкого уровня тактового сигнала. Имеется один тактовый импульс на бит данных. Каждая передача данных начинается с состояния СТАРТ и заканчивается состоянием СТОП. Число байтов данных, переданных между этими состояниями, не ограничено и определяется ведущимустройством. Информация передаётся байтами, и каждый приемник посылает подтверждение с девятым битом.
Подтверждение
:
каждое принимающее устройство, когда оно адресовано, обязано произвести подтверждение после приема каждого байта. Ведущее устройство должно произвести дополнительный тактовый импульс, который связан с этим подтверждающим битом. Подтверждающее устройство должно притянуть к земле линию SDA в течение подтверждающего тактового импульса так, чтобы на линии SDA низкий уровень удерживался в течение высокого уровня подтверждающего тактового импульса. Конечно, должны быть приняты во внимание времена установки и удержания. При получении данных от ведомого ведущий должен сообщить о конце данных ведомому,не генерируя подтверждающий бит на последнем байте, который был передан от ведомого. В этом случае, ведомый должен установить на линии данных высокий уровень, чтобы позволить ведущему установить состояние СТОП.
Передача данных
На рисунках 5, 6, и 7 подробно показано, как передаются данные по 2-проводной шине. В зависимости от состояния бита R/W при передаче, как показано на рисунках 6 и 7, возможны два типа передачи данных:
1. Данные передаются от ведущего к ведомому. Первый байт, переданный ведущим – адрес ведомого. Затем следуют байты данных. Ведомый возвращает подтверждающий бит после каждого полученного байта. Данные передаются, начиная со старшего бита (MSB).
2. Данные передаются от ведомого к ведущему. Первый байт (адрес ведомого) передаётся ведущим. Тогда ведомый возвращает подтверждающий бит. Затем ведомый передаёт байты данных. Ведущий возвращает подтверждающий бит после всех полученных байтов, кроме последнего. В конце последнего полученного байта, возвращается “неподтверждение”. Ведущее устройство генерирует все тактовые импульсы и состояния СТАРТ и СТОП. Передача заканчивается формированием состояния СТОП или повторного состояния СТАРТ. Так как повторное состояние СТАРТ является также началом следующей последовательной передачи, шина не будет освобождена. Данные передаются старшим битом (MSB) вперёд. DS1307 может использовать следующие два способа:
1. Режим ведомого приемника (режим записи DS1307): Последовательные данные и такты получены через SDA и SCL. После передачи каждого байта передаётся подтверждающий бит. Состояния СТАРТ и СТОП опознаются как начало и конец последовательной передачи. Распознавание адреса выполняется аппаратно после приема адреса ведомого и бита направления (См. рисунок 6). Байт адреса содержит семибитный адрес DS1307, равный 1101000, сопровождаемым битом направления (R/W), который при записи равен 0. После получения и расшифровки байта адреса DS1307 выдаёт подтверждение на линии SDA. После того, как DS1307 подтверждает адрес ведомого и бит записи, ведущий передает адрес регистра DS1307. Тем самым будет установлен указатель регистра в DS1307. Тогда ведущий начнет передавать байты данных в DS1307, который будет подтверждать каждый полученный байт. По окончании записи ведущий сформирует состояние СТОП.
2. Режим ведомого передатчика (режим чтения из DS1307): Первый байт принимается и обрабатывается как в режиме ведомого приёмника. Однако в этом режиме бит направления укажет, что направление передачи изменено. Последовательные данные передаются по SDA от DS1307, в то время как последовательные такты – по SCL в DS1307. Состояния СТАРТ и СТОП опознаются как начало и конец последовательной передачи (См. рисунок 7). Байт адреса – первый байт, полученный после того, как ведущим сформировано состояние СТАРТ. Байт адреса содержит семибитный адрес DS1307, равный 1101000, сопровождаемым битом направления (R/W), который при чтении равен 1. После получения и расшифровки байта адреса DS1307 выдаёт подтверждение на линии SDA. Тогда DS1307 начинает передавать данные, начинающиеся с адреса регистра, на которые указывает указатель регистра. Если указатель регистра не записан перед инициированием режима чтения, то первый адрес, который читается – это последний адрес, оставшийся в указателе регистра. DS1307 должен получить “Неподтверждение”, чтобы закончить чтение.
NOTES:
1. All voltages are referenced to ground.
2. Logic zero voltages are specified at a sink current of 5 mA at V CC =4.5V, V OL =GND for capacitive loads.
3. I CCS specified with V CC =5.0V and SDA, SCL=5.0V.
4. V CC =0V, V BAT =3V.
5. After this period, the first clock pulse is generated.
6. A device must internally provide a hold time of at least 300 ns for the SDA signal (referred to the V IHMIN of the SCL signal) in order to bridge the undefined region of the falling edge of SCL.
7. The maximum t HD:DAT has only to be met if the device does not stretch the LOW period (t LOW) of the SCL signal.
8. C B – total capacitance of one bus line in pF.
9. I CCA – SCL clocking at max frequency = 100 KHz.
10. SCL only.
11. SDA and SQW/OUT