jboyton:
It adds another chip (and kind of a big one). Plus the software interface. You also have the issue of synchronizing to a time base that has a resolution of 1 second. You're either freezing the clock or skipping a second every once in a while. Or you have to read the RTC multiple times quickly to try and assess the drift more precisely. Why not just have a better internal clock? The main point of an RTC is to maintain the time when the processor (or at least its clock) is powered down.I didn't come across your library when I was looking for one for the DS3234 recently. But you appear to have made the same mistake that the other libraries I found also made. In order to ensure data integrity you have to read the time registers in burst mode. If you read them one at a time like in your library there is a small chance that there will be a rollover in the middle of reading them. Take a look at the example code that Maxim provides.
My library does not read the registers one at a time. It reads the whole 7 byte block of registers in one call and then the data is BCD->Decimal converted afterwards from the read buffer, not directly from the RTC (I'm no dummy!) ![]()
I read all 7 registers at once simply because it's the easiest thing to do. I didn't do it for any "data integrity" reason, in fact I never even thought about things like a register rolling over when another one did.
// read 7 bytes of raw clock data to buffer
void DS3234::_read_raw (void)
{
uint8_t x = 7;
while (x--) {
_buffer[x] = _command (x, 0x00);
}
}
// write 7 bytes of raw clock data to buffer
void DS3234::_write_raw (void)
{
uint8_t x = 7;
while (x--) {
_command ((x | _BV (7)), _buffer[x]);
}
}
// send command and send or receive data via SPI
uint8_t DS3234::_command (uint8_t cmd, uint8_t data)
{
*_SS_PORT &= ~_SS_BIT;
data = _spi_transfer (((cmd << 8) | data), 16);
*_SS_PORT |= _SS_BIT;
return data;
}
// soft SPI mode 3 CPOL 1 CPHA 1
uint8_t DS3234::_spi_transfer (uint16_t data, uint8_t bits)
{
while (bits--) {
*_SCK_PORT &= ~_SCK_BIT; // sck low
(data & (1 << bits)) ? *_MOSI_PORT |= _MOSI_BIT : *_MOSI_PORT &= ~_MOSI_BIT; // send bit
*_SCK_PORT |= _SCK_BIT; // sck high
*_MISO_PIN &_MISO_BIT ? data |= (1ULL << bits) : data &= ~ (1ULL << bits); // receive bit
}
return (data & 0xFF);
}
As you can see from "[b]_command()[/b]", I send both command and data in one long 16 bit burst. But I did this just to avoid doing two 8 bit calls. The idea of "bursting it for data integrity" never crossed my mind and I don't believe that it's necessary anyway.
Also, the RTC is not "frozen" during reads of the registers. Obviously this would make the time drift towards the slow end the more it was read. The DS3234 "snapshots" the registers into a buffer and THAT is what's read (see this from the DS3234 data sheet pg. 11):
When reading or writing the time and date registers,
secondary (user) buffers are used to prevent errors
when the internal registers update. When reading the
time and date registers, the user buffers are synchronized
to the internal registers on the falling edge of CS
or and when the register pointer rolls over to zero. The
time information is read from these secondary registers,
while the clock continues to run. This eliminates the
need to reread the registers in case the main registers
update during a read.
Lastly, where did you find any example code from Maxim? I never saw any (I've only got the chip datasheet PDF). I would like to see their sample code - might give me some good ideas.