Our project needs a fairly long delay, of 1/20 of a second or rather 0.5 second.
[TUT] [C] Newbie's Guide to AVR Timers
I must say this is a great tutorial. But I am having trouble with my output frequency.
I perform the calculation for timer count.
Target Frecuency = 30000 Target Timer Count = (1/30000)/(1/8000000)-1 = (33.33E-6 / 125E-9)-1 = 264.67
But when I use 264 for my count the output on OC1A is 15khz instead of 30khz.
I could decrease the count to 128 and get 30khz but then my duty cycle resolution decreases. The frequency does not need to be exact. I just need one more bit of resolution to control my duty cycle.
#includeint main(void) { DDRB |= (1 << PORTB1); // PORTB PIN 1(OC1A) SET AS OUTPUT. //CONFIGURE TIMER/COUNTER 1 16BIT TCCR1B |= (1 << CS10); //NO PRESCALER TCCR1B |= (1 << WGM13); // P&F CORRECT TCCR1A |= (1 << COM1A1) | (1 << COM1B1); // SET UP COUNT CLEAR DOWN COUNT //SET ICR1 (TOP) AND OCR1A OCR1A = 75; ICR1 = 264; while(1)
[/code]
With Phase correct and Phase/Frequency correct modes you need to divide by two since they count up to TOP then count down to BOTTOM. Fast PWM counts up, then clears to 0 (no count down). Why is it that you think you need Phase/Frequency correct mode?
Wow that was quick! I'm actually constructing a avr based switching amplifier for a school project. I don't require phase/frequency correctness. It was there so I figured that I would use it. Anyways your explanation makes sense and i'll try without. But if I wanted to test the difference what would I need, a faster clock?
I've done experiments playing audio with both "Fast" and "Phase correct" and try as I might I simply could not hear any difference whatsoever. So I'd pick "Fast" every time. YMMV.
hi there i'm new here and i'm newbie, and i want to say thank you so much for this tutorial, realy helped me.
i want to ask something newbie question, before i played more with timer, i decided to played more in #include
#define F_CPU 1000000UL #include#include #define setservo1 (PORTB |= (1<<PB0)) #define clrservo1 (PORTB &= (0<<PB0)) int main(void) { int i,res1,res2; DDRB = (1<<PB0); // set PINB0 as output res1 = 1000; // if i change this 2000 and res2 = 19000; // this to 18000 everythings fine while(1) { for(i=0;i<=100;i++) { setservo1; _delay_us(res1); clrservo1; _delay_us(res2); } for(i=0;i<=100;i++) { setservo1; _delay_us(1520); clrservo1; _delay_us(18480); } //this problem, when i uncomment two this statemen // res1 = 2000; // res2 = 18000; } }
i attached my servo to test that, everyting work fine, but if i uncomment the last comement, the servo goes error, any clue? :(
Your question is not related to the timers so I'm not sure why you have decided to post it in this thread.
Relating your question about delay, the _delay_us() is intended to be used with constants, not variables, check this recent thread https://www.avrfreaks.net/index.p...
Alex
Your question is not related to the timers so I'm not sure why you have decided to post it in this thread.Relating your question about delay, the _delay_us() is intended to be used with constants, not variables, check this recent thread https://www.avrfreaks.net/index.p...
Alex
thanks for the pointing, sorry before, if i wrong room. :oops:
Love your tutorial ...you are as cool as the code...
:)
Hello!
I have just read this tutorial, very good one.
However I do have a small problem.
I need to generate a 38kHz signal. I have tried to use the formula from the tutorial to calculate the compare value for the timer.
According to the formula, at 8Mhz CPU frequency, with no prescaler for the timer the value should be 208 for getting a 38kHz output frequency.
With this value my output signal is jut 19kHz. If I use 104 instead of 208 everything is ok, I get 38kHz.
I am ussing an AT90USBKey based on AT90USB127 and my code is:
#include#include "avr035.h" #define F_CPU 8000000UL #include int main(void) { CLKPR=0b10000000; CLKPR=0b00000000; //setting the cpu at8MHz DDRC=0xFF;//setting PORTC as output setbit(TCCR3A,COM3A0); //setting the OC.3A toggle OCR3A= 208; //compare value TCCR3B=0b00001001;// starting Timer3 in CTC mode while(1)//this is for testing the cpu frequency { setbit(PORTC,0); _delay_ms(3000); clearbit(PORTC,0); _delay_ms(3000); } }
Can someone explain me why do I get this behavior?
Think about a complete cycle of the wave:
+-----+ | | | | +-----+ + |< 1 >|< 2 >|
That takes 2 toggles to get back to where it started.
Yes, you are right , I now understand, thank you!
Hi Dean,
I'm referring Part Two where you've got
Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1
This can be further simplified to
Target Timer Count = (Input Frequency / Prescale * Target Frequency) - 1
This is simply because (1/a)/(b/c) == c/(a*b) == (c/b)/a
Thanks for such a fantastic guide!
Hrm, not sure how I missed that one. There's some deliberately non-optimal formulas early on in the first chapter to show visually how it's all calculated, but I missed the last transformation when optimizing it at the end of the chapter. I've updated the PDFs to fix that, thanks!
- Dean :twisted:
Hrm, not sure how I missed that one. There's some deliberately non-optimal formulas early on in the first chapter to show visually how it's all calculated, but I missed the last transformation when optimizing it at the end of the chapter. I've updated the PDFs to fix that, thanks!- Dean :twisted:
No worries Dean, I had a read through your PDF and will let you know if I catch anymore. Fantastic guides BTW. I've pretty much worked with Microchip MCUs (mainly) from 2001-2012 @ University. Your guides made it so much easier to figure out which registers need to be set etc. to get something simple working (interrupts etc.)
I posted this video just yesterday http://youtu.be/NxQdCMSOxVo - got a couple others of an omnidirectional robot I built for my Masters if you scroll down my channel.
Thanks - please do let me know if you find anything else wonky. Enjoy the guides (old as they are) and I hope you pass them along to others you find that are interested in AVRs.
- Dean :twisted:
Thanks - please do let me know if you find anything else wonky. Enjoy the guides (old as they are) and I hope you pass them along to others you find that are interested in AVRs.- Dean :twisted:
BTW, I'm seeing the same equation twice now in the PDF?
Hell, I can't catch a break today - fixed.
- Dean :twisted:
if the timer input frequency is 1.1MHz rather than 1.0MHz our one minute timer will be sixty times that small error out in duration.
Great tutorial...do you know how can I compensate the errors due the int. osc. inaccuracy ? If you need 60 sec exactly
Thanks for the tuto Dean
Great tutorial...do you know how can I compensate the errors due the int. osc. inaccuracy ? If you need 60 sec exactly
Usually, whatever the error is, it's pretty constant for the same Vcc and operating temperature. So if those things don't vary much you can just have a fixed value to tweak the OSCCAL register to bring it back to accuracy. But you will, of course, require a known, accurate timing reference to perform such a calibration. Atmel have an app note about this and if you have an STK500 you even have a command line switch to the Atmel program that drives it that causes it to generate a calibration clock.
How are you determining this? Are you toggling a LED in the ISR, just as in Deans code? Have you made sure that the LED is actually wired up correctly.
Just nitpicking, but the STK500 is the hardware doing the programming. What you are programming is the ATmega16.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
I tested the code from part 5, but on an ATmega2560. One small thing had to be changed, since the 2560 has a whole bunch of 16-bit counters: There is no register TIMSK, but rather a register TIMSK1.
Apart from that I took Deans code as it stands, did a build, and flashed the 2560 sitting on an STK-600. The STK-600 has the same LED circuitry as the STK-500. My LED is flashing with 0.5 Hz, just as expected.
Given this, I believe you should not fixate on
but rather go through your wiring and then make sure you've done everything "by the book" (i.e. not changed anything in Deans code, built for the correct device, ATmega16 in the correct STK-500 socket etc).
I did this with Atmel Studio 6, ATmega2560 on an STK-600, Windows Vista Pro.
- Show your code.
- Show your build output.
- Show your AVRDUDE command to program the ATmega16, and the put from it.
- Tell us how you've wired up the LEDs on the STK-500.
- And, again, tell us how you're determining that interrupts do not occur.
Perhaps verify your setup by testing a simple delay-based "blinky". Should take less than five minutes:
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
I am running ATMega16's, not the ATMega2560 or the ATMega128.
My description may have been a little too terse: I tested the code both on an STK500 *programming itself* and the STK500 programming an Olimex P40, both of which are running an ATMega16 @ 16 MHZ. Both boards have their on-board LED wired to PORTB4 - No extra LED wiring is necessary for the following code.
The code examples that poll the counter register and status flags work fine, but the ones that are supposed to generate IRQs do not. I verified the lack of output activity with a logic analyzer just in case the pulse widths happened to be too small duty-cycle-wise to light the LED.
Code, last example (#6 of 6):
Prescaler and count value adjustment have not yet been made for the 16 MHz F_CPU being used. None the less, the LEDs should still light up.
// OVF ISR With Count Preset for Exact Timing:
Note that my files are numbered 0..5, not 1..6.
Build output:
I--- {AVR-Comp.CMD}
I---
I--- PROJECTNAME [ 5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset ]
I--- MCU_TARGET [ atmega16 ]
I--- F_CPU [ 16000000 ]
I--- C_SRCS [ D:\DATA\!MYDOC~1\!PROJE~1\!ELECT~1\!!AVRD~1\AVRCOU~1\5.BA
D.CTC_Timer_OVR_IRQ_WithCountPreset.CPP ]
I--- EXTRACDEFS [ ]
I--- EXTRACINCS [ ]
I--- CINCLUDES [ -I. ]
I--- EXTRACDEFS [ ]
I--- CFLAGS [ -Wall -mmcu=atmega16 -DF_CPU=16000000UL -Os -Wno-unused-
variable ]
I--- ASFLAGS [ -aglm ]
I--- CCLDFLAGS [ -Wl,-Map,5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.map,--cr
ef,-lm ]
I--- LDFLAGS [ ]
I--- EXTRALIBS [ ]
I--- PGMFFORMAT [ ihex ]
I--- BURN_EXT [ hex ]
X--- Compiling [ 5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.CPP ] ...
avr-gcc.exe -c -Wall -mmcu=atmega16 -DF_CPU=16000000UL -Os -Wno-unused-variable
-I. -ID:\DATA\!CURRE~1\!ELECT~1\AVRPRO~1\!LCD~1\ARDUIN~2\ARDUIN~1\hardware\too
ls\avr\avr\include 5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.CPP -o D:\DATA\!MYDO
C~1\!PROJE~1\!ELECT~1\!!AVRD~1\AVRCOU~1\5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.
o
X--- Linking to [ 5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.elf ] ...
X--- Creating FLASH Burn File [ 5.BAD.CTC_Timer_OVR_IRQ_WithCountPreset.hex ]
...[/code]
---------------------------
It seems to me that something extra needs to be done to the mega16 to get it to generate interrupts.
You are utterly confusing/confused. The STK-500 does not program itself. (Unless we where to talk about an upgrade of the firmware of the STK-500 itself - which we are not.) I assume you are talking about "on an STK500 programming an Atmega16 in it's target area".
I can't make heads or tails of your build output. (E.g. I can see a compile command line, but no link command line. It just says "Linking to [...]") Can we see your makefile?
Again: Can we see your AVRdude command line, and the output from it.
Can we see one such example? (To double-check that it accesses the same registers, assumes LEDs on same port etc..)
Since I tested part 5, not 6, why could you not follow me there? (My STK-600 is now stuffed into it's bag for a 50 mile car trip and then I'll hit the sack. Any STK won't come out until tomorrow at the earliest, so I'm more or less pausing here for 12 to 24 hours. Someone else will have to jump in, or you'll have to wait.)
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
This is really awesome tutorial.
Thanks a lot for such nice and clear explaination.
There's an obvious bug in each code example that use interrupts: [ sei() ] must be called in each ISR routine to re-enable interrupts that are automatically turned off each time when entering an ISR function. Otherwise, an IRQ-->ISR will happen just once.
It's obvious the code hasn't been tested recently in the real world ! Perhaps the WinAVR compiler has changed since 2007, but I doubt that very, very much.
What on earth are you talking about? sei() almost never should appear in an ISR(). One of the attributes of an ISR() (that is __attribute__((signal))) is that the return is made by a RETI not a RET. That re-enables the I bit in SREG and to do so any sooner (such as sei() within the ISR() code) is immensely dangerous program design - what then happens if the same interrupt event occurs before this handler has finished and it interrupts the code between the SEI and the RET? If it happens a few times you risk eating the stack. The advantage of RETI is that the re-enabling of I does not actually occur until one cycle later. So the code is firmly back into the interrupted code before the event can reoccur.
Suggest you have a read of any AVR datasheet and try to understand the interrupting mechanism as you have a dangerous mis-knowledge of how it works. It is also very unwise to go correcting a tutorial aimed at other beginners if you don't understand how an underlying mechanism you are commenting on works in the first place!
What?
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
You are talking in "assembly", I am talking in "C". There is no RET(I) instruction in C ! Returns are inserted automatically in C compilers, unless a value needs to be returned.
I am using the WinAVR-20100110 toolchain. What are you using ?
The IRQ/ISR examples simply don't work until a sei() instruction is put anywhere in the ISR functions. I have proved this beyond a shadow of a doubt.
Have you actually compiled, tested and verified these examples recently on an actual ATMega8 or 16 ?
I think I need to do this a bit more gently:
Pascor: I'm afraid you are mistaken. The ISR macro in AVR-GCC will apply the GCC specific "signal" attribute to the function, as Cliff says. Functions marked with this attribute are treated specially by the compiler, meaning they save and restore used registers, but also are generated with a RETI instruction rather than a RET instruction when exiting the function. Attempting to put this in yourself is dangerous, as it will allow for potentially infinite stack recursion.
I honestly don't mind and even warmly welcome all corrections to my tutorials, but your very, very incorrect statements are worrying, as if someone chooses to follow them they could be putting flaws in medically-, safety- and/or reliability- critical applications.
Please take a look at a disassembly listing of a program with an ISR() macro. I assure you, it will be generated correctly for any version of GCC included in any WinAVR release since 2004.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
There's no need to look at the assembly code. I said
The example code is in C, not assembly, so the generated assembly code is a moot point. My C program works as expected only if the sei() instruction is added to the ISR function. Let me rephrase this: The code does not work if an sei() instruction does not appear in the ISR function. I don't understand what is so difficult to understand about this.
Have you verified you own code using the WinAVR-20100110 compiler ? Don't you think you should since this is the most common toolchain ? I believe you will verify my findings.
I honestly think you are joking at this point, but just in case, yes, I have validated the way the compiler works, as has everyone else in the world that has ever written an AVR application that targets AVR-GCC.
What in the world gives you that idea? The AVR microcontroller runs instructions, which have corresponding assembling mnemonics. Your C code is compiled into the same instructions, thus a dissassembly gives you a human readable representation of the instructions the compiler generates. Studying the listing file of your compiled application for 10 seconds would allow you to validate what I am saying is true.
A different tact:
1) Do you think someone else would have pointed this out before now if what you are saying is true?
2) Do you think other members would have written universally incorrect and non-functional code, and shipped them in products if the code obviously did not work?
3) Do you think I would have been hired by Atmel with such a horrible misunderstanding of a fundamental compiler function?
If your code only works with a sei() in the ISR, your code is incorrect. Show us the code, we will show you where you are wrong. I really can't think of a gentler way to put this; figuring out a band-aid to "fix" your code doesn't mean the compiler is broken.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Pascor, as I said you clearly haven't got a clue what you are talking about so you are not in position to correct a tutorial until you have learnt some basics of C programming. Here is a program in which I've deliberately included a "normal" function and also an ISR() function:
the code generated for timer_init() is:
Note that the C compiler has (as you might expect) ended this function with a RET. Now look at the code of the ISR():
Unlike before the function ends with RETI not RET and the prologue and epilogue of the function are more complex as the C compiler has to get things into the right state to run the C code whatever foreground code may have been interrupted and no matter what it was doing (such as a MUL which might mean that R1 did not contain 0).
What's more look at it when I add sei() to the ISR() code:
What happens in this case is the I bit is set back to 1 five opcodes too soon. During the execution of those opcodes another interrupt might occur. If so then the handling of this first ISR() was not finished and R1, R0, SREG and R24 may be on the stack. So the next interrupt occurs and another copy of those four is stacked. Then another interrupt occurs and another 4 and so on. Eventually the stack runs out and the AVR crashes.
If someone has taught you that cli() or sei() should ever appear in an ISR() they are a complete idiot and do not know what they were talking about. You should correct the website or the course tutor (or God forbid the author of a book!) who told you this garbage before more people such as yourself are seriously mis-led. Unless you REALLY know what you are doing (and the only example I've ever seen that justified it was actually written by Dean!) then sei() and cli() have no place in ISR() code and to suggest it is utter madness.
As I said above, read an AVR datasheet and see how the interrupt process actually occurs. The original event will set some kind of flag bit in a status register (in my example it is the TOV1 it in the mega16's TIFR register. When the AVR makes the next opcode fetch it (in vector table order) scans all the bits that may have latched the fact that an interrupt event occurs. When it finds a bit such as TOV1 set it then sets I in SREG to 0 then initiates a call to the vector location associated with that flag, this in turn pushes the PC address (next opcode) of the interrupted code. At the vector location the WinAVR or AS6 C compiler will have put a JUMP/RJMP to the handler code you defined with ISR(). It arrives there something like 12 cycles after the vector process started. The C compiler (as in this example) will typically PUSH 3 or 4 registers. All this occurs with the I bit in SREG clear so cannot be interrupted. The body of the ISR then executes and finally the PUSH'd register are restored and, because the function was defined as ISR() the C compiler will have ended it with RETI so that unstacks the interrupted PC adddress back into PC and during the next opcode executed the I bit in SREG is returned to 1 so that further interrupts can occur.
if you want to read (and I think you should as your knowledge is terrible) then see the description of the signal attribute on this page of the avr-gcc manual:
http://gcc.gnu.org/onlinedocs/gc...
When you use ISR(vect_name) it is really just short form for the signal attribute if you take another view of my example code above after it has passed pre-processing but before it is compiled:
It is the very uise of "signal" in that which caused the compiler to generate the prologue and epilogue it has for this special function.
I'll join the choir, but from a slihtly different angle: This is simply not true. Looking through some well-worked examples or projects here at AVRfreaks should hit to this. Or looking at some of the sample applications from Atmel.
After you've seen a lot of ISR()'s in those, none doing an explicit sei() before it returns, you should back away from your misconception, and start pondering if you've been misinformed elsewhere or just jumped to an erroneous conclusion.
I.e. whenever one finds what one think is a blatantly obvious bug, and it is repeated over and over (or, as in this case, occurs in a place where many, many people ought to have yelled loudly about the bug a long time ago) then it is time to stop and ponder that the mistake is at one's own end.
Someone said that the meek shall inherit the world - be a winner and join the humble team! :wink:
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Well I suppose he did say:
It would be interesting to explore this further and find out what was actually wrong in the code he was testing and how it could have been that the erroneous sei() made it work. Maybe two ISR()s with a higher priority one absorbing all the CPU time so another one or main() could hardly run? we would need to see the non-working code to have any chance of analysing how he was so dangerously mis-led though.
Dean,
If I use timer0 with overflow and reload mode it seems that I can't go faster then +/-50Khz Do you reconize this problem?
ATmega168P 8Mhz int clk.
Alex
Do you have the CKDIV8 fuse cleared?
Also, the ISR takes several clocks to activate and execute. It is likely more than the 16 clocks it takes for your timer to overflow.
Regards,
Steve A.
The Board helps those that help themselves.
You can also try to add this in the start oif main
TCNT0=254; can also be set to 255 although it won't help much.
Have you considered using the compare match to toggle the output pin?
Alex
"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown
I've only just woken up, but why 16 clocks? The code is using DIV1 from FCPU, and sets the start value to 0xFE, thus it should take two clock cycles to overflow rather than 16.
In any case, yes, the ISR will be soaking up execution cycles and slowing it down. Using overflow for this purpose isn't the best way to do it; in later chapters of my tutorial you'll learn about CTC mode which will give you better results.
That isn't optimization safe, use the avr-libc provided inline assembly macro instead:
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
I read that I could better use the counter in the ctc mode, but I just needed a simple 500Khz signal to replace a function generator and I didn't want to use the _delay function..
The problem is that if I change de clk devide from 64 to 8 to non and it still gives me max 51.3Khz If I devide it more until 1024 I can see the calculated value on the scoop.
I also saw a problem with AVR studio if I select the atmega168PA instead of just P, the debugger will fail. And it really says atmega168PA on the chip. But I don't think this is the problem
-Alex-
Try this
Regards,
Steve A.
The Board helps those that help themselves.
Hi Lund,
I tried your code.. And yes this works, its 500 Khz the only strange thing is that I would expect a 100% 50/50 duty cycle If you look at the scoop image every 4/5 cycles it "glitches" but for my application it will do, but do you know why this appears?
Koshchi,
The overflow should have worked..I'll look into that when I have more time
Adding the A to atmega168P gives realy a problem in my debugger (ver.6.0.1843)
Problem with the ctc mode solved.
Forgot to enable the int.
Now the duty signal is perfect 50/50%
But snigelen code didn't use any interrupt :roll:
Alex
"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown
Yes, it should work without interrupts, I can't see why you have the glitches, I don't have them.
And it will take more than 8 clock cycles to enter the ISR, do something and get back, so you don't want to execute interrupt handlers at that rate anyway.
Regards,
Steve A.
The Board helps those that help themselves.
You are right,
can be set to 0. I replaced the uC and it still works without setting the int.
Guys check this site, it is very well explained about AVR Timers,
http://www.zembedded.com/avr-tim...
http://www.zembedded.com/avr-tim...
http://www.zembedded.com/avr-tim...
Just thought of sharing with all of you...thanks!
Success is optional, choose wisely!
Hey,
first off, very nice tutorial, it helped me understand timers quite well.
In part one, you talk about Timer resolution = 1 / Input Frequency.
Well a frequency is 1 / time yielding something in Hz. The first Input Frequency is 100 Hz, so our timer resolution would be .01 seconds per tick or 10ms.
So far so good. All makes perfect sense so far.
But then, the second math bit, you start with (1 / Target Frequency) / (1 / Input Frequency).
Which is Timer Resolution / Input Resolution? Would make sense. Now here comes the confusing bit:
For the Target Frequency, you choose 1 / 20 of a second and while that's legal way, a second in fractions. It reads like some frequency however. Anyhow when filling in the target frequency, where one would expect then 1 / (1/20), you do some conversion or ... I don't know :)
If you'd rewrite the sentance
1 / (1 / 0.05).
Now if you'd put Timer resolution in the first bit, the formula would read:
This sounds logical as 1/20 of a second, or 0.05 seconds is the target resolution and we need to 1/0.05 to get the target frequency. The math bit still seems to be accurate though.
Further below, when you simplify the formula.
[code]Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1
Anyway, just my 2 cents :)
edit: Corrected; yes, 1/20 is 0.05. My brain was allready sleeping.