I need to measure the switching frequency of an open collector output. The waveform will be square shaped and the frequency range is specified as 0 to 5kHz. First of all I don't want to count pulses because I want to determine the duty cycle as well. So here comes my problem:

For this task I explicitly need to use an ATMega16 without any external circuitry (except crystal)

I know there is a pretty simple way of determine frequency and duty cycle, and I already did use this technique: hook the signal to an interrupt, combine it with an asynchronous timer, do a little bit of math and done!

Now this works pretty well with the 16 Bit timer module but not so great with one of the 8 Bit timers since those overflow much faster.

Now I'm curious if I can determine the accuracy of this technique beforehand, e.g without testing it out.

I know the frequency reading will mostly depend on the timers frequency: the higher, the better. An 8 Bit timer running at @ 2MHz (prescaler 2 ; from 16MHz) should give me a basic 0.5us per LSB resolution which looks pretty good on paper. Combined with a 16 Bit overflow register I theoretically could measure up to one second time period. But I know this won't work: updating the 16 Bit overflow register would take too much instructions in the ISR and effectively wreck my accuracy. So is there any way of getting reasonable accuracy (+-5%) from a single 8 Bit timer module in the specified frequency range (0...5kHz)?

  • 1
    \$\begingroup\$ Check the datasheet for Input Capture Pin. Together with smart interrupt usage you can extend the timer without the need for using the prescaler. Not entirely sure of mega16 has ICP, which brings me back to my first suggestion of checking the datasheet. \$\endgroup\$
    – jippie
    Mar 31, 2016 at 20:28
  • \$\begingroup\$ I have heard of Input Capture Pins before, but totally forgot it! Thanks, this looks like a feasible solution, I'll have a look at it. \$\endgroup\$
    – marco-a
    Mar 31, 2016 at 20:46

1 Answer 1


Updating a register or register set inside an interrupt before any other processing will be extremely deterministic. I don't know why that can't be accurate.

In fact, I dare say that accuracy can be significantly higher than the +/-10% RC oscillator accuracy in an old Atmel type as the ATMega16. Unless you mean "I do have a well tuned crystal with the proper loading capacitors" when you say NO external circuitry.

You can claim registers in Atmel Studio (AVR-GCC) by using the keywords, if I'm not mistaken;

volatile register MyRegister asm("R22"); // to claim R22 with name MyRegister

But claiming registers like that is risky business, and even the RAM overhead of just making a volatile global if that gets put into RAM is a static overhead, which becomes, again, fully deterministic at start of ISR.

  • \$\begingroup\$ Yeah, the start of the ISR is deterministic, but the arrival of the signal edge isn't. I only have a clue on how to calculate accuracy for the worst case: assume the timer overflowed as much as it can in the given measurement span. \$\endgroup\$
    – marco-a
    Mar 31, 2016 at 20:52
  • \$\begingroup\$ Thanks for the tip with registers, I didn't realize I could use builtin registers for that! \$\endgroup\$
    – marco-a
    Mar 31, 2016 at 20:52
  • \$\begingroup\$ And yes.. I'm actually allowed to use an external crystal... oops \$\endgroup\$
    – marco-a
    Mar 31, 2016 at 20:53
  • \$\begingroup\$ @d3l if your timer is fed with the maximum clock, that still leaves you 25 clock cycles to handle stuff before you even reach 1% overflow inaccuracy with 256 count (8bit) timers. Again, the internal RC is much, much worse. \$\endgroup\$
    – Asmyldof
    Mar 31, 2016 at 20:54
  • \$\begingroup\$ Even with a 'non-register' overflow counter variable in the ISR? \$\endgroup\$
    – marco-a
    Mar 31, 2016 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.