Ds1307 питание. Моя записная книжка: Библиотека DS1307

DS1307 ещё называют RTC (Real Time Clock). Данная микросхема представляет из себя часы реального времени и календарь. Связь с микросхемой осуществляется по интерфейсу I 2 C. Её преимущество в том, что она работает (считает время) при выключенном основном питании от резервного источника питания в 3 вольта (например, от батареики типа CR3022). Но в DS1307 есть один недостаток: в ней нет проверки на правильность введённых данных. Для работы с микросхемой потребуется минимальный обвес: кварц на 32768Hz, батарея на 3 вольта и два резистора на 4,7кОм. Схема подключения DS1307:

Работа с DS1307 в BASCOM-AVR

Для начала работы с микросхемой необходимо сконфигурировать порты, к которым подключена микросхема, для этого воспользуемся командой Config :
Config Sda = (Порт микроконтроллера к которому подключена нога SDA микросхемы DS1307)
Config Scl = (Порт микроконтроллера к которому подключена нога SCL микросхемы DS1307)
Например:
Config Sda = Portb.1
Config Scl = Portb.0

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

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte (переменная в которую запишем секунды) , Ack I2crbyte (переменная в которую запишем минуты) , Ack I2crbyte (переменная в которую запишем часы) , Ack I2crbyte (переменная в которую запишем номер дня недели) , Ack I2crbyte (переменная в которую запишем дату), Ack I2crbyte (переменная в которую запишем номер месяца) , Ack I2crbyte (переменная в которую запишем год) , Nack I2cstop

После чтения данных необходимо перевести их в десятичный формат, вот так:
(переменная секунд) = Makedec((переменная секунд))
(переменная минут) = Makedec((переменная минут))
(переменная часов) = Makedec((переменная часов))
(переменная дня недели) = Makedec((переменная дня недели))
(переменная даты) = Makedec((переменная даты))
(переменная месяца) = Makedec((переменная месяца))
(переменная года) = Makedec((переменная года))

Вот пример чтения времени и даты, а также перевод их в десятичный формат:

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte Hour , Ack I2crbyte Day , Ack I2crbyte Dat , Ack I2crbyte Month , Ack I2crbyte Year , Nack I2cstop Seco = Makedec(seco) Mine = Makedec(mine) Hour = Makedec(hour) Day = Makedec(day) Dat = Makedec(dat) Month = Makedec(month) Year = Makedec(year)

Данные считывать научились, теперь попробуем записывать данные в DS1307. Вот так:
(Переменная которую запишем) = Makebcd((Переменная которую запишем))
I2cstart
I2cwbyte &HD0
I2 cwbyte (Ячейка в которую запишем данные)
I2 cwbyte (Переменная которую запишем)
I2cstop

Обратите внимание, что командаMakebcd переводит переменную в двоично-десятичный формат. Номера и обозначения ячеек:

Вот пример записи переменной секунд:
Seco = Makebcd(seco)
I2cstart
I2cwbyte &HD0
I2cwbyte 0
I2cwbyte Seco
I2 cstop
Кстати, следует учесть, что при первом запуске DS1307 (например, при подключении батареи резервного питания) микросхема будет возвращать в секундах значение 80, это означает, что часы остановлены. Для их запуска запишите в секунды значение 1. Если DS1307 при чтении любых данных возвращает значение 255 или 168 это означает что, микросхема неправильно подключена, либо отсутствует батарея резервного питания.

Практическая работа с микросхемой DS1307

Теперь попробуем поработать с микросхемой DS1307 на практике: соберём простые часы с установкой времени с помощью кнопок. Для этого возьмём саму микросхему DS1307, микроконтроллер Attiny2313, LCD индикатор на контроллере HD44780 и несколько дискретных компонентов. Соберём простую схему:

И напишем простую программу, применяя полученные знания:

$regfile = "attiny2313.dat" $crystal = 4000000 Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2 Config Lcd = 16 * 2 Config Pind.5 = Input Config Pind.4 = Input Config Sda = Portb.1 Config Scl = Portb.0 Dim Seco As Byte Dim Mine As Byte Dim Hour As Byte Initlcd Cls Cursor Off Do I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte Hour , Nack I2cstop Seco = Makedec(seco) Mine = Makedec(mine) Hour = Makedec(hour) Locate 1 , 1 Lcd Hour ; ":" ; Mine ; ":" ; Seco ; " " If Pind.5 = 0 Then Incr Mine Mine = Makebcd(mine) I2cstart I2cwbyte &HD0 I2cwbyte 1 I2cwbyte Mine I2cstop Waitms 100 End If If Pind.4 = 0 Then Incr Hour Hour = Makebcd(hour) I2cstart I2cwbyte &HD0 I2cwbyte 2 I2cwbyte Hour I2cstop Waitms 100 End If Loop End

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 << TWPS1)|(1 << TWPS0); // Предделитель на 64 TWCR |= (1 << TWEN); // Включение модуля TWI } // Функция СТАРТ void I2CStart(void) { TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTA); // Передача условия СТАРТ while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT } // Функция СТОП void I2CStop(void) { TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTO); // Передача условия СТОП while(TWCR & (1 << TWSTO)); // Ожидание завершения передачи условия СТОП } // Функция записи данных по шине uint8_t I2CWriteByte(uint8_t data) { TWDR = data; // Загрузка данных в TWDR TWCR = (1 << TWEN)|(1 << TWINT); // Сброс флага TWINT для начала передачи данных while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT // Проверка статуса // Если адрес DS1307+R и принято "подтверждение"(0x18) // или адрес DS1307+W и принято "подтверждение"(0x40) // или передается байт данных и принято "подтверждение"(0x28) if((TWSR & 0xF8) == 0x18 || (TWSR & 0xF8) == 0x40 || (TWSR & 0xF8) == 0x28) return 1; // OK else return 0; // ОШИБКА } // Функция чтения данных по шине uint8_t I2CReadByte(uint8_t *data,uint8_t ack) { // Возвращаем "подтверждение" после приема if(ack) TWCR |= (1 << TWEA); // Возвращаем "неподтверждение" после приема // Ведомое устройство не получает больше данных // обычно используется для распознования последнего байта else TWCR &= ~(1 << TWEA); // Разрешение приема данных после сброса TWINT TWCR |= (1 << TWINT); while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT // Проверка статуса // Если принят байт данных и возвращается "подтверждение"(0x50) // или принят байт данных и возвращается "ненеподтверждение"(0x58) if((TWSR & 0xF8) == 0x50 || (TWSR & 0xF8) == 0x58) { *data = TWDR; // Читаем данные из TWDR return 1; // OK } else return 0; // ОШИБКА } // Функция чтения данных из DS1307 uint8_t DS1307Read(uint8_t address,uint8_t *data) { uint8_t res; I2CStart(); // СТАРТ res = I2CWriteByte(0b11010000); // адрес DS1307+W if(!res) return 0; // ОШИБКА // Передача адреса необходимого регистра res = I2CWriteByte(address); if(!res) return 0; // ОШИБКА I2CStart(); // Повторный СТАРТ res = I2CWriteByte(0b11010001); // адрес DS1307+R if(!res) return 0; // ОШИБКА // Чтение данных с "неподтверждением" res = I2CReadByte(data,0); if(!res) return 0; // ОШИБКА I2CStop(); // СТОП return 1; // OK } // Функция записи данных в DS1307 uint8_t DS1307Write(uint8_t address,uint8_t data) { uint8_t res; I2CStart(); // СТАРТ res = I2CWriteByte(0b11010000); // адрес DS1307+W if(!res) return 0; // ОШИБКА // Передача адреса необходимого регистра res = I2CWriteByte(address); if(!res) return 0; // ОШИБКА res = I2CWriteByte(data); // Запись данных if(!res) return 0; // ОШИБКА I2CStop(); // СТОП return 1; // OK } // Функции работы с LCD #define RS PD0 #define EN PD2 // Функция передачи команды void lcd_com(unsigned char p) { PORTD &= ~(1 << RS); // RS = 0 (запись команд) PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); } // Функция передачи данных void lcd_data(unsigned char p) { PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); } // Функция вывода строки на LCD void lcd_string(unsigned char command, char *string) { lcd_com(0x0C); lcd_com(command); while(*string != "\0") { lcd_data(*string); string++; } } // Функция вывода переменной void lcd_num_to_str(unsigned int value, unsigned char nDigit) { switch(nDigit) { case 4: lcd_data((value/1000)+"0"); case 3: lcd_data(((value/100)%10)+"0"); case 2: lcd_data(((value/10)%10)+"0"); case 1: lcd_data((value%10)+"0"); } } // Функция инициализации LCD void lcd_init(void) { PORTD = 0x00; DDRD = 0xFF; _delay_ms(50); // Ожидание готовности ЖК-модуля // Конфигурирование четырехразрядного режима PORTD |= (1 << PD5); PORTD &= ~(1 << PD4); // Активизация четырехразрядного режима PORTD |= (1 << EN); PORTD &= ~(1 << EN); _delay_ms(5); lcd_com(0x28); // шина 4 бит, LCD - 2 строки lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея _delay_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0C); // включение дисплея, курсор не видим } int main(void) { _delay_ms(100); DDRC = 0x00; PORTC = 0xFF; lcd_init(); // Инициализация LCD I2CInit(); // Инициализация шины I2C lcd_string(0x81, "«acГ Ѕa DS1307"); // Часы на DS1307 lcd_string(0xC4, " : : "); // Запускаем ход часов uint8_t temp; DS1307Read(0x00,&temp); temp &= ~(1 << 7); // обнуляем 7 бит DS1307Write(0x00,temp); while(1) { unsigned char hour, minute, second, temp; // Читаем данные и преобразуем из BCD в двоичную систему DS1307Read(0x00,&temp); // Чтение регистра секунд second = (((temp & 0xF0) >> 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 << PC0)) == 0) // Если нажата кнопка { while((PINC & (1 << PC0)) == 0){} // Ждем отпускания кнопки hour++; // Увеличиваем часы на 1 if(hour > 23) hour = 0; // Преобразуем из двоичной системы в BCD и записываем в DS1307 uint8_t temp; temp = ((hour/10) << 4)|(hour%10); DS1307Write(0x02, temp); _delay_ms(100); } if((PINC & (1 << PC1)) == 0) // Если нажата кнопка { while((PINC & (1 << PC1)) == 0){} // Ждем отпускания кнопки minute++; // Увеличиваем минуты на 1 if(minute > 59) minute = 0; // Преобразуем из двоичной системы в BCD и записываем в DS1307 uint8_t temp; temp = ((minute/10) << 4)|(minute%10); DS1307Write(0x01, temp); _delay_ms(100); } } }

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

Особенности:

  • Очень маленькое энергопотребление. Производитель обещает 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 это небольшой модуль, предназначенный для подсчета времени. Собранный на базе микросхемы 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» или копируем код снизу.

// Подключаем библиотеку DS1307RTC 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; monthIndex++) { if (strcmp(Month, monthName) == 0) break; } if (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 // Подключаем библиотеку Wire #include // Подключаем библиотеку TimeLib #include // Подключаем библиотеку DS1307RTC 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 < 10) { Serial.write("0"); } Serial.print(number); }

Скачать скетч

Загружаем данную код в контроллер Arduino, открываем «Мониторинг порта»

Эта библиотека была написана для легкого взаимодействия и использования модуля на микросхеме DS1307 с Arduino или chipKit без необходимости использования библиотеки Wire.
Данная библиотека использует по умолчанию режим Fast Mode (400 кГц) аппаратного интерфейса I2C.
Работа этой библиотека не гарантируется в режиме одновременной работы с библиотекой Wire и совместного использования контактов.

Структура:

Time;
Структура управления данными времени и даты.
Переменные :
hour, min, sec: Для определения данных времени
date, mon, year: Для определения данных даты
dow: День недели, начиная с понедельника
Пример: Time t; // Определяем структуру с именем t класса "время"

DS1307_RAM;
Буфер для использования совместно с ReadBuffer () и WriteBuffer ().
Переменные:
Cell : Байт-массив для хранения данных, с возможностью чтения или записи в ОЗУ микросхемы.
Пример: DS1307_RAM ramBuffer; // Объявляем буфер для использования

Определенные литералы:

Дни недели

Используется совместно с setDOW() и Time.dow
MONDAY: 1
TUESDAY: 2
WEDNESDAY : 3
THURSDAY: 4
FRIDAY: 5
SATURDAY: 6
SUNDAY: 7

Длина названия
Используется совместно с getTimeStr(), getDateStr(), getDOWStr() and getMonthStr()
FORMAT_SHORT: 1 (полное название)
FORMAT_LONG: 2 (сокращенное (3 буквенное) название)

Формат даты
Используется совместно с getDateStr()
FORMAT_LITTLEENDIAN: 1 (дд.мм.гггг)
FORMAT_BIGENDIAN: 2 (гггг.мм.дд)
FORMAT_MIDDLEENDIAN: 3 (мм.дд.гггг)

Частота на выходе SQW

Используется совместно с setSQWRate()

SQW_RATE_1: 1 (1 Гц)

SQW_RATE_4K: 2 (4096 Гц)

SQW_RATE_8K: 3 (8192 Гц)

SQW_RATE_32K: 4 (32768 Гц)

Функции:

DS1307(SDA, SCL);
Инициализация библиотеки с помощью интерфейса I2C
Параметры:
SDA: Вывод подключения SDA-пина DS1307 (Вывод 5, данные)
SCL: Вывод подключения SCL-пина DS1307 (вывод 6, тактирование)
Пример: DS1307 rtc(SDA, SCL); // Инициализация библиотеки DS13071 с помощью интерфейса I2C
Примечание: DS1307 можно подключать с любым свободным выводам Arduino. Если в схеме уже используется шина I2C и Вы попытаетесь подключиться к тем же выводам, то данная библиотека работать не будет, т.к. любой TWI-совместимый протокол требует исключительного доступа к пинам.

begin();
Инициализация подключения к DS1307
Параметры: Нет
Возврат: Нет

Пример: rtc.begin(); //Инициализация подключения к DS1307

getTime();
Считать текущие данные из DS3231.
Параметры : Нет
Возврат: формат Time-structure
Пример: t = rtc.getTime(); // Считать текущую дату и время.


getTimeStr();
Считать текущее время в виде строковой переменной.
Параметры:
format: <необязательный параметр>
FORMAT_LONG "ЧЧ:ММ:СС" (По умолчанию)
FORMAT_SHORT "ЧЧ:ММ"
Возврат: Строковое значение, содержащее текущее время с секундами или без них.
Пример: Serial.print(rtc.getTimeStr()); // Отправить текущее время через последовательный порт

getDateStr(]]);
Считать текущую дату в виде строковой переменной.
Параметры:
slformat: <необязательный параметр>
FORMAT_LONG Год из 4х цифр (ГГГГ) (По умолчанию)
FORMAT_SHORT Год из 2х цифр (ГГ)
eformat: <необязательный параметр>
FORMAT_LITTLEENDIAN "ДД.ММ.ГГГГ" (По умолчанию)
FORMAT_BIGENDIAN "ГГГГ.ММ.ДД"
FORMAT_MIDDLEENDIAN "ММ.ДД.ГГГГ"
divider: <необязательный параметр>
Символ для разделения. По умолчанию "."
Возврат: Строковое значение, содержащее текущую дату в указанном формате.
Пример: Serial.print(rtc.getDateStr()); // Отправить текущую дату через последовательный порт (В формате "ДД.ММ.ГГГГ")

getDOWStr();
Считать текущий день недели в виде строковой переменной.
Параметры:
format: <необязательный параметр>
FORMAT_LONG День недели на английском языке (По умолчанию)
FORMAT_SHORT Сокращенное название дня недели на английском языке (3 символа)
Возврат: Строковое значение, содержащее текущий день день недели в полном или сокращенном формате.
Пример: Serial.print(rtc.getDOWStr(FORMAT_SHORT)); // Отправить сокращенное название текущего дня недели через последовательный порт

getMonthStr();
Считать текущий месяц в виде строковой переменной.
Параметры:
format: <необязательный параметр>
FORMAT_LONG название месяца на английском языке (По умолчанию)
FORMAT_SHORT Сокращенное название месяца на английском языке (3 символа)
Возврат: Строковое значение, содержащее текущий месяц в полном или сокращенном формате.
Пример: Serial.print(rtc.getMonthStr()); // Отправить название текущего месяца через последовательный порт

getUnixTime(time);
Преобразование значения времени и даты в формат Unix Time (UNIX-время).
Параметры:
Время: Переменная, содержащее дату и время для преобразования
Возврат : Unix Time для предоставленного значения времени
Пример: Serial.print(rtc.getUnixTime(rtc.getTime())); // Отправить текущее значение Unixtime через последовательный порт
Примечание: UNIX-время (англ. Unix time) или POSIX-время — система описания моментов во времени, принятая в UNIX и других POSIX-совместимых операционных системах. Определяется как количество секунд, прошедших с полуночи (00:00:00 UTC) 1 января 1970 года (четверг); время с этого момента называют «эрой UNIX» (англ. Unix Epoch).

setTime(hour, min, sec);
Установка времени.
Параметры:
hour: Часы (0-23)
min: Минуты (0-59)
sec: Секунды (0-59)
Пример: rtc.setTime(23, 59, 59); // Установка времени 23:59:59

setDate(date, mon, year);
Установка даты.
Параметры:
date: День (1-31)
mon: Месяц (1-12)
year: Год (2000-2099)
Пример: rtc.setDate(16, 5, 2016); // Установка даты 16 мая 2016г.
Примечание: Защиты от ввода неправильной даты нет. Т.е., возможно ввести 31 февраля, но результат будет не предсказуем

setDOW(dow);
Установка дня недели.
Параметры:
dow: <необязательный параметр> День недели (1-7)
Если параметр не задан, значение параметра будет рассчитываться на основе данных, хранящихся в настоящее время в DS3231.
Пример: rtc.setDOW(FRIDAY); // Установить день недели - Пятница
Примечание: Устанавливаются от понедельника (1) до воскресенья (7).

halt(value);
Установка или сброс флага запуска часов.
Параметры:
value: true: Установить CH флаг
false: Сбросить CH флаг
Возврат: Нет
Пример: rtc.halt(false); // Запустить часовой модуль в работу

setOutput(enable);
Установка на выводе SQW/OUT (вывод 7) микросхемы DS1307 высокого или низкого уровня. Данная команда не работает, если enableSQW() имеет значение TRUE.
Параметры:
enable: TRUE : Установить на выводе высокий уровень
FALSE: Установить на выводе низкий уровень.
Возврат: Нет
Пример: rtc.setOutput(true); // Установить на выводе SQW/OUT высокий уровень

enableSQW(enable);
Разрешение или запрет вывода прямоугольных импульсов заданной частоты на выводе SQW/OUT.
Параметры:
enable: TRUE: Разрешить прямоугольные импульсы на выводе
FALSE: Запретить прямоугольные импульсы на выводе
Возврат: Нет
Пример: rtc.enableSQW(true); // Использовать вывод SQW/OUT в качестве генератора прямоугольных импульсов

setSQWRate(rate);
Задание частоты прямоугольных импульсов на выводе SQW.
Параметры:
rate: SQW_RATE_1 - частота 1Гц
SQW_RATE_4K - частота 4.096кГц
SQW_RATE_8K - частота 8.192кГц
SQW_RATE_32K - частота 32.768кГц
Возврат: Нет
Пример: rtc.setSQWRate(SQW_RATE_1); // Задать частоту на выводе SQW равной 1Гц

writeBuffer(buffer);
Записать данные из буфера в ОЗУ микросхемы.
Параметры:
buffer: DS1307_RAM буфер
Возврат: Нет
Пример: rtc.writebuffer(ramBuffer); // Записать 56 байт из переменной ramBuffer в ОЗУ микросхемы

readBuffer();
Считать данные из ОЗУ микросхемы в буфер.
Параметры: Нет
Возврат: DS1307_RAM буфер
Пример: ramBuffer=rtc.readBuffer(); // Считать все 56 bytes из ОЗУ микросхемы в переменную ramBuffer

poke(address, value);
Записать 1 байт в ОЗУ микросхемы
Параметры:
address: Адрес для записи байта (0-55)
value: Значение для записи по адресу

(0-255)
Возврат: Нет
Пример: rtc.poke(15, 160); // Записать 160 по адресу 15

peek(address);
Считать 1 байт из ОЗУ микросхемы
Параметры:
address : Адрес для чтения байта (0-55)
Возврат: 1 байт данных, считанных из ОЗУ микросхемы
Пример: b=rtc.peek(18); // Считать 1 байт по адресу 18 и записать значение в переменную b

mob_info