I built a sketch using some timer ISR code to get a trigger every second. (for the Atmega328 chip I use the following code I got form the internets. It works)
It runs fine and I get a trigger/callback every second.
void setupAtmega328()
{
#ifdef __AVR_ATmega328P__
// traceDebug("setupAtmega328() entry");
cli(); // stop interrupts
// traceDebug("setupAtmega328() 1");
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
// traceDebug("setupAtmega328() 2");
sei();//allow interrupts
// traceDebug("setupAtmega328() 3");
#endif
}
I also wanted to add the capability of a real time clock (RTC) so I got a DS3231.
I downloaded and ran the sample app from this RTCLib on github
The sample code works fine when running under the Arduino IDE
However, when I add the RTC code to my sketch I don't get the results I want/expect.
Specifically, the program seems to hang/halt at the call to:
cli();
I am new to the Arduino platform and not sure what I am missing.
What do I need to do to get the RTC to work in conjunction with an ISR?
I wired the RTC according to the directions from Adafruit's site
I have other arduino boards that use different ISRs, but I have not tried them yet with the rtc since the 328 seems to be the standard arduino boars that is used to do initial work/testing.
How can I use the 3231 RTC AND a 1 second ISR/callback?
EDIT: I removed the trace/serial output - I had originally added those to track the code to see where I got but i think I exacerbated or added problems in doing that.
for those interested the code is at https://github.com/tjurik/Intervalometer
1 Answer 1
In the Arduino you don't have control how are some essential parts implemented.
For example delay
function requires interrupts to be enabled or it'll be deadlocked (for sure).
Serials are little bit better, it'll be working until send buffer gets full. For devices with small RAM it's 16B only! And your traceDebug
is little bit longer.
In general ISR
should be as short as possible and it's mainly used for setting some flag to be handled in main loop later.
volatile bool flag = false;
ISR(...) {
flag = true;
}
int main() {
init();
while (1) {
if (flag) {
do_something();
flag = false;
}
}
}
-
Yeah, that is how i wrote the code - and then when trying to debug the problem I added serial output which I think made more problems!Tim– Tim2016年10月05日 16:02:14 +00:00Commented Oct 5, 2016 at 16:02
cli
is ill advised. Serial requires interrupt to send the data (if I remember correctly). Try removing the serial.prints between cli and sei, or at least make the text shorter so the buffer doesn't fill up. PS you can setup the DS3231 to send a pulse every second to the SQW pin. You can connect this pin to one of the Arduino interrupt pins. That way you get a very accurate 1Hz interrupt call.