Кому интересно, выкладываю скетч для работы с DS1307 и I2C 16x2 дисплеем. Основные возможности:
1. Автоматическая установка даты и времени, а также дня недели при компиляции, не требующей повторно заливать скетч и комментировать строку установки времени(работает при помощи сравнивания хеша в EEPROM.
2. Вывод всех этих данных на I2C 16x2 дисплей.
Данный скетч собирался из кусочков кодов, найденных на просторах интернета. Возможно код не оптимален, особенно в функции установки дня недели, но всё работает.
#include <Wire.h> #include <EEPROM.h> #include "DS1307.h" #include <LiquidCrystal_I2C.h> //Массив, содержащий время компиляции char compileTime[] = __TIME__; //Массив, содержащий время компиляции char compileDate[] = __DATE__; LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); DS1307 clock; void setup() { //Ручная установка времени и даты //clock.fillByYMD(2013,1,19);//2013, Jan, 19, //clock.fillByHMS(15,28,30);//15:28 30" // clock.fillDayOfWeek(SAT);//Saturday //clock.setTime();//write time to the RTC chip lcd.begin (16, 2); Serial.begin(9600); clock.begin(); //Получаем часы, минуты, секунды byte hour = getInt(compileTime, 0); byte minute = getInt(compileTime, 3); byte second = getInt(compileTime, 6); //Получаем год, месяц и число int year = get4DigitInt(compileDate, 7); int day = getInt(compileDate, 4); int month; switch (compileDate[0] + compileDate[1] + compileDate[2]) { case 'J'+'a'+'n': month = 1; break; case 'F'+'e'+'b': month = 2; break; case 'M'+'a'+'r': month = 3; break; case 'A'+'p'+'r': month = 4; break; case 'M'+'a'+'y': month = 5; break; case 'J'+'u'+'n': month = 6; break; case 'J'+'u'+'l': month = 7; break; case 'A'+'u'+'g': month = 8; break; case 'S'+'e'+'p': month = 9; break; case 'O'+'c'+'t': month = 10; break; case 'N'+'o'+'v': month = 11; break; case 'D'+'e'+'c': month = 12; break; } char week[7][10] = { "1", "2", "3", "4", "5", "6", "7" }; //Импровизированный хэш времени //Содержит в себе количество секунд с начала дня unsigned int hash = hour * 60 * 60 + minute * 60 + second; //Проверяем несовпадение нового хэша с хэшем в EEPROM if (EEPROMReadInt(0) != hash) { //Сохраняем новый хэш EEPROMWriteInt(0, hash); //Готовим для записи в RTC часы, минуты, секунды, год, месяц, день clock.fillByHMS(hour, minute, second); //Всавляем часы, минуты, секунды clock.fillByYMD(year, month, day); //Вставляем год, месяц, день clock.fillDayOfWeek(String(week[weekday(month, day, year)]).toInt()); //Вставляем день недели //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock.setTime(); } } void loop() { clock.getTime(); lcd.setCursor(0, 0); lcd.print(clock.hour / 10); lcd.print(clock.hour % 10); lcd.print(":"); lcd.print(clock.minute / 10); lcd.print(clock.minute % 10); lcd.print(":"); lcd.print(clock.second / 10); lcd.print(clock.second % 10); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(clock.dayOfMonth / 10); lcd.print(clock.dayOfMonth % 10); lcd.print("/"); lcd.print(clock.month / 10); lcd.print(clock.month % 10); lcd.print("/"); lcd.print(clock.year + 2000, DEC); lcd.print(" "); switch (clock.dayOfWeek) { case 1: lcd.print("MON"); break; case 2: lcd.print("TUE"); break; case 3: lcd.print("WED"); break; case 4: lcd.print("THU"); break; case 5: lcd.print("FRI"); break; case 6: lcd.print("SAT"); break; case 7: lcd.print("SUN"); break; } delay(1000); } //Запись двухбайтового числа в память void EEPROMWriteInt(int address, int value) { EEPROM.write(address, lowByte(value)); EEPROM.write(address + 1, highByte(value)); } //Чтение числа из памяти unsigned int EEPROMReadInt(int address) { byte lowByte = EEPROM.read(address); byte highByte = EEPROM.read(address + 1); return (highByte « 8) | lowByte; } char getInt(const char* string, int startIndex) { return int(string[startIndex] - '0') * 10 + int(string[startIndex + 1]) - '0'; } //Вычисление года int get4DigitInt(const char* string, int startIndex) { return (string[startIndex ] - '0') * 1000 + (string[startIndex + 1] - '0') * 100 + (string[startIndex + 2] - '0') * 10 + (string[startIndex + 3] - '0'); } //Вычисление дня недели int weekday(int month, int day, int year) { int ix, tx, vx; switch (month) { case 2 : case 6 : vx = 0; break; case 8 : vx = 4; break; case 10 : vx = 8; break; case 9 : case 12 : vx = 12; break; case 3 : case 11 : vx = 16; break; case 1 : case 5 : vx = 20; break; case 4 : case 7 : vx = 24; break; } if (year > 1900) // 1900 was not a leap year year -= 1900; ix = ((year - 21) % 28) + vx + (month > 2); // take care of February tx = (ix + (ix / 4)) % 7 + day; // take care of leap year return (tx % 7); }