diff --git a/README.md b/README.md index 1e6ba23..231a612 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ -# TroykaRTC -Arduino library to drive Troyka real time clock by Amperka.ru +Часы реального времени (Troyka-модуль) +====================================== + +Используйте библиотеку, для получения текущей секунды, минуты, часа, дня недели месяца и года с помощью [часов реального времени](http://amperka.ru/product/troyka-rtc). + +Установка библиотеки +==================== + +В Arduino IDE выберите пункт меню «Скетч» → «Импортировать библиотеку» → +«Добавить библиотеку…». В появившемся окне выберите скачаный архив с +библиотекой. Установка завершена. + +Подробности работы и примеры [часов реального времени](http://wiki.amperka.ru/продукты:troyka-rtc). \ No newline at end of file diff --git a/TroykaRTC.cpp b/TroykaRTC.cpp index 0df8deb..ae3e808 100644 --- a/TroykaRTC.cpp +++ b/TroykaRTC.cpp @@ -1,50 +1,42 @@ /****************************************************************************/ // Function: Cpp file for troyka-RTC // Hardware: DS1307 -// Arduino IDE: Arduino-1.6.5 +// Arduino IDE: Arduino-1.8.2 // Author: Igor Dementiev // Date: Sep 10,2015 -// Version: v1.0 +// Version: v1.1 // by www.amperka.ru /****************************************************************************/ #include #include "TroykaRTC.h" -#include - -uint8_t RTC::decToBcd(uint8_t val) { - return ( (val/10*16) + (val%10) ); -} - -// Convert binary coded decimal to normal decimal numbers -uint8_t RTC::bcdToDec(uint8_t val) { - return ( (val/16*10) + (val%16) ); -} void RTC::begin() { Wire.begin(); } -/* Function: The clock timing will start */ - -void RTC::start() { // set the ClockHalt bit low to start the rtc +// the clock timing will start +void RTC::start() { + // set the ClockHalt bit low to start the rtc Wire.beginTransmission(DS1307_I2C_ADDRESS); -// Register 0x00 holds the oscillator start/stop bit + // Register 0x00 holds the oscillator start/stop bit Wire.write((uint8_t)0x00); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 1); -// save actual seconds and AND sec with bit 7 (sart/stop bit) = clock started + // save actual seconds and AND sec with bit 7 (sart/stop bit) = clock started _second = Wire.read() & 0x7f; Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write((uint8_t)0x00); -// write seconds back and start the clock + // write seconds back and start the clock Wire.write((uint8_t)_second); Wire.endTransmission(); } -/*Function: The clock timing will stop */ -void RTC::stop() { // set the ClockHalt bit high to stop the rtc + +// the clock timing will stop +void RTC::stop() { + // set the ClockHalt bit high to stop the rtc Wire.beginTransmission(DS1307_I2C_ADDRESS); - // Register 0x00 holds the oscillator start/stop bit + // register 0x00 holds the oscillator start/stop bit Wire.write((uint8_t)0x00); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 1); @@ -56,74 +48,51 @@ void RTC::stop() { // set the ClockHalt bit high to stop the rtc Wire.write((uint8_t)_second); Wire.endTransmission(); } + /****************************************************************/ -/*Function: Read time and date from RTC */ +// read time and date from RTC void RTC::read() { -// Reset the register pointer + // reset the register pointer Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write((uint8_t)0x00); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 7); -// A few of these need masks because certain bits are control bits - _second = bcdToDec(Wire.read() & 0x7f); - _minute = bcdToDec(Wire.read()); + // a few of these need masks because certain bits are control bits + _second = BcdToDec(Wire.read() & 0x7f); + _minute = BcdToDec(Wire.read()); // Need to change this if 12 hour am/pm - _hour = bcdToDec(Wire.read() & 0x3f); - _dayOfWeek = bcdToDec(Wire.read()); - _day = bcdToDec(Wire.read()); - _month = bcdToDec(Wire.read()); - _year = bcdToDec(Wire.read()) + 2000; -} -/*******************************************************************/ -/*Frunction: Write the time that includes the date to the RTC chip */ -void RTC::set(uint8_t hour, uint8_t minute, uint8_t second, uint16_t day, - uint8_t month, uint8_t year, uint8_t dow) { - _hour = hour; - _minute = minute; - _second = second; - _day = day; - _month = month; - _year = year-2000; - _dayOfWeek = dow; - - Wire.beginTransmission(DS1307_I2C_ADDRESS); - Wire.write((uint8_t)0x00); - // 0 to bit 7 starts the clock - Wire.write(decToBcd(_second)); - Wire.write(decToBcd(_minute)); - // If you want 12 hour am/pm you need to set bit 6 - Wire.write(decToBcd(_hour)); - Wire.write(decToBcd(_dayOfWeek)); - Wire.write(decToBcd(_day)); - Wire.write(decToBcd(_month)); - Wire.write(decToBcd(_year)); - Wire.endTransmission(); + _hour = BcdToDec(Wire.read() & 0x3f); + _weekDay = BcdToDec(Wire.read()); + _day = BcdToDec(Wire.read()); + _month = BcdToDec(Wire.read()); + _year = BcdToDec(Wire.read()) + 2000; } +// write the time that includes the date to the RTC chip void RTC::set(const char* compileTimeStamp) { int i = 0; -// Serial.println(compileTimeStamp); +// Serial.println(compileTimeStamp); -/*--------------------DayOfWeek----------------------------*/ +/*--------------------Week day----------------------------*/ char dow[4]; for (i = 0; i < 3; i++) dow[i] = compileTimeStamp[i]; dow[i] = '\0'; if (strcmp(dow, "Mon") == 0) - _dayOfWeek = 1; + _weekDay = 1; else if (strcmp(dow, "Tue") == 0) - _dayOfWeek = 2; + _weekDay = 2; else if (strcmp(dow, "Wed") == 0) - _dayOfWeek = 3; + _weekDay = 3; else if (strcmp(dow, "Thu") == 0) - _dayOfWeek = 4; + _weekDay = 4; else if (strcmp(dow, "Fri") == 0) - _dayOfWeek = 5; + _weekDay = 5; else if (strcmp(dow, "Sat") == 0) - _dayOfWeek = 6; + _weekDay = 6; else if (strcmp(dow, "Sun") == 0) - _dayOfWeek = 7; + _weekDay = 7; /*--------------------------Day----------------------------*/ _day = ((compileTimeStamp[8] - '0') * 10 + (compileTimeStamp[9] - '0')); @@ -131,32 +100,32 @@ void RTC::set(const char* compileTimeStamp) { /*--------------------------Month---------------------------*/ char month[4]; for (i = 0; i < 3; i++) - month[i] = compileTimeStamp[i+4]; + month[i] = compileTimeStamp[i + 4]; month[i] = '\0'; - if (strcmp(month, "Jan") == 0) + if (strcmp(month, "Jan")) _month = 1; - else if (strcmp(month, "Feb") == 0) + else if (strcmp(month, "Feb")) _month = 2; - else if (strcmp(month, "Mar") == 0) + else if (strcmp(month, "Mar")) _month = 3; - else if (strcmp(month, "Apr") == 0) + else if (strcmp(month, "Apr")) _month = 4; - else if (strcmp(month, "May") == 0) + else if (strcmp(month, "May")) _month = 5; - else if (strcmp(month, "Jun") == 0) + else if (strcmp(month, "Jun")) _month = 6; - else if (strcmp(month, "Jul") == 0) + else if (strcmp(month, "Jul")) _month = 7; - else if (strcmp(month, "Aug") == 0) + else if (strcmp(month, "Aug")) _month = 8; - else if (strcmp(month, "Sep") == 0) + else if (strcmp(month, "Sep")) _month = 9; - else if (strcmp(month, "Oct") == 0) + else if (strcmp(month, "Oct")) _month = 10; - else if (strcmp(month, "Nov") == 0) + else if (strcmp(month, "Nov")) _month = 11; - else if (strcmp(month, "Dec") == 0) + else if (strcmp(month, "Dec")) _month = 12; /*--------------------------Year----------------------------*/ @@ -174,26 +143,116 @@ void RTC::set(const char* compileTimeStamp) { _second = ((compileTimeStamp[17] - '0') * 10 + (compileTimeStamp[18] - '0')); - unsigned int hash = _hour * 60 * 60 + _minute * 60 + _second; - if (EEPROMReadInt(0) != hash) { - EEPROMWriteInt(0, hash); - Wire.beginTransmission(DS1307_I2C_ADDRESS); - Wire.write((uint8_t)0x00); + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x00); // 0 to bit 7 starts the clock - Wire.write(decToBcd(_second)); - Wire.write(decToBcd(_minute)); + Wire.write(DecToBcd(_second)); + Wire.write(DecToBcd(_minute)); // If you want 12 hour am/pm you need to set bit 6 - Wire.write(decToBcd(_hour)); - Wire.write(decToBcd(_dayOfWeek)); - Wire.write(decToBcd(_day)); - Wire.write(decToBcd(_month)); - Wire.write(decToBcd(_year)); + Wire.write(DecToBcd(_hour)); + Wire.write(DecToBcd(_weekDay)); + Wire.write(DecToBcd(_day)); + Wire.write(DecToBcd(_month)); + Wire.write(DecToBcd(_year)); Wire.endTransmission(); } + +// write the time that manually +void RTC::set(uint8_t hour, uint8_t minute, uint8_t second, uint16_t day, + uint8_t month, uint8_t year, uint8_t weekDay) { + _hour = hour; + _minute = minute; + _second = second; + _day = day; + _month = month; + _year = year - 2000; + _weekDay = weekDay; + + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x00); + // 0 to bit 7 starts the clock + Wire.write(DecToBcd(_second)); + Wire.write(DecToBcd(_minute)); + // if you want 12 hour am/pm you need to set bit 6 + Wire.write(DecToBcd(_hour)); + Wire.write(DecToBcd(_weekDay)); + Wire.write(DecToBcd(_day)); + Wire.write(DecToBcd(_month)); + Wire.write(DecToBcd(_year)); + Wire.endTransmission(); } -void RTC::getTimeStr(char* output, uint8_t len) const { +// write the hour that manually +void RTC::setHour(uint8_t hour) { + _hour = hour; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x02); + Wire.write(DecToBcd(_hour)); + Wire.endTransmission(); +} + +// write the minute that manually +void RTC::setMinute(uint8_t minute) { + _minute = minute; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x01); + Wire.write(DecToBcd(_minute)); + Wire.endTransmission(); +} + +// write the second that manually +void RTC::setSecond(uint8_t second) { + _second = second; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x00); + Wire.write(DecToBcd(_second)); + Wire.endTransmission(); +} + +// write the day that manually +void RTC::setDay(uint8_t day) { + _day = day; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x04); + Wire.write(DecToBcd(_day)); + Wire.endTransmission(); +} + +// write the month that manually +void RTC::setMonth(uint8_t month) { + _month = month; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x05); + Wire.write(DecToBcd(_month)); + Wire.endTransmission(); +} + +// write the year that manually +void RTC::setYear(uint8_t year) { + _year = year - 2000; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x06); + Wire.write(DecToBcd(_year)); + Wire.endTransmission(); +} + +// write the week day that manually +void RTC::setWeekDay(uint8_t weekDay) { + _weekDay = weekDay; + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write((uint8_t)0x03); + Wire.write(DecToBcd(_weekDay)); + Wire.endTransmission(); +} + +void RTC::getTimeStamp(char* time, char* date, char* weekDay) const { + getTimeStr(time); + getDateStr(date); + getWeekDayStr(weekDay); +} + +void RTC::getTimeStr(char* output) const { char buff[8]; if (_hour < 10) buff[0] = '0'; @@ -215,23 +274,19 @@ void RTC::getTimeStr(char* output, uint8_t len) const { buff[6] = char((_second / 10) + 48); buff[7] = char((_second % 10) + 48); buff[8] = '\0'; - - len--; - int i = 0; - while (i < 8 && len > 0) { + int i; + for (i = 0; i < 8; i++ ) { output[i] = buff[i]; - i++; - len--; } output[i] = '\0'; } -void RTC::getDateStr(char* output, uint8_t len) const { +void RTC::getDateStr(char* output) const { char buff[10]; if (_day < 10) buff[0] = '0'; else - buff[0] = char((_day / 10)+ 48); + buff[0] = char((_day / 10) + 48); buff[1] = char((_day % 10) + 48); buff[2] = '.'; @@ -242,24 +297,21 @@ void RTC::getDateStr(char* output, uint8_t len) const { buff[4] = char((_month % 10) + 48); buff[5] = '.'; buff[6]=char((_year / 1000)+48); - buff[7]=char(((_year % 1000) / 100)+48); - buff[8]=char(((_year % 100) / 10)+48); - buff[9]=char((_year % 10)+48); + buff[7]=char(((_year % 1000) / 100) + 48); + buff[8]=char(((_year % 100) / 10) + 48); + buff[9]=char((_year % 10) + 48); buff[10]='\0'; - len--; - int i = 0; - while (i < 10 && len > 0) { + int i; + for (i = 0; i < 10; i++ ) { output[i] = buff[i]; - i++; - len--; } output[i] = '\0'; } -void RTC::getDOWStr(char* output, uint8_t len) const { +void RTC::getWeekDayStr(char* output) const { char buff[10]; - switch (_dayOfWeek) { + switch (_weekDay) { case 1: { strcpy(buff, "Monday"); break; @@ -290,29 +342,18 @@ void RTC::getDOWStr(char* output, uint8_t len) const { } } - int i = 0; - len--; int s = strlen(buff); - while (i < s && len > 0) { + int i; + for (i = 0; i < s; i++ ) { output[i] = buff[i]; - i++; - len--; } output[i] = '\0'; } -//Запись двухбайтового числа в память -void EEPROMWriteInt(int address, int value) -{ - EEPROM.write(address, lowByte(value)); - EEPROM.write(address + 1, highByte(value)); +uint8_t RTC::DecToBcd(uint8_t val) { + return (val / 10 * 16) + (val % 10); } -//Чтение числа из памяти -unsigned int EEPROMReadInt(int address) -{ - byte lowByte = EEPROM.read(address); - byte highByte = EEPROM.read(address + 1); - - return (highByte << 8) | lowByte; +uint8_t RTC::BcdToDec(uint8_t val) { + return (val / 16 * 10) + (val % 16); } diff --git a/TroykaRTC.h b/TroykaRTC.h index 08ce832..c219940 100644 --- a/TroykaRTC.h +++ b/TroykaRTC.h @@ -1,58 +1,66 @@ /****************************************************************************/ // Function: Header file for troyka-RTC // Hardware: DS1307 -// Arduino IDE: Arduino-1.6.5 +// Arduino IDE: Arduino-1.8.2 // Author: Igor Dementiev // Date: Sep 10,2015 -// Version: v1.0 +// Version: v1.1 // by www.amperka.ru /****************************************************************************/ #ifndef TROYKARTC_H_ #define TROYKARTC_H_ #include + #define DS1307_I2C_ADDRESS 0x68 +#define MONDAY 1 +#define TUESDAY 2 +#define WEDNESDAY 3 +#define THURSDAY 4 +#define FRIDAY 5 +#define SATURDAY 6 +#define SUNDAY 7 + class RTC { - public: +public: void begin(); void start(); void stop(); - void set(uint8_t hour, uint8_t minute, uint8_t second, uint16_t day, - uint8_t month, uint8_t year, uint8_t dow); - void set(const char *compileTimeStamp); + void set(uint8_t hour, uint8_t minute, uint8_t second, uint16_t day, + uint8_t month, uint8_t year, uint8_t weekDay); + void setHour(uint8_t hour); + void setMinute(uint8_t minute); + void setSecond(uint8_t second); + void setDay(uint8_t day); + void setMonth(uint8_t month); + void setYear(uint8_t year); + void setWeekDay(uint8_t weekDay); void read(); - void getTimeStr(char* output, uint8_t len) const; - void getDateStr(char* output, uint8_t len) const; - void getDOWStr(char* output, uint8_t len) const; - + void getTimeStamp(char* time, char* date, char* weekDay) const; + void getTimeStr(char* output) const; + void getDateStr(char* output) const; + void getWeekDayStr(char* output) const; uint8_t getSecond() const { return _second; } uint8_t getMinute() const { return _minute; } uint8_t getHour() const { return _hour; } - uint8_t getDOW() const { return _dayOfWeek; } + uint8_t getWeekDay() const { return _weekDay; } uint8_t getDay() const { return _day; } uint8_t getMonth() const { return _month; } uint16_t getYear() const { return _year; } - private: - uint8_t decToBcd(uint8_t val); - uint8_t bcdToDec(uint8_t val); + uint8_t DecToBcd(uint8_t val); + uint8_t BcdToDec(uint8_t val); + +private: uint8_t _second; uint8_t _minute; uint8_t _hour; - uint8_t _dayOfWeek; // day of week, 1 = Monday + uint8_t _weekDay; // day of week, 1 = Monday uint8_t _day; uint8_t _month; uint16_t _year; }; - -//Запись двухбайтового числа в память -void EEPROMWriteInt(int address, int value); - - -//Чтение числа из памяти -unsigned int EEPROMReadInt(int address); - #endif // TROYKARTC_H_ diff --git a/examples/testClock/testClock.ino b/examples/testClock/testClock.ino index 2a37d8e..4a18f81 100644 --- a/examples/testClock/testClock.ino +++ b/examples/testClock/testClock.ino @@ -3,20 +3,23 @@ // библиотека для работы с часами реального времени #include "TroykaRTC.h" -// EEPROM — энергонезависимая память -// библиотека для записи и считывания информации с EEPROM -#include - -// размер массива для времени с учётом завершающего нуля +// размер массива для времени #define LEN_TIME 12 -// размер массива для даты с учётом завершающего нуля +// размер массива для даты #define LEN_DATE 12 -// размер массива для дня недели с учётом завершающего нуля +// размер массива для дня недели #define LEN_DOW 12 // создаём объект для работы с часами реального времени RTC clock; +// массив для хранения текущего времени +char time[LEN_TIME]; +// массив для хранения текущей даты +char date[LEN_DATE]; +// массив для хранения текущего дня недели +char weekDay[LEN_DOW]; + void setup() { // открываем последовательный порт @@ -24,37 +27,25 @@ void setup() // инициализация часов clock.begin(); // метод установки времени и даты в модуль вручную - // clock.set(10,25,45,27,07,2005,THURSDAY); + // clock.set(10,25,45,27,07,2005,THURSDAY); // метод установки времени и даты автоматически при компиляции clock.set(__TIMESTAMP__); + // что бы время менялось при прошивки или сбросе питания + // закоментируйте оба метода clock.set(); } void loop() { - // массив для хранения текущего времени - char time[LEN_TIME]={0}; - // массив для хранения текущей даты - char date[LEN_DATE]={0}; - // массив для хранения текущего дня недели - char dow[LEN_DOW]={0}; - // запрашиваем данные с часов clock.read(); - - // сохраняем текущее время в массив time - clock.getTimeStr(time, LEN_TIME); - // сохраняем текущую дату в массив date - clock.getDateStr(date, LEN_DATE); - // сохраняем текущий день недели в массив dow - clock.getDOWStr(dow, LEN_DOW); - + // сохраняем текущее время, дату и день недели в переменные + clock.getTimeStamp(time, date, weekDay); // выводим в serial порт текущее время, дату и день недели Serial.print(time); - Serial.print("--"); + Serial.print("\t"); Serial.print(date); - Serial.print("--"); - Serial.println(dow); - + Serial.print("\t"); + Serial.println(weekDay); // ждём одну секунду delay(1000); }