/* Title: I2C_Master_Software_DS3231_1.ino Author: Florin Dragan florind@mas.utcluj.ro Date Created: 01-10-2017 Last Modified: 02-04-2020 Purpose: This is an example how to communicate with DS32310 RTC (Real Time Clock) chip, using I2C interface with Arduino's Wire library implementation */ #include /* The I2C address of the DS3231 chip. Default is b110100|x (R/W bit) */ True Address byte will be 0x68 <<1 = 0xD0|R/W bit (0xD0 or 0xD1) #define DS3231_ADDRESS 0x68 uint8_t ss, mm, hh, dw, d, m, y, TL ; int8_t TH; uint16_t y2k ; /* Conversion functions from bcd to bin and vice versa */ uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); /* valbin = valbcd - 6 * (valbcd / 16) */ } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); /* valbcd = valbin + 6 * (valbin / 10) */ } /* Returns the value (8 bits) of a single register. Remember that the values of the first 14 registers 0x00 to 0x0D are in BCD format. You can use the bin2bcd() or bcd2bin() methods to convert values as necessary */ uint8_t Get_Register(uint8_t reg) { /* Wake the I2C device */ Wire.beginTransmission(DS3231_ADDRESS); /* Advance its internal register pointer.*/ Wire.write(reg); /* End the transmission */ Wire.endTransmission(); /* Request 1 byte from device */ Wire.requestFrom(DS3231_ADDRESS, 1); /* Reads register value and returns it */ return Wire.read(); } /* Sets the value (8 bits) of a single register. Remember that the values of the first 14 registers 0x00 to 0x0D are in BCD format. You can use the bin2bcd() or bcd2bin() methods to convert as necessary */ void Set_Register(uint8_t reg, uint8_t value) { /* Wake the I2C device */ Wire.beginTransmission(DS3231_ADDRESS); Wire.write(reg); /* Advance its internal register pointer. */ /* Write data bytes...*/ Wire.write(value); /* End the transmission */ Wire.endTransmission(); } /* Initialize some things */ void setup() { Serial.begin(9600); Wire.begin(); } /* Main loop */ void loop() { /* Listen on serial COM port for new Date/Time values */ if (Serial.available() > 0) { /* Get incoming byte: must be NULL, 0x00 */ if (Serial.read() == 0x00) { d = Serial.read(); m = Serial.read(); y = Serial.read(); hh = Serial.read(); mm = Serial.read(); ss = Serial.read(); /* This will runs only if there are some data on serial port!!! */ Set_DateTime(); delay(1000); } else { /* This sequence will empty the read buffer */ while (Serial.available) Serial.read(); } } //end if (Serial.available).. /* Wake the I2C device */ Wire.beginTransmission(DS3231_ADDRESS); /* Set its internal register pointer.*/ Wire.write(0); /* End the transmission */ Wire.endTransmission(); /* Request 7 bytes from device */ Wire.requestFrom(DS3231_ADDRESS, 7); / Read 7 bytes of data...*/ ss = bcd2bin(Wire.read() & 0x7F); mm = bcd2bin(Wire.read()); hh = bcd2bin(Wire.read()); dw = Wire.read(); // The day of week. d = bcd2bin(Wire.read()); m = bcd2bin(Wire.read()); y = bcd2bin(Wire.read()); /* Calculate full fprmat of Year, ex. 2020 */ y2k = 2000 + y; /* Read Temperature */ Wire.beginTransmission(DS3231_ADDRESS); /* Advance the internal register pointer to 0x11.*/ Wire.write(0x11); /* Send the STOP transmission sequence */ Wire.endTransmission(); /* Request 2 bytes from device TH and TL */ Wire.requestFrom(DS3231_ADDRESS, 2); /*See the DS3231 datasheet for more details */ TH = (Wire.read()); TL = (Wire.read()>>6)*25; /* Display results on COM port. Add leading "zeros" if values are < 10 */ if(d<10) Serial.write(0x30); Serial.print(d); Serial.print("-"); if(m<10) Serial.write(0x30); Serial.print(m); Serial.print("-"); Serial.print(y+2000); Serial.print(" "); if(hh<10) Serial.write(0x30); Serial.print(hh); Serial.print(":"); if(mm<10) Serial.write(0x30); Serial.print(mm); Serial.print(":"); if(ss<10) Serial.write(0x30); Serial.print(ss); Serial.print(" T="); Serial.print(TH); Serial.print(","); Serial.print(TL); Serial.println("*C"); /* If you want more line spacing, use the line bellow */ // Serial.write(0x0A); delay(1000); } //end loop /* Set new Date/Time, by writting new values into registers */ void Set_DateTime() { /* Wake the I2C device by sending it's address */ Wire.beginTransmission(DS3231_ADDRESS); /* Set internal register pointer to 0x00 */ Wire.write(0); /* write data, convert if needed Wire.write(bin2bcd(ss)); Wire.write(bin2bcd(mm)); Wire.write(bin2bcd(hh)); /* Skip the day of week (1-7). Its value will be calculated automatically after */ Wire.write(bin2bcd(0)); Wire.write(bin2bcd(d)); Wire.write(bin2bcd(m)); Wire.write(bin2bcd(y)); /* End the transmission */ Wire.endTransmission(); }