Posted by abcminiuser: Wed. Nov 7, 2007 - 06:51 AM
1
2
3
4
5
Total votes: 0
That should be fine, however, there's one more thing you're not accounting for - atomic access of the variables.
It's possible for your COMPA interrupt to fire in between the reading of a multi-byte global variable, which results in corrupted data being used. The solution is to read the volatile value into a normal local variable while interrupts are disabled in your main code:
volatile unsigned int verticalspeed = 0;
volatile int reference=0;
volatile int altitudeR_int=0;
int main(void)
{
// initialise interrupt here
while(1)
{
// at here the altitudeR_int changes according to our sensor
cli(); // Read in the globals here with interrupts disabled to prevent the ISR from updating them while reading the values
unsigned int verticalspeed_LCL = verticalspeed;
int reference_LCL = reference;
int altitudeR_int_LCL = altitudeR_int;
sei();
printf("Pump ON \n" );
printf("Altitude= %d ft \n", altitudeR_int_LCL);
printf("reference= %d mb \n",reference_LCL);
printf("verticalspeed:%u ", verticalspeed_LCL);
}
}
ISR(TIMER1_COMPA_vect)
{
verticalspeed=((altitudeR_int-reference)*60);
reference = altitudeR_int;
}
The added benefit of this in your code, is that since all globals are cached locally with the interrupts disabled, you prevent the update from also occuring between the variable reads. Without this you might get the corrupt data as above, but also correct data, but with half the variables from one sample, and half from another.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Just to note that when you want to interrupt protect access to a variable you may not always know that the current interrupt state is SEI or CLI so rather than wrapping the access in a cli() before and an sei() afterwards it sometimes makes sense to define a 'uint8_t sreg_state' then do 'sreg_state = SREG; cli();' before the access and then 'SREG = sreg_state;' afterwards which recovers the pre-existing interrupt state rather than making the assumption that it was SEI.
Posted by abcminiuser: Wed. Nov 7, 2007 - 09:47 PM
1
2
3
4
5
Total votes: 0
Right as always Cliff, I was oversimplifying for his example, which seemed to always need interrupts enabled. The "correct" way to do it is to save and restore SREG:
Which I wrapped up into a handy macro and submitted to the avr-lib-c project, so it's going to be part of the library in the next avr-lib-c release or so.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
hi Dean,
thanks for ur help ... we are not sure if we have disable our interrupt correctly...
int main (void)
{
TCCR1A= (1 << WGM12); TCCR1B = 0x04; // prescaler 256
TIMSK |= (0 << OCIE1A); disable the interrupt
sei(); // Enable global interrupts
function1(); //
function2(); // interrupt start and end here
funciotn3(); //
}
function2()
{
TIMSK |= (1 << OCIE1A);
OCR1A = 625; // we set the 20ms interrupt here
while(1)
{
// at here the altitudeR_int changes according to our sensor
cli(); // Read in the globals here with interrupts disabled to prevent the ISR from updating them while reading the values
unsigned int verticalspeed_LCL = verticalspeed;
int reference_LCL = reference;
int altitudeR_int_LCL = altitudeR_int;
sei();
printf("Pump ON \n" );
printf("Altitude= %d ft \n", altitudeR_int_LCL);
printf("reference= %d mb \n",reference_LCL);
printf("verticalspeed:%u ", verticalspeed_LCL);
}
TIMSK |= (0 << OCIE1A); // disable CTC interrupt
}
ISR(TIMER1_COMPA_vect)
{
verticalspeed=((altitudeR_int-reference)*60);
reference = altitudeR_int;
}
is this a correct way to disable and enable the interrupt? and another problem is even we intend to set to 20ms interrupt but the program seem to perform one second interrupt? did we set the interrupt interval correctly ?
Posted by abcminiuser: Fri. Nov 9, 2007 - 06:15 AM
1
2
3
4
5
Total votes: 0
That's correct for the atomic access, assuming that you want interrupts on at all times except for the global reads (otherwise you need to save and restore SREG as discussed above).
This line:
TIMSK |= (0 << OCIE1A); disable the interrupt
Does nothing - I suggest you read the "Bit Manipulation" tutorial. The correct code is:
TIMSK &= ~(1 << OCIE1A); disable the interrupt
Although since that bit is cleared when the AVR is reset, it *still* doesn't achieve anything.
What clock speed are you feeding into the AVR? It comes with it's internal 1MHz RC oscillator enabled by default, you need to change the fuses to use an external crystal/clock source.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by penquissciguy: Tue. Nov 13, 2007 - 04:32 PM
1
2
3
4
5
Total votes: 0
Great tutorial! I successfully ran several of the code examples in this tutorial on an Olimex AVR MT 128 board (ATMega 128-based) after changing the timer prescale to 1/1024 to match a 16MHz system clock. I also changed the pin assignment to Port E Pin 2 because that pin on my board is adjacent to a ground pin. I'm just starting out with the AVR, and code from your tutorials is the first code I've successfully run on an AVR.
You write very well. You definitely have the right mindset when you write these tutorials - assume NOTHING of the reader. That's where many tutorials fall short. I teach for a living, and I've seen many "introductory" books in several different areas that miss this point. If you ever do get the time to write the book everyone is suggesting, I'll certainly buy it.
Thanks for the great tutorial. Using your tutorial alone, I've just wrote my very first interrupt implementation, to drive a servo with PWM signal in software, on a atmega8. Loaded it up, and it worked first time. Great tutorial! I'm very impressed. You've taught me how periodic interrupts work.
FYI, the PDF of this tutorial is not in sync with the online version at the top of the thread. I just spent two hours chasing a mistake in the PDF that was fixed online a while ago. Once I figured out that the PDF was old, I fixed it in minutes. On the flip side, I have spent two hours reading the mega168 datasheet trying to figure this mess out :) .
Dean, is there a plan to update the PDF? If not, it might be a good idea to either take it offline or add a disclaimer at the beginning that the document is not up to date.
The tutorial was great even though I had problems. Thanks for putting it together.
You can have my mac when you pry my cold dead fingers off of it.
Posted by abcminiuser: Sun. Nov 25, 2007 - 11:12 AM
1
2
3
4
5
Total votes: 0
Kevin,
Sorry about that, my fault. I'm going to remove the PDF version for the meantime, while I try to find an automated solution; maintaining two formats is a pain in the rear and I want to simplify things. Ideally I'd want to go from BBCode from the post straight to a formatted PDF, but that's a pipe-dream. I think the best I can hope for is a BBCode-HTML converter, then a HTML to PDF converter. I'll have a look around.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by abcminiuser: Sun. Nov 25, 2007 - 01:51 PM
1
2
3
4
5
Total votes: 0
Actually, I've been thinking today about the comments others have made about me writing a book. Books on AVR and the C language has been done, and I don't want to take away money from hungry mouths like Smokey (and that, as he will tell you, is a big mouth :lol:). However, I think that a book that is essentially a set of worked examples using the different AVR peripherals might fill a niche while not treading on any toes. A bit like a book of my tutorials, but ones that flow from one to the next. Thoughts?
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Well, speaking from my days of having to tackle that cursed Perl language, the Perl Cookbook was a lifesaver. The reference books (i.e. datasheets) are not a good place to learn the basics. The beginner books (i.e. turorials) are not much good once you have run through them once because the examples are too simple. Something like a cookbook that illustrates each function helps bridge the gap.
For example, as of right now, I would KILL for an example of a working input capture counter! I am not ready to give up and go to the AVR Forum yet but a cookbook would be high on my list to Santa right now.
You can have my mac when you pry my cold dead fingers off of it.
I have made a simple timer program that would toggle 3 LEDs after set time. I am using tiny13 uc. The program works perfect if I simulate it using AVR simulator or debug it using JTAGICE mk II but doesn't work at all if I flash program using ISP. All 3 LEDs stay ON instead of toggling after a set time.
I don't think there is an error with ISP. I have developed few other programs (not shown below) and they work fine when I flash them using ISP.
Any idea whats wrong ? I have tried playing with different clock prescales and different time delays (as explained using variable elapstedtimeseconds for longer time delays) but it didn't really help.
If the LEDs appear to be on all the time it suggests that on/off toggling is simply happening too fast for you to see it (which is the difference between the simulator and real life - one is hundreds of times slower than the other). For one thing start by increasing the clock prescaler to the highest setting - you comment says "Fcpu/1024" but that's not what you are setting - I'll bet you speeded it up so you could see something happening in the simulator!
Posted by uzairsaeed: Mon. Dec 10, 2007 - 08:27 PM
1
2
3
4
5
Total votes: 0
hi
guys can any one tell me how do i start my AVR studies i m bit confused plz help me with this k where i should i start my AVR program......some of my frends said to start studies of AVR 4m ATMEGA8 datasheet....plz tell me or give any brief or supporting tutorial
thanx....
Posted by WilburWright: Mon. Dec 10, 2007 - 08:35 PM
1
2
3
4
5
Total votes: 0
uzairsaeed wrote:
hi
guys can any one tell me how do i start my AVR studies i m bit confused plz help me with this k where i should i start my AVR program......some of my frends said to start studies of AVR 4m ATMEGA8 datasheet....plz tell me or give any brief or supporting tutorial
thanx....
After reading those, then start a new thread in the AVR Forum, not the tutorials forum, and give it an informative title like: "How to start with AVR?"
Thanks for the new year gift Dean.
Thanks a lot for ur dedicated work on even the new years eve.
i have a doubt.i simulated the code in part part five of ur tutorial in avrstudio.i am not able to see the counting in the tcnt registers.
is it so that the count is not visibile while using interrupts?
#include
#include
int main (void)
{
DDRB |= (1 << 0); // Set LED as output
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
sei(); // Enable global interrupts
OCR1A = 15625; // Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64
TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64
for (;;)
{
}
}
ISR(TIMER1_COMPA_vect)
{
PORTB ^= (1 << 0); // Toggle the LED
}
Posted by abcminiuser: Tue. Jan 1, 2008 - 06:41 AM
1
2
3
4
5
Total votes: 0
Studio has a number of known issues when simulating timers, depending on the version. Check your version's help file -- see if there are any timer-related issues. It should indeed show the timer counting correctly.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
i was breaking my head over this.
when i programmed mega16 with this code it worked properly.
only problem was with simulation.
i checked up the help page.there is a problem with tcnt buffering wen we use 16 bit timer.
in part eight of ur tutorial you mentioned to use prescale of 64 and in the code you used prescale of 8.
Quote:
Let's go with the previous example in part two: a 1Hz flasher, using a 1MHz clock and a prescale of 64. We found the timer count to be 15625 for those conditions.
../bla.c:385: error: 'TIMSK' undeclared (first use in this function)
../bla.c:385: error: (Each undeclared identifier is reported only once
../bla.c:385: error: for each function it appears in.)
I've been playing with the following code on an atmega168@18.432MHz.
#include
#include
int main (void)
{
DDRC |= (1 << 0); // Set LED as output on port c0
// Waveform generation bits - see table 14-8 on page 104 of datasheet atmega168
TCCR0B |= (0 << WGM02); // Configure timer 0 for CTC mode
TCCR0A |= (1 << WGM01) | (0 << WGM00);
TIMSK0 |= (1 << OCIE0A); // Enable CTC interrupt
sei(); // Enable global interrupts
OCR0A = 1; // Set CTC compare value
TCCR0B |= ((1 << CS00) | (0 << CS01) | (0 << CS02)); // Start timer at Fcpu/1 table 14-9
for (;;)
{
}
}
ISR(TIMER0_COMPA_vect)
{
PORTC ^= (1 << 0); // Toggle the LED on port c0
// sei();
// if sei(); is omitted then the maximum freq is lower.
// Using a 18.432 MHz x-tal, the max freq is 236 kHz (no sei() - with sei() in isr: 368 kHz
}
I would like to have a faster timer. Why is it so slow? Any idea what to do?
Posted by abcminiuser: Tue. Jan 22, 2008 - 04:32 AM
1
2
3
4
5
Total votes: 0
Don't put the sei() in the ISR - the compiler takes care of that for you.
The ISR takes quite a few clock cycles to execute, about 9 just to get to it, plus a whole bunch more to execute your code, and the ISR overhead. 368KHz sounds about right for the maximum ISR speed.
You can do two things.
1) If your ISR is very basic, and has no side-effects, register or otherwise, you can make the ISR "naked" and ommit all the prologue and epilogue code. That'll speed it up, but will cause problems if your ISR tries to modify any of the registers or CPU flags.
2) Switch over to the hardware CTC method I outline. The timer circuitry can toggle the hardware compare pin as fast as the compare flag triggers, with no CPU overhead. That's the preferable option.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
I thought about the issue and it seems that the isr routine needs about 80 cycles to run. A naked one could be ok. I'll try the hardware one.
Oh, thanks for the tutorial.
I ran your examples and monitoring things on my digital scope. One one monitor I had the datasheet and on the other your tutorial and avr studio. The datasheet is quite cryptic and contains hardly any quick to use info. I've been looking at the microchip website lately and they have much more info about different things. Atmel is quite sparse with info.
Posted by abcminiuser: Tue. Jan 22, 2008 - 01:34 PM
1
2
3
4
5
Total votes: 0
Ah bugger, I've had the PWM section on my "ToDo" list for months, but can never quite seem to bring myself to sit down and really type it out. I lack motivation, and six seasons of Stargate on DVD doesn't help much.
Part Six: Pure Hardware CTC is the section you want to read on the hardware-only toggling solution.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Well I know the feeling... Ever heard of Firefly? just one season and a film called Serenity.
Anyway, I would like to have 3 pwm timers in an atmega168. Plenty of questions and the datasheet is cryptic. Perhaps if you just wrote something about the scope of this (strategy of what to use and perhaps why). Then I have enough to work on.
I've been playing with the pure hardware ctc routine. I used the two outputs on an atmega 168.
#include
#include
int main (void)
{
DDRD |= (1 << 6); // set port PD6 as output. (led-> Timer 0 output on port OC0A (PD6, pin 12))
DDRD |= (1 << 5); // set port PD5 as output. (led-> Timer 0 output on port OC0B (PD5, pin 11))
DDRC |= (1 << 0);
// Waveform generation bits - see table 14-8 on page 104 of datasheet atmega168
// Configure timer 0 for CTC mode
TCCR0B |= (0 << WGM02);
TCCR0A |= (1 << WGM01) | (0 << WGM00);
OCR0A = 10; // Set Clear Timer on Compare Match mode (CTC) value - also known as TOP
OCR0B = 1; // Set Clear Timer on Compare Match mode (CTC) value
// set OC0A and OC0B to toggle on compare match. page 102/103
TCCR0A |= ((1<< COM0A0) | (0 << COM0A1) | (1<< COM0B0) | (0 << COM0B1));
// Start timer at Fcpu/64 See prescaler table 14-9 on page 106
TCCR0B |= ((1 << CS00) | (1 << CS01) | (0 << CS02));
for (;;)
{
}
}
OCR0B = 0..10. At 10 the phase relation between OC0A and OC0B is 100% If OCR0B >10 then the output on OC0B is zero.
Posted by abcminiuser: Tue. Jan 22, 2008 - 10:29 PM
1
2
3
4
5
Total votes: 0
Each timer can only have *one* CTC channel operating at a time - if you use both, the timer will clear when the first channel compares, and the second one will never be reached. The point of the multiple channels is for PWM mode, where you can have dual channels operating simultaneously.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Now I've been playing with pwm on timer 0 using two outputs. I would like to get a possibility to set the freq and duty cycle of both outputs independently. But alas. I can only do one channel or use two channels with a fixed freq.
I do not yet understand it completely.
Perhaps you can have a look at the following code and tell me what I'm missing:
/*
PWM on atmega168 @ 10 MHz
two outputs OC0A (Port D6, pin 12) and OC0B (Port PD5, pin 11)
1) case WGM02=0 Mode 1 (table 14-8), PWM, Phase correct, TOP=0xFF
If WGM02=0
Fixed freq: 39.0 kHz if fast is on (WGM01=1) or 19.6 kHz if fast is off (WGM01=0)
duty cycle set by OCR0A and OCR0B for both output ports.
2) case WGM02=1 Mode 5 (table 14-8), PWM, Phase correct, TOP=OCRA
If WGM02 = 1 then behavior is different: One (1) output only: OCR0B. Output OCR0A is constant high.
Frequency is determined by OCR0A: e.g.
OCR0A = 100 : freq = 50.0 kHz (fast off)
OCR0A = 200 : freq = 25.0 kHz (fast off)
OCR0A = 100 : freq = 99.0 kHz (fast on)
OCR0A = 200 : freq = 49.75 kHz (fast on)
OCR0A = 199 : freq = 50.0 kHz (fast on)
The duty cycle of the output is: (OCR0B / OCR0A).
e.g. OCR0A = 200, OCR0B = 35. Duty cycle=(35/200) * 100% = 17.5%
*/
#include
#include
int main (void)
{
DDRD |= (1 << 6); // set port PD6 as output. (led-> Timer 0 output on port OC0A (PD6, pin 12))
DDRD |= (1 << 5); // set port PD5 as output. (led-> Timer 0 output on port OC0B (PD5, pin 11))
DDRC |= (1 << 0);
// Waveform generation bits - see table 14-8 on page 104 of datasheet atmega168
// Configure timer 0 for PWM, Phase Correct
TCCR0B |= (1 << WGM02);
TCCR0A |= (0 << WGM01) | (1 << WGM00);
OCR0A = 200; // Set Clear Timer on Compare Match mode (CTC) value - also known as TOP
OCR0B = 9; // Set Clear Timer on Compare Match mode (CTC) value
// set OC0A and OC0B . page 102/103
TCCR0A |= ((0<< COM0A0) | (1 << COM0A1) | (0<< COM0B0) | (1 << COM0B1));
// Start timer at Fcpu/1 See prescaler table 14-9 on page 106
TCCR0B |= ((1 << CS00) | (0 << CS01) | (0 << CS02));
for (;;)
{
// Take a hike
}
}
Posted by abcminiuser: Wed. Jan 23, 2008 - 12:38 AM
1
2
3
4
5
Total votes: 0
As far as I am aware, you set the frequency per-timer, then the duty-cycle per channel. Different frequencies require different timers - but most of the time muti-channel PWM applications all use the same frequency anyway (e.g. robots with servos, LED light controllers, etc).
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by abcminiuser: Wed. Jan 23, 2008 - 04:17 AM
1
2
3
4
5
Total votes: 0
Added the start of the PWM chapter. Not entirely certain that I like it so far, so might be scrapped again (this is the second revision, I lost the first one!) depending on my mood and feedback.
I hate having things in public view that are unfinished, so hopefully this will serve me as a good motivator to finish it off this week.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by abcminiuser: Wed. Jan 23, 2008 - 04:19 AM
1
2
3
4
5
Total votes: 0
Quote:
frequency per-timer, duty-cycle per channel
I could not create that for both outputs, its either - or.
How many outputs per timer is normally used?
One for CTC modes, and up to as many as it has for PWM. Phase and Frequency correct PWM should allow you to vary both the duty cycle of each channel (UPDATE value), and the frequency (TOP value).
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by grinninggator: Fri. Jan 25, 2008 - 12:41 AM
1
2
3
4
5
Total votes: 0
Hey, Dean.
Just wanted to thank you for all your work on this great resource in the hope that a kind word might add to your motivation to push-on through the PWM section. Looks like you are off to a great start!
As an AVR newbie this site, and especially your timer guide, has been an invaluable resource to me.
Posted by JohnnyG101: Wed. Jan 30, 2008 - 04:55 PM
1
2
3
4
5
Total votes: 0
As a newbie, this is THE most informative guide I have found yet relating timers. WOW, before most the code was greek to me but after the explanations, I can actually understand what is going on. Thanks! I hope you find the motovation soon, I cannot wait until you get the PWM section done!!!!!
hi , this is another great work. i cant describe how its useful. thanks..
I am trying with this tutorial because it doesn't require any tools beside my mega162 and small programmer.
I read the first four parts and try it , i fail :(
i changed anything with respect to my avr. here is the code:
TCCR1B |= ( 1 << CS12) ; // set up timer at Fcpu/256
for(;;)
{
// Check timer value in if statement, true when count //matches 1 second
if (TCNT1 >= 31250)
{
TCNT1 = 0; // Reset timer value
ElapsedSeconds++;
if ( ElapsedSeconds == 30 ) // Check if 1/2 minute //has elapsed
{
ElapsedSeconds = 0; // Reset counter variable
PORTC ^= ( 1 << 0); //Toggle the LED
}
}
}
}
another thing to notice is that my programmer has a 4MHZ crystal. but in the program i am asuming i am suing the internal 8mhz.. after programmed i use it in my board without any crystal.!
does it make sense!??
Posted by abcminiuser: Mon. Feb 25, 2008 - 05:44 AM
1
2
3
4
5
Total votes: 0
Sorry, the PDF was subsequently removed as it was outdated. I would update the PDF, but the data is currently sitting on a backup disk awaiting the repair of my laptop.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by superchiku: Mon. Feb 25, 2008 - 07:01 PM
1
2
3
4
5
Total votes: 0
man this is an awesome tutorial it completely cleared my fundamentals cant wait for the pwm section to come in but i got one doubt i worked ont the principle u had given and i made led flash at a frequency of 0.5 hz that means 2 times in a sec the code i had written is as follows
# include
int main(void)
{
PORTD^=(1<<2);
TCNT1=0;
}
}
return(1);
}
but when i connected the led nothing happened instead og toggling it never lit on (the led is fine) is something wrong in the code
Posted by superchiku: Mon. Feb 25, 2008 - 07:17 PM
1
2
3
4
5
Total votes: 0
iwas silly enough to connect to the wrong port and see the output but i so much appreciate ur effort but when will the pwm section come coz i need it as soon as possible coz i need to make a robot
That should be fine, however, there's one more thing you're not accounting for - atomic access of the variables.
It's possible for your COMPA interrupt to fire in between the reading of a multi-byte global variable, which results in corrupted data being used. The solution is to read the volatile value into a normal local variable while interrupts are disabled in your main code:
The added benefit of this in your code, is that since all globals are cached locally with the interrupts disabled, you prevent the update from also occuring between the variable reads. Without this you might get the corrupt data as above, but also correct data, but with half the variables from one sample, and half from another.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Dean,
Just to note that when you want to interrupt protect access to a variable you may not always know that the current interrupt state is SEI or CLI so rather than wrapping the access in a cli() before and an sei() afterwards it sometimes makes sense to define a 'uint8_t sreg_state' then do 'sreg_state = SREG; cli();' before the access and then 'SREG = sreg_state;' afterwards which recovers the pre-existing interrupt state rather than making the assumption that it was SEI.
Cliff
Right as always Cliff, I was oversimplifying for his example, which seemed to always need interrupts enabled. The "correct" way to do it is to save and restore SREG:
Which I wrapped up into a handy macro and submitted to the avr-lib-c project, so it's going to be part of the library in the next avr-lib-c release or so.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
hi Dean,
thanks for ur help ... we are not sure if we have disable our interrupt correctly...
is this a correct way to disable and enable the interrupt? and another problem is even we intend to set to 20ms interrupt but the program seem to perform one second interrupt? did we set the interrupt interval correctly ?
Location : Singapore
That's correct for the atomic access, assuming that you want interrupts on at all times except for the global reads (otherwise you need to save and restore SREG as discussed above).
This line:
Does nothing - I suggest you read the "Bit Manipulation" tutorial. The correct code is:
Although since that bit is cleared when the AVR is reset, it *still* doesn't achieve anything.
What clock speed are you feeding into the AVR? It comes with it's internal 1MHz RC oscillator enabled by default, you need to change the fuses to use an external crystal/clock source.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Great tutorial! I successfully ran several of the code examples in this tutorial on an Olimex AVR MT 128 board (ATMega 128-based) after changing the timer prescale to 1/1024 to match a 16MHz system clock. I also changed the pin assignment to Port E Pin 2 because that pin on my board is adjacent to a ground pin. I'm just starting out with the AVR, and code from your tutorials is the first code I've successfully run on an AVR.
You write very well. You definitely have the right mindset when you write these tutorials - assume NOTHING of the reader. That's where many tutorials fall short. I teach for a living, and I've seen many "introductory" books in several different areas that miss this point. If you ever do get the time to write the book everyone is suggesting, I'll certainly buy it.
Ken
Thanks for the great tutorial. Using your tutorial alone, I've just wrote my very first interrupt implementation, to drive a servo with PWM signal in software, on a atmega8. Loaded it up, and it worked first time. Great tutorial! I'm very impressed. You've taught me how periodic interrupts work.
Thank you.
FYI, the PDF of this tutorial is not in sync with the online version at the top of the thread. I just spent two hours chasing a mistake in the PDF that was fixed online a while ago. Once I figured out that the PDF was old, I fixed it in minutes. On the flip side, I have spent two hours reading the mega168 datasheet trying to figure this mess out :) .
Dean, is there a plan to update the PDF? If not, it might be a good idea to either take it offline or add a disclaimer at the beginning that the document is not up to date.
The tutorial was great even though I had problems. Thanks for putting it together.
You can have my mac when you pry my cold dead fingers off of it.
Kevin McEnhill -- mcenhillk@gmail.com
Kevin,
Sorry about that, my fault. I'm going to remove the PDF version for the meantime, while I try to find an automated solution; maintaining two formats is a pain in the rear and I want to simplify things. Ideally I'd want to go from BBCode from the post straight to a formatted PDF, but that's a pipe-dream. I think the best I can hope for is a BBCode-HTML converter, then a HTML to PDF converter. I'll have a look around.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Actually, I've been thinking today about the comments others have made about me writing a book. Books on AVR and the C language has been done, and I don't want to take away money from hungry mouths like Smokey (and that, as he will tell you, is a big mouth :lol:). However, I think that a book that is essentially a set of worked examples using the different AVR peripherals might fill a niche while not treading on any toes. A bit like a book of my tutorials, but ones that flow from one to the next. Thoughts?
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Well, speaking from my days of having to tackle that cursed Perl language, the Perl Cookbook was a lifesaver. The reference books (i.e. datasheets) are not a good place to learn the basics. The beginner books (i.e. turorials) are not much good once you have run through them once because the examples are too simple. Something like a cookbook that illustrates each function helps bridge the gap.
For example, as of right now, I would KILL for an example of a working input capture counter! I am not ready to give up and go to the AVR Forum yet but a cookbook would be high on my list to Santa right now.
You can have my mac when you pry my cold dead fingers off of it.
Kevin McEnhill -- mcenhillk@gmail.com
Hey All,
I have made a simple timer program that would toggle 3 LEDs after set time. I am using tiny13 uc. The program works perfect if I simulate it using AVR simulator or debug it using JTAGICE mk II but doesn't work at all if I flash program using ISP. All 3 LEDs stay ON instead of toggling after a set time.
I don't think there is an error with ISP. I have developed few other programs (not shown below) and they work fine when I flash them using ISP.
Any idea whats wrong ? I have tried playing with different clock prescales and different time delays (as explained using variable elapstedtimeseconds for longer time delays) but it didn't really help.
Below is program code :
Thanks for all your help !!!
- Umesh
Umesh,
If the LEDs appear to be on all the time it suggests that on/off toggling is simply happening too fast for you to see it (which is the difference between the simulator and real life - one is hundreds of times slower than the other). For one thing start by increasing the clock prescaler to the highest setting - you comment says "Fcpu/1024" but that's not what you are setting - I'll bet you speeded it up so you could see something happening in the simulator!
Cliff
hi
guys can any one tell me how do i start my AVR studies i m bit confused plz help me with this k where i should i start my AVR program......some of my frends said to start studies of AVR 4m ATMEGA8 datasheet....plz tell me or give any brief or supporting tutorial
thanx....
FIRST READ: General Information about Posting in the AVR Forum
https://www.avrfreaks.net/index.p...
ESPECIALLY THE LINK:
http://www.catb.org/~esr/faqs/sm...
After reading those, then start a new thread in the AVR Forum, not the tutorials forum, and give it an informative title like: "How to start with AVR?"
Wilbur
:-D
Hi,
I tried the short LED Toggling Programm on my CM-5 Atmega 128. But i don´t know which LED is mean with DDRG? Could i see this one on my CM-5 case?
Could you help me let my LED´s on CM-5 like AUX/TXD blink? :-)
Added part eight - "Overflow as CTC". Writing PWM section now, just need to figure out the best way to go about it.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Thanks for the new year gift Dean.
Thanks a lot for ur dedicated work on even the new years eve.
i have a doubt.i simulated the code in part part five of ur tutorial in avrstudio.i am not able to see the counting in the tcnt registers.
is it so that the count is not visibile while using interrupts?
Studio has a number of known issues when simulating timers, depending on the version. Check your version's help file -- see if there are any timer-related issues. It should indeed show the timer counting correctly.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
thanks dean.
i was breaking my head over this.
when i programmed mega16 with this code it worked properly.
only problem was with simulation.
i checked up the help page.there is a problem with tcnt buffering wen we use 16 bit timer.
in part eight of ur tutorial you mentioned to use prescale of 64 and in the code you used prescale of 8.
Fixed, copied the wrong code template. Thanks for the good bug-spotting.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
hi
want to ask about the timer
Why I'm getting problem with the TIMSK? The code is like below using m169
The error i always get is:
../bla.c:385: error: 'TIMSK' undeclared (first use in this function)
../bla.c:385: error: (Each undeclared identifier is reported only once
../bla.c:385: error: for each function it appears in.)
How i want to solve this?
Shouldn't it be TIMSK1 instead of just TIMSK?
You are not using a mega 16 I guess? Here is an answer to a similar question (from this thread actually):
I've been playing with the following code on an atmega168@18.432MHz.
I would like to have a faster timer. Why is it so slow? Any idea what to do?
Don't put the sei() in the ISR - the compiler takes care of that for you.
The ISR takes quite a few clock cycles to execute, about 9 just to get to it, plus a whole bunch more to execute your code, and the ISR overhead. 368KHz sounds about right for the maximum ISR speed.
You can do two things.
1) If your ISR is very basic, and has no side-effects, register or otherwise, you can make the ISR "naked" and ommit all the prologue and epilogue code. That'll speed it up, but will cause problems if your ISR tries to modify any of the registers or CPU flags.
2) Switch over to the hardware CTC method I outline. The timer circuitry can toggle the hardware compare pin as fast as the compare flag triggers, with no CPU overhead. That's the preferable option.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Thanks,
I thought about the issue and it seems that the isr routine needs about 80 cycles to run. A naked one could be ok. I'll try the hardware one.
Oh, thanks for the tutorial.
I ran your examples and monitoring things on my digital scope. One one monitor I had the datasheet and on the other your tutorial and avr studio. The datasheet is quite cryptic and contains hardly any quick to use info. I've been looking at the microchip website lately and they have much more info about different things. Atmel is quite sparse with info.
How far are you with the the pwm tutorial? :wink:
Nick
Ah bugger, I've had the PWM section on my "ToDo" list for months, but can never quite seem to bring myself to sit down and really type it out. I lack motivation, and six seasons of Stargate on DVD doesn't help much.
Part Six: Pure Hardware CTC is the section you want to read on the hardware-only toggling solution.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Well I know the feeling... Ever heard of Firefly? just one season and a film called Serenity.
Anyway, I would like to have 3 pwm timers in an atmega168. Plenty of questions and the datasheet is cryptic. Perhaps if you just wrote something about the scope of this (strategy of what to use and perhaps why). Then I have enough to work on.
Thanks in advance.
Nick
I've been playing with the pure hardware ctc routine. I used the two outputs on an atmega 168.
OCR0B = 0..10. At 10 the phase relation between OC0A and OC0B is 100% If OCR0B >10 then the output on OC0B is zero.
Each timer can only have *one* CTC channel operating at a time - if you use both, the timer will clear when the first channel compares, and the second one will never be reached. The point of the multiple channels is for PWM mode, where you can have dual channels operating simultaneously.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Thanks,
Now I've been playing with pwm on timer 0 using two outputs. I would like to get a possibility to set the freq and duty cycle of both outputs independently. But alas. I can only do one channel or use two channels with a fixed freq.
I do not yet understand it completely.
Perhaps you can have a look at the following code and tell me what I'm missing:
As far as I am aware, you set the frequency per-timer, then the duty-cycle per channel. Different frequencies require different timers - but most of the time muti-channel PWM applications all use the same frequency anyway (e.g. robots with servos, LED light controllers, etc).
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
frequency per-timer, duty-cycle per channel
I could not create that for both outputs, its either - or.
How many outputs per timer is normally used?
Added the start of the PWM chapter. Not entirely certain that I like it so far, so might be scrapped again (this is the second revision, I lost the first one!) depending on my mood and feedback.
I hate having things in public view that are unfinished, so hopefully this will serve me as a good motivator to finish it off this week.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
One for CTC modes, and up to as many as it has for PWM. Phase and Frequency correct PWM should allow you to vary both the duty cycle of each channel (UPDATE value), and the frequency (TOP value).
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Dean,
Can you update pdf, please.
Thanks for fine tutorial.
Pop
Hey, Dean.
Just wanted to thank you for all your work on this great resource in the hope that a kind word might add to your motivation to push-on through the PWM section. Looks like you are off to a great start!
As an AVR newbie this site, and especially your timer guide, has been an invaluable resource to me.
As a newbie, this is THE most informative guide I have found yet relating timers. WOW, before most the code was greek to me but after the explanations, I can actually understand what is going on. Thanks! I hope you find the motovation soon, I cannot wait until you get the PWM section done!!!!!
Anyone know where I can find an easy to follow guide for PWM until this tutorial is done?
Atmel's AVR335 app note talks about PWM (in the context of producing sound in fact)
hi , this is another great work. i cant describe how its useful. thanks..
I am trying with this tutorial because it doesn't require any tools beside my mega162 and small programmer.
I read the first four parts and try it , i fail :(
i changed anything with respect to my avr. here is the code:
another thing to notice is that my programmer has a 4MHZ crystal. but in the program i am asuming i am suing the internal 8mhz.. after programmed i use it in my board without any crystal.!
does it make sense!??
-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------
Sorry, the PDF was subsequently removed as it was outdated. I would update the PDF, but the data is currently sitting on a backup disk awaiting the repair of my laptop.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
man this is an awesome tutorial it completely cleared my fundamentals cant wait for the pwm section to come in but i got one doubt i worked ont the principle u had given and i made led flash at a frequency of 0.5 hz that means 2 times in a sec the code i had written is as follows
# include
int main(void)
{
DDRD|=(1<<2);
TCCR1B|=((1<<CS10)|(1<<CS11));
while(1)
{
if(TCNT1>=31250)
{
PORTD^=(1<<2);
TCNT1=0;
}
}
return(1);
}
but when i connected the led nothing happened instead og toggling it never lit on (the led is fine) is something wrong in the code
oh yes iam using atmega16
iwas silly enough to connect to the wrong port and see the output but i so much appreciate ur effort but when will the pwm section come coz i need it as soon as possible coz i need to make a robot
Thanks for your kind reply.
India_AVR
-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------
Kevin Rosenberg
http://b9.com
http://kevin.hypershots.com
Pages