Hello,
I'd like to use an ATmega328 as an "RTC" for test purposes. My starting point was this post. It is not too detailed about the process, but I found it interesting enough to try it out.
I've set up the breadboard, everthing works fine, uC is running from its internal clock, I can program it with an UNO board. I wrote a sketch for the time display (4 digit & TM1637) and it worked if the "unixTime" was updated with the millis() function. It was time to move on with Timer2 method, I've soldered the 32768Hz crsytal and the appropriate capacitors to the OSC1 (XTAL1), OSC2 (XTAL2) pins. After reading the Datasheet, Section 17.9 I uploaded this:
#include <TM1637Display.h>
#include <TimeLib.h>
const byte DISP_CLK_PIN = 0;
const byte DISP_DIO_PIN = 1;
const byte BUTTON_PIN = 2;
const bool LEAD_ZEROS = true;
const bool NO_LEAD_ZEROS = false;
const uint8_t NO_DOTS = 0;
const uint8_t MIDDLE_DOTS = B11100000;
const byte length4 = 4;
const byte position0 = 0;
TM1637Display display = TM1637Display(DISP_CLK_PIN, DISP_DIO_PIN);
tmElements_t TimeData;
volatile bool updateSecond = false;
byte buttonState = HIGH; //pull-up, reversed logic
byte lastButtonState = HIGH; //pull-up, reversed logic
unsigned long unixTime = 1610547300ul;
unsigned long lastDebounceTime = 0ul;
unsigned long dispRefreshed = 0ul;
void setup()
{
pinMode(BUTTON_PIN, INPUT);
display.setBrightness(2);
display.clear();
delay(2000); //The user is advised to wait for at least one second before using Timer/Counter2 after power-up or wake-up
noInterrupts();
//Asynchronous Operation of Timer/Counter2
//The CPU main clock frequency must be more than four times the oscillator frequency
//a. Disable the Timer/Counter2 interrupts by clearing OCIE2x and TOIE2
TIMSK2 = 0;
//b. Select clock source by setting AS2 as appropriate
//When AS2 is written to one, Timer/Counter2 is clocked from a crystal oscillator
//connected to the timer oscillator 1 (TOSC1) pin
ASSR |= (1 << AS2);
//c. Write new values to TCNT2, OCR2x, and TCCR2x
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
//d. To switch to asynchronous operation: Wait for TCN2xUB, OCR2xUB, and TCR2xUB
while (ASSR & 0x1F) {}
//no need to change TCCR2A, normal counting mode
//prescaler set to 128
TCCR2B |= (1 << CS22) | (1 << CS20);
//e. Clear the Timer/Counter2 interrupt flags
TIFR2 = 0x07;
//f. Enable interrupts, if needed
TIMSK2 |= (1 << TOIE2);
interrupts();
}
ISR(TIMER2_OVF)
{
updateSecond = true;
}
void loop()
{
if (updateSecond == true)
{
updateSecond = false;
unixTime += 1ul;
breakTime(unixTime, TimeData);
display.showNumberDecEx( (((int)TimeData.Minute * 100u) + (int)TimeData.Second) , MIDDLE_DOTS, NO_LEAD_ZEROS, length4, position0);
}
readButton();
}
void readButton() //pull-up, reversed logic
{
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState)
{
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > 50ul)
{
if (reading != buttonState)
{
buttonState = reading;
if (buttonState == LOW)
{
unixTime += 1u;
breakTime(unixTime, TimeData);
display.showNumberDecEx( (((int)TimeData.Minute * 100u) + (int)TimeData.Second) , MIDDLE_DOTS, NO_LEAD_ZEROS, 4, 0);
}
}
}
lastButtonState = reading;
}
Result:
Time can only be updated with the button, and the chip resets roughly every second. If I don't set the TOIE2 (Timer/Counter2 Overflow Interrupt Enable) in the setup, the uC not resets, I can increment the timestamp with the button as long as I'd like to. Unfortunately I can't measure the quartz if it is working correctly, but I successfully used another one from this type with a Teensy 3.2 board, I hope this one is also okay.
I think the Timer/Counter2 configuration is not correct.
Could someone help to get it right?
Thanks in advance.