1
\$\begingroup\$

I'm trying to understand how to set up an overflow interrupt on ATmega328 TIMER1 to measure a frequency.

I'm feeding pin PD4, which is where TIMER1 is externally clocked, with a 503kHz square wave (4.8Vpp).

Given that TIMER1 is 16 bit, I would assume that it would overflow 7 times every second. My reasoning is the following:

$$ number\;of\;overflows = \frac{f}{TIMER1\;max\;count} = \frac{503,000Hz}{65,536} = 7.67$$

However, my program counts 988 overflows instead. That's 128 times more than I expected. Why??

I'm using the following code:

volatile unsigned long int running;
ISR(TIMER1_OVF_vect) {
 running++;
}
void setup()
{
 Serial.begin(9600);
 // set up the 16 bit timer as an external frequency counter:
 TCCR1B |= (1 << CS10)|(1 << CS11)|(1 << CS12); // External clock, rising edge
 TIMSK1 |= (1 << TOIE1); // Enable overflow interrupt
 sei(); // enable global interrupts
}
void loop() {
 running = 0;
 delay(1000); // wait 1000ms
 Serial.println(running);
}

Below is the external clock signal on the scope:

External clock scope shot

The schematic I'm using is this one below. The inductor is 220uH instead of 68uH.

Schematic

asked Aug 15, 2014 at 18:00
\$\endgroup\$
8
  • 2
    \$\begingroup\$ I'm guessing you absolutely need to clear a flag in the interrupt routine. Plus I'm not sure that delay(1000) will wait exactly 1s... That's the flag thing though. \$\endgroup\$ Commented Aug 15, 2014 at 18:05
  • \$\begingroup\$ Is the chip programmed with a bootloader? \$\endgroup\$ Commented Aug 15, 2014 at 18:24
  • \$\begingroup\$ Be sure you have defined F_CPU, otherwise the compiler will default to 1MHz for use with delay. It looks like you are mixing AVRgcc with Arduino API. Try using _delay_ms(1000), which is the inline implementation given in the AVR header file delay.h. The Arduino implementation probably just calls this routine anyway, however. \$\endgroup\$ Commented Aug 15, 2014 at 18:33
  • \$\begingroup\$ @Ignacio yes, it's got an Arduino Uno bootloader (optiboot I suppose). \$\endgroup\$ Commented Aug 15, 2014 at 19:04
  • 1
    \$\begingroup\$ Check out Table 16-4 in the datasheet for your micro, and make sure you are in Normal mode. Otherwise, the overflow flag could be triggering for other reasons. \$\endgroup\$ Commented Aug 15, 2014 at 20:37

2 Answers 2

1
\$\begingroup\$

As per page 140 of the datasheet the flag that must be cleared is called \$\mathtt{TOV1}\$ and is the LSB of the register \$\mathtt{TIFR1}\$. That bit should be cleared automatically but that feature might be disabled to use nested interrupts, which seems the case to me. I would have expected an higher value for running, but that's an int and might well be 8 bit wide, so it's overflowing like crazy (that's even signed!).

Try adding this line as the first thing in your overflow ISR:

TIFR1 &= 0x01;

Maybe something like:

TIFR1 &= 1 << TOV1;

will work too, but who knows? You should dive into headers. Try the first solution, that should work.

answered Aug 15, 2014 at 20:24
\$\endgroup\$
1
  • \$\begingroup\$ Tried both lines, but didn't work. It turns out that the problem was something else. Somehow TCCR1A comes set to 0x01 instead of 0x00 in my setup. See my own answer below for more details. Thanks for the effort and for digging into the datasheet, though! +1 \$\endgroup\$ Commented Aug 15, 2014 at 22:47
0
\$\begingroup\$

Thanks to Mewa's comment, which I copy below, I found what the problem was.

Check out Table 16-4 in the datasheet for your micro, and make sure you are in Normal mode. Otherwise, the overflow flag could be triggering for other reasons.

Somehow, in my programming environment, the TCCR1A is set initially to 1 and not to 0 as I assumed.

I verified and fixed the issue with the following lines:

 Serial.println(TCCR1A); // <- this line outputs 1
 TCCR1A = 0; // <- this line fixed the problem - I now get 7 to 8 overflows per second
 TCCR1B |= (1 << CS10)|(1 << CS11)|(1 << CS12); 
 TIMSK1 |= (1 << TOIE1);

If I understand it correctly, that means that bit WGM10 as set to 1, setting my TIMER1 to Mode 1 (PWM, Phase Correct, 8-bit) instead of the intended Mode 0 (Normal). The result was that the timer was overflowing at 511 and not 65535 as I assumed.

Thanks to all of you who helped me figure this one out!

answered Aug 15, 2014 at 22:43
\$\endgroup\$
1
  • 1
    \$\begingroup\$ And that's why I alsways set all the bits I need, also if on reset they should be as I like. \$\endgroup\$ Commented Aug 15, 2014 at 22:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.