NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Math Check Please

December 21, 2010
by Keyster
Keyster's Avatar

Can someone please do a sanity check for me? i have written some code to blink 6 sets of LEDs (Red, Green, and Blue). Everything in the code works EXACTLY like i want it to but it does not run at the speed that i expect. i want it to switch between the "rows" of LEDs every 2ms. here is what i have for the interrupt:

setup code:

    cli();              //make sure interrups are disabled during setup
    TCCR0A = (1<<WGM01);    //CTC (Clear Timer on Compare Match)
    TCCR0B = (1<<CS01);     // set prescaler to 8 (1,843,200Hz)
    OCR0A = 1;          //set the compare register (2 = 921,600Hz)
    TIMSK0 = 2;         // set the bit mask to enable interrupt - Timer 0 Compare Match A
    {blah, blah}
    sei();
    endless while loop

now here is the interrupt i am using:

ISR(TIMER0_COMPA_vect)
{  blah, blah...

after doing hours of testing with counters it seems to be running at apx 115,200Hz instead of the 921,600Hz i expect.

here is my math: 14,745,600 / 8 (prescaler) = 1,843,200Hz

1,843,200 / 2 (compare register set to 1) = 921,600Hz

921,600Hz = interrupt apx every 1.1 microsecond

1.1 microsecond x 2000 = apx 2ms

when i set my counter to 2000 i see a BAD flicker. when i set it to 18000 it takes exactly 1 second to get through all 6 sets of LEDs (166.6ms per row instead of the 18ms i expect).

is my math flawed? am i figuring the prescaler incorrectly?

Note: this is a brand new chip i just received from the NK guys but, other than this, it seems to be working perfectly.

Bryan

December 22, 2010
by bretm
bretm's Avatar

You're asking for an interrupt every 2 x 8 = 16 clock cycles. It probably takes more clock cycles than that just to save the registers, restore them, and return, which is code that the C compiler is generating automatically. Each machine register that needs to be saved takes four cycles--two to push to the stack and two to pop. The reti instruction takes 4 cycles. Interrupts are disabled during this process so you won't get all the interrupts that you want.

And then subtract the time it takes your ISR code to run. It sounds like you have at least a two-byte increment and compare, which would take 4 or 5 cycles minimum if that's all you do.

December 22, 2010
by Keyster
Keyster's Avatar

Ahhhh, I knew there was something that was not "adding up". I knew it was firing fast but I did not put two and two together and think that it was "skipping" some interrupt fires because it was already in an interrupt... tonight I will try to slow it down to speed it up (that is almost irony). I will post the results.

thank you Bretm

December 22, 2010
by bretm
bretm's Avatar

Slowing it shouldn't help. When the next interrupt comes in while the ISR is running, the MCU will queue it up (it can remember one, but not more than one) and will fire it as soon as the current ISR is done, plus one more instruction. So my guess is that you'll only make it slower.

If the main loop isn't doing anything else, the fastest would probably be to do the work there, with no interrupts or waiting. That will free up the clock cycles used getting in and out of the ISR.

December 22, 2010
by Keyster
Keyster's Avatar

Hey BretM,

when i said "slow it down to speed it up" i know i was being a little vague there. :) what i ment to say was slow down the rate at which the interrupts fire so the MCU is not constantly firing interrupts. i changed the pre-scaler to be 64 and i can still get it to work. here is the "new" math.

~14Mhz / 64 = 230Khz

230Khz / 2 = 115Khz (Compare Register set to 1)

this will fire an interrupt ever 8.6 microseconds. if i move to the next row of LEDs every 233 count that will be every 2ms.

I did all of this when i got home from work today and it works perfectly. I setup another counter to count up 20 seconds of the "233 counts" and then turn on a test LED. it fired off at exactly 20 seconds. Thank you for pointing me down the right road BretM.

Post a Reply

Please log in to post a reply.

Did you know that our USB NerdKit works on Windows, Linux, and Mac OS X? Learn more...