#include "Wire.h" #include "time.h" // 7-bit RTC address on the I2C bus, specified in the datasheet #define RTC_ADDR 0x68 #define RTC_DATA_SIZE 7 // Specify 1 to set a new time at initialization #define RTC_SET_NEW_TIME 0 uint8_t rxBytes[15]; struct tm newTime; char str[32]; void setup() { Serial.begin(115200); Serial.println("Start I2C rtc"); // Initializing the device as a master on the I2C bus Wire.begin(); // Set new time if necessary if (RTC_SET_NEW_TIME) writeTimeToRtc(); // setting time is written inside the function } void loop() { // Read and display the current time readTimeFromRtc(); delay(2000); } // ------------------- rtc ------------------- // // Function to write new time to rtc void writeTimeToRtc(void) { /* The data to be written is located in the common buffer. First, the register address is specified - writing starts from register 0x00. Next, the values ​​of seconds, minutes, etc. are listed in accordance with the order of the corresponding registers, specified in the datasheet for ds1307. The values ​​are pre-translated into binary-decimal format */ // sec min hour wday mday month year uint8_t buf[] = {0x00, dec2bcd(00), dec2bcd(01), dec2bcd(12), dec2bcd(2), dec2bcd(1), dec2bcd(1), dec2bcd(24)}; Wire.beginTransmission(RTC_ADDR); // Start of transaction Wire.write(buf, sizeof(buf)); // Writing data for a transaction uint8_t result = Wire.endTransmission(); // Completing a transaction // Show results if (result == 0) Serial.println("New time successfully set"); else Serial.println("New time set failed"); } // Function to read time from rtc void readTimeFromRtc(void) { /* Send a request to receive data from rtc. When reading from rtc, you must first specify from which register to start reading. To do this, use the extended version of the requestFrom() function. In the arguments specify: - device address, - the number of bytes we want to read, - the address of the starting register, - the size of the address of the starting register in bytes, - 1 - generate a stop condition after the request, 0 - do not generate */ Wire.requestFrom(RTC_ADDR, RTC_DATA_SIZE, 0x00, 1, 1); // Get data uint8_t i = 0; while(Wire.available()) rxBytes[i++] = Wire.read(); // Show new time in the port upon successful reading if (i == RTC_DATA_SIZE) parseAndShowTime(); else Serial.println("New time read failed"); } // Functions for converting binary-decimal code to decimal and back uint8_t bcd2dec(uint8_t val) { return (val >> 4) * 10 + (val & 0x0f); } uint8_t dec2bcd(uint8_t val) { return ((val / 10) << 4) + (val % 10); } // Function for format and output the current time to the port void parseAndShowTime(void) { /* take the values ​​for time output from the received data buffer. Convert the values ​​into decimal format and adjust them in accordance with the datasheet for ds1307 */ newTime.tm_sec = bcd2dec(rxBytes[0] & 0x7f); newTime.tm_min = bcd2dec(rxBytes[1]); if (rxBytes[2] & (1 << 6)) { // RTC in 12 hour mode newTime.tm_hour = bcd2dec(rxBytes[2] & 0x1f) - 1; if (rxBytes[2] & (1 << 5)) newTime.tm_hour += 12; } else newTime.tm_hour = bcd2dec(rxBytes[2] & 0x3f); newTime.tm_wday = bcd2dec(rxBytes[3])-1; newTime.tm_mday = bcd2dec(rxBytes[4]); newTime.tm_mon = bcd2dec(rxBytes[5])-1; // Subtract 1900 so that the year is correctly displayed in the struct tm type structure newTime.tm_year = bcd2dec(rxBytes[6])+2000-1900; // The received time is output to the port in the format Sun Aug 19 02:56:02 2012 strftime(str, sizeof(str), "%c", &newTime); Serial.println(str); }