DS3231 – connection of a real time clock. Clock - designer on a high-precision (extremely accurate I2C) chip DS3231 SDA and SCL pins on different Arduino boards

💖 Do you like it? Share the link with your friends

Why is all this needed?

60sec * 60min *24 hours * 365 days = 31,536,000 seconds per year.

For each of these millions, 2 seconds can go in one direction or another. Divide 31.5 million by a million and multiply by 2: we get 63 seconds per year (maximum). Acceptable option? Very. But once every six months I would synchronize the time so that it fits into 1 minute.

In what ways can you generally set the time on the module clock?

Traditionally, starting with the DS3107 module, the time was set using an Arduino sketch from among the examples of using the library. The algorithm is as follows: open the sketch, click “compile and upload”, and when the controller is launched for the first time, the time is set. The question remains: what time? How can Arduino know exactly what time to set? And it’s very simple - sketch compilation time. However, I see several disadvantages with this approach:
  • compilation time depends on the “power” of the computer;
  • the download time depends on the speed at which the compiled sketch is transferred to the Arduino board;
  • the uploaded sketch is “disposable” (it becomes obsolete immediately after uploading to Arduino).
How can you “work around” to get around these restrictions? Well, for example, knowing (experimentally setting) the compilation time, you can “drive” the clock on the computer forward to this time. Then run the compilation, flash the board, and the time will be set. The advantage of the method is its relative simplicity. Disadvantages - relatively inconvenient, relatively inaccurate, one-time method.

What else can you think of? You can, for example, set the required time in the sketch manually, provide a button that can be pressed right moment will set the specified time “by hand”, for example, 2 minutes from the current moment: while the sketch is “filled”, while we prepare to manually track the very necessary moment of pressing the button, just that couple of minutes will pass. And then, looking at the clock on the computer, wait for “that very” moment to press the button. Pros - more difficult previous method, but still relatively simple, but more accurate than the first method. Disadvantages - this method is even more inconvenient, it takes longer, and it’s still a “one-time” sketch.

Who is to blame and what to do?

Having asked myself these two rhetorical questions, I went to the Internet to look for who had already written the time synchronization of the clock module with the computer. And, as you know, he who seeks always finds. I found an option with . In theory, everything is simple: a regular “batch file” parses the current full time obtained in the “first” method (because in addition to the time itself, you also need a date), increases the time by 2 seconds, and “drives” an empty loop until the moment when this new one arrives , “plus_two_seconds”, time to “throw” data into the COM port. Moreover, the “new plus_two_seconds” time is tracked in a different way (via %time%, if anyone is interested). But about the “jambs” of such a decision later. The data “thrown out” into the COM port is parsed by Arduino and then sets the time in the module. Everything seems simple, logical and convenient. But there is a very bad word “BUT”. All this seems to have been written by a German, and his regional standards in Windows differ from “ours”, and in particular, the fractional part is separated by a dot, not a comma. When launched with domestic regional standards, the batch file does not work, because in it the time to exit the empty loop is described by the comparison condition with XX:XX:XX.xxx. Well, you need to put a comma instead of a period - and that’s it, “I fixed everything.” But that’s not all (you can check who else remembers what kind of evil it is to program in “batch books”). The body file needs to be corrected more seriously. And I fixed it using “rewind mats” and a “manual” for DOS. The "Batnik" fixed it, but the sketch still didn't work - the time was not set. That is, data was sent to the port, Arduino saw it, but “something went wrong.”

Let's take a look at what the batch file sends to Arduino and in what format (for reference).

Case 83: //S = second case 68: //D = Minute (Daghigheh in Persian) case 72: //H = Hour case 84: //T = Day Of Month (Tag in German) case 77: /// M = Month case 74: /// J = Year (Jahr in German)
Data is sent in the format S**~D**~H**~T*~M**~J****~, where ~ is 2 bytes of carriage return. Total, 31 bytes. It doesn’t seem like much, the data will be sent quickly.

However, there is also an inconvenience - as you can see, the day of the week is not sent. Only the day of the month. There will be a problem with implementing clocks with alarms that depend on the days of the week. The day of the week will have to be set “by hand” in the sketch, which again hints at some “disposability” of the sketch, its inferiority.

Adding up the factors - the inferiority of the sketch "from the factory", its refusal to work normally, the need to correct the "body file" for "our" latitudes - I decided to develop everything on my own. And if so, then I can eliminate the shortcomings and optimize the data format.

Software and hardware.

In order for everything to work, you need 2 components: a program for Windows and an Arduino hardware-software combination.

First, general data on the exchange protocol. Once I was free to choose the data format to be sent, I decided that sending 31 bytes of information was not rational, and reduced the transmitted data to 4 bytes. So, was that enough? What can you put in 4 bytes? Yes, that's enough. Everything you need fits in. I'm sure many have guessed what 4 bytes are. For those who haven’t guessed, I’ll quote a fragment of an article from Wikipedia:

UNIX time (POSIX time) - a system for describing moments in time, adopted in UNIX and other POSIX-compatible operating systems. Defined as the number of seconds that have passed since midnight (00:00:00 UTC) January 1, 1970 (Thursday).
UNIX time is represented as an integer that increases with each passing second without the need for calculations to determine the year, month, day, hour, or minute for human readability. Modern UNIX time is consistent with UTC - counting occurs in SI seconds.

So, the integer that stores UNIX time takes up 4 bytes, which is enough to last up to 2,147,483,648 seconds. And then possible potential problems. Why potential? Because this is the threshold at which the number Maybe be interpreted as negative (as with the iPhones of many curious comrades at one time). Maybe, but it won’t necessarily happen - it depends on whether the programmers’ hands grow from the place provided by nature. The number of seconds indicated corresponds to 03:14:08 19-Jan-2038. Until this time, you can slowly switch to a 64-bit version of the OS, where time will be stored in an 8-byte variable, which will easily last for the next 292 billion years. There is a possibility that this will be enough for our lifetime. And then you will have to upgrade to the 128-bit version of UNIX.

What problems did I solve by coming to this option? First, it greatly reduced the number of bytes transferred, which increases the accuracy of time setting by milliseconds. Great, right? And two: I (probably) made Linux compatibility easier. To my shame, I can’t get used to Linux and mostly use only Windows. I can write a forwarding program for this very Windows, but not for Linux. But I believe that in Linux you can get the UNIX time value much more easily than in Windows, and send this number to the COM port.

None additional There is no need to transmit data such as the day of the week and so on. UNIX time only. Everything else is done in Arduino.

Now a little specifics directly about first component - a program for Windows. The program is written in good old Delphi. When launched, a pop-up window asks you to select a COM port to send data to. Let's choose. The remaining settings should be left as default.

How does the program work? It recalculates from the time format Windows data for UNIX format, that is, the number of seconds since midnight January 1, 1970. Then it adds 3 seconds and “falls” into an empty loop (obviously lasting less than those extra 3 seconds), exiting from which occurs in the required number of seconds, as close to 000 milliseconds as possible. In other words, the occurrence of the very beginning of that second of time is monitored, the value of which will have to be sent to Arduino. Agree, sending data that, for example, now is XXXXXXXXX5 seconds when in fact it is already, for example, XXXXXXXXX5 and 756 thousandths (for example) seconds, would not be correct. This is why you need to track the very beginning of the second to start data transfer. After transferring the data, the program friendlyly reports the status “Done:)”. This completes the mission of the program.


Second component - hardware and software - Arduino. There are 2 varieties hardware for this project: a “full” version with a screen and a button, and a “stripped-down” version for quick installation module time, assembled from “shit and sticks.” About their differences - below. The “full” version consists of an Arduino Nano, a 1602 shield with an “adapter” from I2C to the shield, an optional Arduino reset button and a pin header (female) for connecting the clock module. Also, optionally, from the device body with a “cute” sticker. The “stripped-down” version consists of an Arduino (Uno, Nano, Pro Mini + the “correct” USB adapter with DTR) and 4 wires for connecting the clock module.



As can be seen from the diagrams, the “full” version, in addition to the “stripped down” version, contains a reset button and a 1602 screen with an “adapter”. Both versions are absolutely identical in the main functionality - setting the time. The screen is only needed to display the stages of the process and , upon completion of the process of setting the time, the newly set time, date and day of the week will be displayed. Moreover, by that time the data will already be read from the clock module itself. In the “stripped-down” version, the role of the screen is played by the LED built into the Arduino board: after the process of setting the new time, it will start to light up. That's all the indication.

What is the reset button for? For what's in full version after setting the time, the Arduino will enter endless cycle by displaying that very newly set time, that is, in fact, it will become a clock. Moreover, they are watches made in haste, and therefore they cannot replace a normal watch for several reasons (the selection of seconds is implemented via delay, the time display will disappear when the power is turned off). After all, the goal is to make sure that the time is synchronized correctly, nothing more. Therefore, to synchronize the next clock module, you can’t do without a reset (more precisely, you can do it if you “distort” USB cable). In other words, the purpose of the button is purely utilitarian. If you wish, you can do without it.

How to flash Arduino, since there are two hardware versions, but only one sketch? To compile the “correct” version of the firmware, you need to set the desired parameter value in the sketch header fullVersion: true for the "full" version, or false - for “stripped down”. The compiler will thus determine for which version of hardware to compile the firmware.

So, we have the connection diagram, we need the sketch code. Please note that for the sketch to work properly with the “full” version, a library is needed LiquidCrystal I2C by Frank de Brabander(installed from the repository using the Library Manager). We also need a library to support the clock module, and not just any one :). Download here: . We've sorted out the libraries.

Here's the code for the sketch:

//====================================================== setting available for change === ===================================== #define fullVersion true //true = "full" version with screen; false = "stripped down" version with built-in LED //================================================ used libraries and declaration of variables = =================================== #include #include #if (fullVersion) #include #endif unsigned long t1 = 0; //variable for the received time unsigned long t2 = 0; //variable for the received time byte b; //buffer for receiving data from the COM port #if (fullVersion) byte day = 0; #endif DS3231 clock; RTCDateTime dat1; #if (fullVersion) LiquidCrystal_I2C lcd(0x3F,16,2); //Chinese people love the new address for “adapters” from i2c to screen #endif //================================ ===================================================== ==================================== void setup())( #if (!fullVersion) // relevant only for "truncated" version - the beginning of the code section pinMode(13, OUTPUT); digitalWrite(13,LOW); #endif //relevant only for the "trimmed" version - the end of the code section clock.begin(); Serial.begin(9600); #if (fullVersion) //relevant only for the “full” version - the beginning of the code section lcd.init(); lcd.backlight(); lcd.setCursor(0,0); lcd.print("COMport 9600 8N1"); //hint which COM port parameters to select in the program lcd.setCursor(0,1); lcd.print("Ready to sync"); //status message - ready for synchronization delay(1000); #endif //relevant only for the "full" version - the end of the code section) void loop())( if (Serial.available())( //if there is "gunpowder in the flask" of the COM port Serial.readBytes(b,4); //count all 4 bytes (we don’t expect anything else) t1=b; t2=(t1<<24); //поместить значение байта в 4-байтную переменную и передвинуть его на 3 байта влево t1=b; t2+=(t1<<16); //поместить значение байта в 4-байтную переменную и передвинуть его на 2 байта влево t1=b; t2+=(t1<<8); //поместить значение байта в 4-байтную переменную и передвинуть его на 1 байт влево t2+=b; //поместить значение байта в 4-байтную переменную clock.setDateTime(t2); //установить полученное время на DS3231 #if (fullVersion) //актуально только для "полной" версии - начало участка кода lcd.clear(); lcd.setCursor(0,0); lcd.print("Done:) : :"); while (true){ //начало бесконечного цикла по отображению свежеустановленных времени и даты dat1 = clock.getDateTime(); if (dat1.day != day){ day = dat1.day; lcd.setCursor(0,1); if (dat1.day < 10) lcd.print("0"); lcd.print(day); lcd.print("-"); switch (dat1.month){ //выбираем буквенное соответствие месяца по цифре case 1:{ lcd.print("Jan"); break; } case 2:{ lcd.print("Feb"); break; } case 3:{ lcd.print("Mar"); break; } case 4:{ lcd.print("Apr"); break; } case 5:{ lcd.print("May"); break; } case 6:{ lcd.print("Jun"); break; } case 7:{ lcd.print("Jul"); break; } case 8:{ lcd.print("Aug"); break; } case 9:{ lcd.print("Sep"); break; } case 10:{ lcd.print("Oct"); break; } case 11:{ lcd.print("Nov"); break; } case 12:{ lcd.print("Dec"); break; } default:{ lcd.print("???"); break; } }//switch month lcd.print("-"); lcd.print(dat1.year); lcd.print(" "); switch(dat1.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; } default:{ lcd.print("???"); break; } }//switch dayOfWeek }//if date changed lcd.setCursor(8,0); if (dat1.hour < 10) lcd.print("0"); lcd.print(dat1.hour); lcd.setCursor(11,0); if (dat1.minute < 10) lcd.print("0"); lcd.print(dat1.minute); lcd.setCursor(14,0); if (dat1.second < 10) lcd.print("0"); lcd.print(dat1.second); delay(995); }//while #else //актуально только для "урезанной" версии - начало участка кода digitalWrite(13, HIGH); delay(3000); digitalWrite(13, LOW); #endif //актуально только для "полной" версии - конец участка кода }//if Serial }//loop


A couple of photos of the “full” version of the finished device.


And finally, a video of the device working “in battle”:

Where can I download the sketch and program?

Download sketch (Dropbox).
Download the program for Windows (Dropbox).

"Advantages and disadvantages".

It is difficult to formulate “pros” and “cons” in this case. Consequently, everyone decides for themselves what is good and what is bad.

Total.

I really liked how the time is now set in modules! When I need to set the time, I don’t have to remember every time what sketch I need and think about how accurately the time will be set in the module. Moreover, there will soon be a review of a homemade clock where I have built in such a synchronization method - I liked the method so much. I hope some of the readers will also find this method useful.

The project is free, non-commercial. Everyone has the right to use data from the review for any purpose other than commercial.

All the best.

I'm planning to buy +48 Add to favorites I liked the review +60 +114

The DS3231 module (RTC, ZS-042) is a low-cost board with an extremely accurate real-time clock (RTC), with temperature compensation of the crystal oscillator and crystal. The module includes a lithium battery that maintains uninterrupted operation even when the power supply is turned off. An integrated generator improves the accuracy of the device and reduces the number of components.

Technical specifications

Supply voltage: 3.3V and 5V
Memory chip: AT24C32 (32 KB)
Accuracy: ±0.432 sec per day
Quartz frequency: 32.768 kHz
Supported protocol: I2C
Dimensions: 38mm x 22mm x 15mm

General information

Most microcircuits, such as DS1307, use an external quartz oscillator with a frequency of 32 kHz, but they have a significant drawback: when the temperature changes, the quartz frequency changes, which leads to an error in timing. This problem is eliminated in the DS3231 chip, which contains a crystal oscillator and a temperature sensor that compensates for temperature changes so that the time remains accurate (temperature data can be read if necessary). The DS3231 chip also supports seconds, minutes, hours, day of the week, date, month and year information, and also monitors the number of days in a month and makes adjustments for leap years. It supports clocks in two formats: 24 and 12, and it is also possible to program two alarms. The module operates on a two-wire I2C bus.


Now a little about the module itself; it is built on the DS3231N chip. Resistor assembly RP1 (4.7 kOhm) is required to pull up the 32K, SQW, SCL and SDA lines (by the way, if several modules with an I2C bus are used, it is necessary to unsolder the pull-up resistors on other modules). The second assembly of resistors is necessary to tighten up the lines A0, A1 and A2; they are needed to change the addressing of the AT24C32N memory chip. Resistor R5 and diode D1 serve to recharge the battery; in principle, they can be removed, since a regular SR2032 battery lasts for years. An AT24C32N memory chip is also installed, this is like a bonus; it is not necessary for the RTC DS3231N clock to work. Resistor R1 and the Power LED signal that the module is turned on. As mentioned, the module operates on the I2C bus; for convenience, these buses were routed to two connectors J1 and J2; the assignment of the remaining contacts can be seen below. Purpose J1
32K: output, frequency 32 kHz
SQW: output
SDA: data line (Serial Dфta)
VCC: “+” module power supply
GND: “-” module power supply Purpose J2
SCL: Serial CLock
SDA: Serial Data Line
VCC: “+” module power supply
GND: “-” module power supply


I’ll tell you a little about the AT24C32N chip, this is a chip with 32k memory (EEPROM) from the manufacturer Atmel, assembled in a SOIC8 package, operating on a two-wire I2C bus. The address of the microcircuit is 0x57; if necessary, it can be easily changed using jumpers A0, A1 and A2 (this allows you to increase the number of connected AT24C32/64 microcircuits). Since the AT24C32N chip has three address inputs (A0, A1 and A2), which can be in two states, either log “1” or log “0”, eight addresses are available to the chip. from 0x50 to 0x57.

Connecting DS3231 to Arduino

Required parts:
Arduino UNO R3 x 1 pc.
Real time clock on DS3231, RTC, SPI, AT24C32 x 1 pc.
DuPont wire, 2.54 mm, 20 cm, F-M (Female - Male) x 1 pc.
USB 2.0 A-B cable x 1 pc.

Connection:
In this example, I will use only the DS3231 module and Arduino UNO R3, all data will be transferred to “Port Monitoring”. The circuit is not complicated, only four wires are needed, first we connect the I2C bus, SCL in A4 (Arduino UNO) and SDA in A5 (Arduino UNO), all that remains is to connect the power supply GND to GND and VCC to 5V (can be written from 3.3V), circuit assembled, now we need to prepare the software part.

There is no library that works with the DS3231 in the Arduino IDE, you need to download “DS3231” and add it to the Arduino development environment.

Setting the DS3231 time
When you turn it on for the first time, you need to program the time, open the example from the DS3231 library “File” -> “Examples” -> “DS3231” -> “Arduino” -> “DS3231_Serial_Easy”, or copy the code from below

/* Testing was carried out on Arduino IDE 1.8.0 Test date 08/31/2018. */ #include // Connect the Wire DS3231 library rtc(SDA, SCL); // Initialize DS3231 void setup() ( Serial.begin(115200); // Set up a serial connection rtc.begin(); // Initialize rtc // Set the time rtc.setDOW(FRIDAY); // Set the day of the week rtc. setTime(16, 29, 0); // Set the time to 16:29:00 (24 hour format) rtc.setDate(31, 8, 2018); // Set the date to August 31, 2018) void loop() ( Serial. print(rtc.getDOWStr()); // Send the day-week Serial.print(" "); Serial.print(rtc.getDateStr()); // Send the date Serial.print(" -- "); Serial. println(rtc.getTimeStr()); // Send time delay (1000); // Delay one second)

Testing was carried out on Arduino IDE 1.8.0

Test date: 08/31/2018

#include // Include the Wire library

DS3231 rtc (SDA, SCL); // Initialize DS3231

void setup()

Serial. begin(115200); // Establish a serial connection

rtc. begin(); // Initialize rtc

// Set the time

rtc. setDOW(FRIDAY); // Set day-of-week

rtc. setTime(16, 29, 0); // Set the time to 16:29:00 (24 hour format)

void loop()

Serial. print (rtc . getDOWStr () ) ; // Send day-week

Serial. print (" " ) ;

Serial. print (rtc . getDateStr () ) ; // Send the date

Serial. print (" -- " ) ;

Serial. println(rtc. getTimeStr()); // Send time

delay(1000); // One second delay

Upload the sketch to the Arduino controller and open “Port Monitoring”

The DS3231 chip is a high-precision RTC real-time clock that has a built-in temperature-compensated quartz oscillator, resulting in time drift of only ±2 minutes per year. Additionally, an alarm function is implemented, and there is also an interrupt output. The clock can be purchased as a ready-made Arduino module with strapping elements and a battery compartment.

I ordered the module here. The diagram is shown in the picture below:


The microcircuit uses the widely used . Supports standard (100 kHz) and high (400 kHz) data rates. The microcircuit address (7 bits) on the I2C bus is 1101000. Additionally, the module has I2C memory (24C32), not shown in the diagram.

Power Modes

The supply voltage of the microcircuit can be in the range of 2.3...5.5V, there are two power lines, for an external source (Vcc line), as well as for the battery (Vbat). The external source voltage is constantly monitored, and when it drops below the threshold Vpf=2.5V, it switches to the battery line. The following table shows the conditions for switching between power lines:

The watch's accuracy is maintained by monitoring the ambient temperature. The microcircuit starts an internal procedure for adjusting the frequency of the clock generator; the amount of adjustment is determined using a special graph of frequency versus temperature. The procedure starts after power is applied and then runs every 64 seconds.

In order to conserve charge, when the battery is connected (voltage is applied to the Vbat line), the clock generator does not start until the voltage on the Vcc line exceeds the threshold value Vpf, or the correct address of the microcircuit is transmitted via the I2C interface. The clock generator startup time is less than one second. Approximately 2 seconds after power is applied (Vcc), or the address is received via the I2C interface, the frequency correction procedure starts. Once the clock generator has started, it continues to operate as long as Vcc or Vbat is present. When turned on for the first time, the date and time registers are reset and have the following values: 01/01/00 – 01 – 00/00/00 (day/month/year/ – day of the week – hour/minutes/seconds).

The current consumption when powered by a 3.63V battery is 3 µA, in the absence of data transmission via the I2C interface. The maximum current consumption can reach 300 µA when using an external 5.5V power supply and high I2C data transfer speed.

External reset function

The RST line can be used for external reset and also has a low voltage alarm function. The line is pulled high through an internal resistor; no external pull-up is required. To use the external reset function, a button can be connected between the RST line and the common wire; the microcircuit has protection against contact bounce. The alarm function is activated when the supply voltage Vcc drops below the threshold value Vpf, while the RST line is set to a low logic level.

Description of DS3231 registers

The table below shows a list of real-time clock registers:

AddressD7D6D5D4D3D2D1D0FunctionLimits
0x000 10 SecondsSecondsSeconds00-59
0x010 10 minutesminutesminutes00-59
0x020 12/24 AM/PM10 hoursHourWatch1-12 + AM/PM or 00-23
10 hours
0x030 0 0 0 0 DayDay of the week1-7
0x040 0 10thNumberdate01-31
0x05Century0 0 10 monthMonthMonths/century01-12 + Century
0x0610 yearsYearYears00-99
0x07A1M110 SecondsSecondsSeconds, 1st alarm00-59
0x08A1M210 minutesminutesMinutes, 1st alarm00-59
0x09A1M312/24 AM/PM10 hoursHourClock, 1st alarm1-12 + AM/PM or 00-23
10 hours
0x0AA1M4DY/DT10thDayDay of the week, 1st alarm1-7
NumberDate, 1st alarm01-31
0x0BA2M210 minutesminutesMinutes, 2nd alarm00-59
0x0CA2M312/24 AM/PM10 hoursHourClock, 2nd alarm1-12 + AM/PM or 00-23
10 hours
0x0DA2M4DY/DT10thDayDay of the week, 2nd alarm1-7
NumberDate, 2nd alarm01-31
0x0EEOSCBBSQWCONVRS2RS1INTCNA2IEA1IESettings register (Control)
0x0FO.S.F.0 0 0 EN32kHzBSYA2FA1FStatus Register
0x10SIGNDATADATADATADATADATADATADATAAging Offset Register
0x11SIGNDATADATADATADATADATADATADATATemperature register, high byte
0x12DATADATA0 0 0 0 0 0 Temperature register, low byte

Time information is stored in binary decimal format, that is, each digit of a decimal number (from 0 to 9) is represented as a group of 4 bits. In the case of one byte, the low nibble counts ones, the high nibble counts tens, etc. Time is counted in registers with addresses 0x00-0x06; for counting hours, you can select the 12 or 24 hour mode. Setting the 6th bit of the clock register (address 0x02) sets the 12-hour mode, in which the 5th bit indicates the time of day, value 1 corresponds to afternoon (PM), value 0 corresponds to afternoon (AM). The zero value of the 6th bit corresponds to the 24-hour mode, here the 5th bit is involved in counting the hours (values ​​20-23).

The day of the week register is incremented at midnight, counting from 1 to 7, the month register (address 0x05) contains the Century bit (7th bit), which switches when the years counting register (address 0x06) overflows, from 99 to 00.

The DS3231 chip implements two alarm clocks, the 1st alarm clock is configured using registers with addresses 0x07-0x0A, the 2nd alarm clock is configured using registers 0x0B-0x0D. The A1Mx and A2Mx bits can be used to configure various modes for alarms; setting the bit excludes the corresponding register from the comparison operation. The tables below show the bit combinations for different alarm modes:

Bit combinations not specified in the tables lead to incorrect functioning of alarms. If the DY/DT bit is cleared, then the date match (day of the month) is monitored for the alarm clock; when the DY/DT bit is set, the match of the day of the week is checked.

Most functions are configured in the Control register. The EOSC bit controls the start of the clock generator, resetting the bit starts the clock generator. Setting the bit stops the generator, for battery mode (Vbat) only. When powered from an external source (Vcc), the oscillator is always running regardless of the state of the EOSC bit. When enabled, the default bit value is 0.

Setting the BBSQW bit allows the INT/SQW output (3rd pin) to operate in battery power mode, in the absence of external power. When the bit is set to zero, the INT/SQW output goes into state 3 (deactivated) if the external source voltage Vcc falls below the threshold value Vpf. After power is applied, the default bit value is 0.

The CONV bit is responsible for forced temperature measurement; setting the bit starts the conversion process, during which the clock generator frequency is also adjusted; the measurement result is located in registers with addresses 0x11, 0x12. Starting is possible only if the previous conversion has completed; before starting, you need to check the busy flag BSY. Forced temperature conversion does not affect the internal 64 second frequency adjustment cycle. Setting the CONV bit does not affect the BSY flag for 2 ms. The CONV and BSY bits are cleared automatically after conversion is complete.

Bits RS2, RS1 set the frequency of rectangular pulses (square wave) at the INT/SQW output. By default, when enabled, the bits are set to 1. The table below shows the possible combinations of bits:

The INTCN bit controls the INT/SQW output. If the bit is reset, rectangular pulses (square waves) appear at the output, the frequency of which is set by the RS2, RS1 bits. When the INTCN bit is set, the output is used to generate alarm interrupts. By default, the bit value is 1. The output type is INT/SQW - open drain, therefore it is necessary to pull it up through a resistor to a high logic level, the active level is low.

Setting bits A1IE, A2IE enables interruptions on the 1st and 2nd alarm signals, respectively. Reset bits, disables interrupts. The default value is 0.

The Status register contains event flags and controls the 32 kHz output. The OSF flag reflects the state of the clock generator, a value of 1 means that the clock generator is stopped, this event can occur in the following cases:

  • For the first time after power is applied
  • Battery or external voltage is insufficient to operate the clock generator
  • The generator is turned off by setting the EOSC bit in battery mode
  • External factors affecting the crystal oscillator (noise, leakage, etc.)

Once set, the bit value does not change; the bit must be reset manually.

Setting the EN32kHz bit allows the generation of rectangular pulses (square waves) at the 32kHz output (1st pin), the pulse frequency is fixed and equal to 32.768 kHz. Resetting the bit disables this function and moves the output to the 3rd state (high input impedance). By default, the bit value is 1; after power is applied, pulses appear at the output. The output type is 32kHz open drain, so it requires a pull-up to a high logic level.

The BSY busy flag is set during the temperature conversion and clock adjustment process. The flag is reset when the conversion is complete.

Alarm clock flags A1F, A2F are set when the values ​​of the time counting registers and the alarm clock registers match. If alarm interrupts A1IE, A2IE are enabled, and an interrupt output is assigned (INTCN bit is set), then an interrupt signal appears at the INT/SQW output (transition from high to low logic level). The flags must be reset manually by writing the value 0.

The Aging Offset register is designed to adjust the clock generator frequency. The register value is added to the oscillator frequency during the internal adjustment procedure, if a temperature change is detected, and also when temperature conversion is triggered by the CONV bit. The offset value is signed, that is, positive values ​​(1-127) reduce the frequency, negative values ​​(128-255) increase it. For the same offset, the frequency change will be different depending on the temperature. At +25°C, the frequency change will be 0.1 ppm/LSB.

The current temperature value is stored in registers with addresses 0x11 and 0x12, the high and low byte, respectively, the temperature value in the registers is periodically updated. Left alignment is set, the resolution is 10 bits or 0.25°C/LSB, that is, the high byte contains the integer part of the temperature, and the 6th, 7th bits in the low registers make up the fractional part. In the high byte, the 7th bit indicates the sign of the temperature, for example, the value 00011011 01 corresponds to a temperature of +27.25 °C, the value 11111110 10 corresponds to a temperature of -2.5 °C.

When reading time registers, it is recommended to use an additional buffer, that is, read several registers at once, and not separately, since between individual reading operations, the time registers can change their value. This rule is also recommended to be followed when writing new data to account registers. Writing a new value to the seconds register pauses the clock for 1 second, the remaining registers must be rewritten during this time.

Connecting DS3231 to a microcontroller

I connected the clock to a PIC16F628A microcontroller and used . The connection diagram is shown below:


After power is applied, dashes (– – – – – –) are displayed on the indicators, then the clock is initialized, the time value appears on the indicators with a delay of 1 second, which is required to start the clock generator. The indicators display the hours, minutes and seconds, separated by a decimal point, and the time format is 24-hour. Using the SB1 “Indication” button, you can change the display format, where the indicators will display the temperature, as well as the value of hours and minutes, separated by a decimal point, which blinks at a frequency of 2 Hz. The temperature is displayed without a fractional part; the program reads only the high byte of temperature storage at address 0x11.

The time value is read from the clock via an interrupt on the SQW/INT line, which is controlled by the 1st alarm signal; during the clock initialization, the alarm clock is set to an every second signal. The HL1 LED serves as an indicator and flashes at the interrupt signal every second. The HL2 LED lights up if there is an error in data transmission via the I2C interface.

Additionally, I added to the program the ability to set the clock using the SB2 “Settings”, SB3 “Installation” buttons. The setup mode is entered by pressing the SB2 button; the indicators display 00 hours and dashes instead of minutes and seconds (00 – – – –). Using the SB3 button, you set the hour value (increment with each press), then pressing the SB2 button switches to editing the minutes; instead of a dash, 00 minutes will be displayed. Button SB3 also sets the required value and so on. After editing the seconds and pressing the SB2 button, the time in the clock is rewritten, and the updated time is displayed on the indicators.

Partial program code is given below (the full version can be downloaded at the end of the article):

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;; #include LIST p=16F628A __CONFIG H"3F10" ;Microcontroller configuration errorlevel -302 ;do not display messages with error 302 in listing Sec equ 0020h ;auxiliary account registers Sec1 equ 0021h ; Sec2 equ 0022h ; scetbit equ 0024h;auxiliary register for counting the number of bits perem equ 0025h;auxiliary register for byte reception/transmission via spi, i2c temp equ 0026h;temperature register perem_1 equ 0027h;auxiliary register for binary-decimal converter. result equ 0028h ;binary-decimal converter auxiliary register dat_ind equ 0029h ;data register for transmission via the spi protocol adr_ind equ 002Ah ;address register for transmission via the spi protocol second equ 002Bh ;seconds storage register for setting the time minut equ 002Ch ;minutes storage register for setting the time hour equ 002Dh ;hour storage register for time settings adr_i2c equ 002Eh ;registers of the i2c interface data transfer subroutine tmp_i2c equ 002Fh slave_adr equ 0030h data_i2c equ 0031h flag equ 007Fh ;flag register #DEFINE int PORTB,0 ;interrupt line INT/SQW DS3231 #DEFINE sda PORTB,1 ; SDA line for connections DS3231 #DEFINE scl PORTB,2 ;SCL line for connecting DS3231 #DEFINE sda_io TRISB,1 ;direction of the SDA line #DEFINE scl_io TRISB,2 ;direction of the SCL line #DEFINE datai PORTB,5 ;data input line of the MAX7219 driver #DEFINE cs PORTB ,6 ;driver selection line MAX7219 #DEFINE clk PORTB,7 ;driver clock line MAX7219 #DEFINE led PORTB,4 ;i2c error LED #DEFINE led_sec PORTB,3 ;clock progress indicator LED 1Hz #DEFINE regim PORTA,2 ;Indication button - changing the display mode #DEFINE nast PORTA,3 ;Setting button - entering the time setting mode #DEFINE ust PORTA,4 ;Setting button - setting the clock value;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0000h ;start program execution from address 0000h goto Start ;go to the Start label ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Main program Start movlw b"00000000" ;setting the values ​​of the output latches of port A movwf PORTA ; movlw b"01000000" ;set the values ​​of the output latches of port B movwf PORTB ; movlw b"00000111" ;turn off comparators movwf CMCON ; bsf STATUS,RP0 ;select the 1st bank movlw b"00000111" ;set up the input/output lines of port B movwf TRISB ;RB0-RB2 - for input, the rest for output movlw b"11111111" ;set up the input/output lines of port A movwf TRISA ;all lines to input bcf STATUS,RP0 ;select bank 0 clrf flag ;reset flag register call init_lcd ;call driver initialization subroutine (MAX7219) call viv_not ;output dash symbols " ------ " ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;; movlw b"11010000" ;device address (DS3231) movwf slave_adr ;Write 4 bytes to the receive/transmit registers via i2c;here the 1st alarm is configured, beeping every second movlw data_i2c ;set the first receive/transmit register via i2c movwf FSR ; movlw b"10000000" ;data for the seconds register of the 1st alarm movwf INDF ; incf FSR,F ; movlw b"10000000" ;data for the minutes register of the 1st alarm movwf INDF ; incf FSR,F ; movlw b"10000000" ;data for the clock register of the 1st alarm clock movwf INDF ; incf FSR,F ; movlw b"10000000" ;data for the date/day of week register of the 1st alarm movwf INDF ; movlw. 4 ;transfer 4 bytes via i2c movwf tmp_i2c ; movlw 0x07 ;setting the address of the seconds register of the 1st alarm clock movwf adr_i2c ; call write_i2c ;calling the writing subroutine via the i2c interface call err_prov ;checking for I2C write/read errors movlw .1 ;transferring the 1st byte via i2c movwf tmp_i2c ; movlw 0x0E ;setting the address of the Control register movwf adr_i2c ; movlw data_i2c ;setting the first transmit/receive register via i2c movwf FSR ; movlw b"00000101" ;start the clock generator, prohibit the operation of the INT/SQW pin for movwf INDF ;battery power mode, pulse frequency at the INT/SQW output is 1Hz, ;the INT/SQW output is used to generate alarm clock interrupts, ;enable alarm clock interrupts 1st alarm call write_i2c ;calling the recording subroutine via the i2c interface call err_prov ;checking for I2C write/read errors met_2 movlw .1 ;transferring the 1st byte via i2c movwf tmp_i2c ; movlw 0x0F ;setting the address of the Status register movwf adr_i2c ; movlw data_i2c ;setting the first transmit/receive register via i2c movwf FSR ; movlw b"00000000" ;reset the OSF bit, prohibit the generation of pulses at the EN32kHz output, movwf INDF ;reset the alarm interrupt flags A2F, A1F call write_i2c ;call the recording subroutine via the i2c interface call err_prov ;check for I2C write/read errors met_1 btfsc int ; polling the alarm interrupt line goto met_3; bsf led_sec ;turn on the clock progress indicator LED goto met_4 ; met_3 bcf led_sec ;turns off the clock progress indicator LED btfsc nast ;polls the clock setting button goto met_5 ; call nast_time ;call the subroutine for setting the time goto met_2 ; met_5 btfsc regim ;poll of the indication mode button goto met_1 ; met_6 call paus_knp ; btfss regim ; goto met_6 ; btfss flag,2 ;change the value of the indication mode flag goto met_7 ; bcf flag,2 ;reset indication flag, clock display mode goto met_1 ; met_7 bsf flag,2 ;setting the indication flag, temperature and clock display mode goto met_1 ; met_4 movlw .1 ;transmitting the 1st byte via i2c movwf tmp_i2c ; movlw 0x11 ;setting the address of the high temperature register movwf adr_i2c ; call read_i2c ;calling the reading subroutine via I2C call err_prov ;checking for I2C write/read errors movf INDF,W ;copying the temperature value into the temp register movwf temp rd_time movlw .3 ;transferring 3 bytes via i2c movwf tmp_i2c ; movlw 0x00 ;setting the seconds register address movwf adr_i2c ; call read_i2c ;calling the reading subroutine via I2C call err_prov ;checking for I2C write/read errors btfsc flag,2 ;poll of the indication mode flag goto met_8 ; call vivod ;calling the subroutine for displaying the clock value on the digital display goto met_2 ; met_8 call vivod_temp ;calling the subroutine for displaying the temperature and clock on the digital display goto met_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#include

CONFIG H"3F10" ;Microcontroller configuration

errorlevel -302 ;do not display 302 error messages in the listing

Sec equ 0020h ;auxiliary account registers

Sec1 equ 0021h ;

Sec2 equ 0022h ;

scetbit equ 0024h ;counting auxiliary register number of bits

perem equ 0025h ;auxiliary byte reception/transmission register via spi, i2c

temp equ 0026h ;temperature register

perem_1 equ 0027h ;BCD auxiliary register

result equ 0028h ;binary-decimal converter auxiliary register

dat_ind equ 0029h ;data register for transmission via spi protocol

adr_ind equ 002Ah ;address register for transmission via spi protocol

second equ 002Bh ;seconds storage register for setting the time

minut equ 002Ch ;minute storage register for setting the time

hour equ 002Dh ;hour storage register for setting the time

adr_i2c equ 002Eh ;registers of the i2c interface data transfer subroutine

tmp_i2c equ 002Fh

slave_adr equ 0030h

data_i2c equ 0031h

flag equ 007Fh ;flag register

#DEFINE int PORTB,0 ;interrupt line INT/SQW DS3231

#DEFINE sda PORTB,1 ;SDA line for connecting DS3231

#DEFINE scl PORTB,2 ;SCL line for connecting DS3231

#DEFINE datai PORTB,5 ;data input line of MAX7219 driver

#DEFINE cs PORTB,6 ;driver selection line MAX7219

#DEFINE clk PORTB,7 ;clock line of MAX7219 driver

#DEFINE led PORTB,4 ;i2c error LED

#DEFINE led_sec PORTB,3 ;LED clock progress indicator 1Hz

#DEFINE regim PORTA,2 ;Indication button - changes the display mode

#DEFINE nast PORTA,3 ;Settings button - enters time setting mode

#DEFINE ust PORTA,4 ;Set button - set the clock value

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

org 0000h ;start program execution from address 0000h

goto Start ;go to the Start label

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Main program

Start movlw b"00000000" ;set the values ​​of the output latches of port A

movlw b"01000000" ;set the values ​​of the output latches of port B

movlw b"00000111" ;turn off comparators

bsf STATUS,RP0 ;select 1st bank

movlw b"00000111" ;configuring the input/output lines of port B

movwf TRISB ;RB0-RB2 - to the input, the rest to the output

movlw b"11111111" ;setting up the input/output lines of port A

movwf TRISA ;all lines to input

bcf STATUS,RP0 ;select bank 0

clrf flag ;reset flag register

call init_lcd ;call the driver initialization routine (MAX7219)

call viv_not ;output dash symbols " ------ " to indicators

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

movlw b"11010000" ;device address (DS3231)

;Write 4 bytes to the receive/transmit registers via i2c

movlw data_i2c ;setting the first receive/transmit register via i2c

movlw b"10000000" ;data for the seconds register of the 1st alarm

movlw b"10000000" ;data for the minutes register of the 1st alarm

movlw b"10000000" ;data for the 1st alarm clock register

movlw b"10000000" ;data for the date/day of week register of the 1st alarm

movlw .4 ;transfer 4 bytes via i2c

movlw 0x07 ;setting the address of the seconds register of the 1st alarm clock

This review is for beginner radio amateurs (those who like to solder), for those who are interested in the process itself. You can evaluate your skill. The DS3231 chip is a real time clock (RTC) with an integrated crystal oscillator and temperature compensation.

This, of course, is not soldering an oscilloscope. Level below. But it's an interesting activity.
Let's quickly go over the form in which everything arrived.


The contents were in two bags. Standard bags with lock. A small bag of small things was inside a large one.


The kit included:
- As a body there are two plates made of translucent plastic (tinted and protected with film from scratches).
- Board (very high quality).


Two matrices.


On the front side they are protected by film. The legs were protected by porous polyethylene.


USB cable is about a meter long.


I poured out everything that was left.


Divided into two parts.
Screws with nuts.


And the fact that you have to solder.


A socket for a lithium battery of a very rare CR1220 format, a mercury position sensor, a pair of transistors, electrolytic capacitors, an AMS1117 stabilizer (3.3V), SMD capacitors and resistors (10K), 3 buttons, a USB connector, a buzzer.
The most important thing is the STC 15w1k24s controller and the high-precision DS3231 chip. They were packed in a very hard blister, it was very difficult to wrinkle.


There was no scheme. However, no questions arose, everything was clear.
All details on the board are not only labeled, but also (conditionally) drawn.
It's simple.
But first I prepared.


I started by soldering the two most complex (I thought so) microcircuits. Positioned and grabbed in two places (diametrically opposite). And then I soldered it properly. Don’t forget to hold it so they don’t “run away”.


Then the stabilizer.


Transistor.


Four SMD resistors and two SMD capacitors. Positioning and grabbing from one edge was not so easy (it takes skill). And I don’t have enough of it :).


Two electrolytes.


USB connector.


Lithium battery socket.


Squeaker. Don't forget about the plus and minus. After soldering, I bit off the legs just right, I don’t want them to interfere later when soldering the dies.


Mercury position sensor.


3 buttons.


And finally, matrices. Pay attention to the orientation. This is the top (the tweeter will be on the left).


This is what happened.


True, there were spare parts left (in case of loss, probably): one transistor, two resistors and a capacitor.


I wash it off from the flux.
I'm checking.
They work!
I remove the protective films.


I'm collecting.

After switching on, the watch congratulated me on the New Year.


No wonder, the clock on January 1, 2000 is 00 hours 01 minutes.


Do not pay attention to the different colors of the matrix. The refresh rate of the “screen” is comparable to the shutter speed of the camera. The human eye sees everything in the correct red color. That’s why I shaded the windows a little when I was filming the video (to increase the shutter speed).
Now we need to configure it.
The watch has three buttons on the back. I myself conventionally called them (from top to bottom):
1. Menu.
2. Plus.
3. Minus.
See the setup algorithm. If you have a watch in your hands, even what is not clear will become clearer 
To enter, hold down the top button (menu) for a while. Next we work with short presses.

Let me explain something. There are six menus in total. They switch in a circle. You can use the plus button, you can use the minus button.
TIME – time setting.
DATE – date setting.
ALAR – alarm setting.
FONT – selection of fonts (5 types in total: thin, wide, smooth...).
DISP – selection of information output algorithm (you can only use a clock, you can have sequentially changing information: time, temperature, date, holidays in a creeping line...).
MIDP – select the type of dividing points.


It’s not easy to explain everything in words. I showed this in detail in the video (link at the end).
And in this video (30 seconds) you can see the algorithm for displaying information on matrices (DISP type2 menu).


Important note. Without a lithium battery, after setting the time and date are lost. The remaining settings remain in memory.
Connected it to a regular charger. I measured my consumption.


A USB device does not show anything when consuming less than 50mA (this is a feature).
Conclusion: in clock mode the current consumption is less than 50mA, in ticker mode it is about 70mA. Not so much.
I measured the dimensions: 105*85mm.
The numbers in the standard display are 20*30mm each.


I put it in front of the TV.


I almost forgot about the mercury position sensor.
The clock will always show correctly, even if it is turned upside down. The mercury ball either closes or opens the contacts. Accordingly, the controller changes the algorithm for outputting information to matrices.
That's basically it.
It's time to take stock.
A good DIY kit for beginning radio amateurs to test their skills. Moreover, this is not just a set for training, but in the end it turned out to be a good watch.
What I wrote should be enough for a correct conclusion.
If something is unclear, ask questions. I hope it helped at least someone.
Good luck!

The product was provided for writing a review by the store. The review was published in accordance with clause 18 of the Site Rules.

I'm planning to buy +61 Add to favorites I liked the review +66 +122

Distinctive features:

  • Accuracy ±2 ppm over temperature range 0°C to +40°C
  • Accuracy ±3.5 ppm over temperature range -40°C to +85°C
  • Input for connecting an autonomous power source to ensure continuous operation
  • Operating temperature range commercial: from 0°C to +70°C industrial: -40°C to +85°C
  • Low consumption
  • Real time clock counting seconds, minutes, hours, days of the week, days of the month, month and year with leap year correction up to 2100
  • Two daily alarms
  • Square wave output with programmable frequency
  • Fast (400 kHz) I 2 C interface
  • 3.3V power
  • Digital temperature sensor with measurement accuracy ±3°C
  • Register containing data about the required adjustment
  • nonRST reset input/output

Application:

  • Servers
  • Electronic electricity meters
  • Telematics equipment
  • GPS systems

Typical connection diagram for DS3231:

General description:

The DS3231 is a high-precision real-time clock (RTC) with built-in I 2 C interface, temperature-compensated crystal oscillator (TCXO) and quartz resonator. The device has an input for connecting a backup autonomous power source, which allows timekeeping and temperature measurement even when the main supply voltage is turned off. The built-in quartz resonator increases the service life of the device and reduces the required number of external elements. The DS3231 is available in commercial and industrial temperature versions and is packaged in a 300 mil 16 pin SO package.

RTC provides counting of seconds, minutes, hours, days of the week, days of the month and year. The end date of the month is determined automatically taking into account leap years. The real time clock operates in 24 or 12 hour format with an indication of the current half of the day (AM/PM). The device has two daily alarms and a square wave output with a programmable frequency. Data exchange with the device is carried out through the built-in serial I 2 C compatible interface.



tell friends