| Author |
Message |
|
|
Posted: Nov 07, 2007 - 06:34 AM |
|

Joined: Aug 30, 2007
Posts: 6
|
|
Hi Dean,
thanks for ur advice..
We have declared our variables below:
Code:
unsigned volatile int verticalspeed=0;
int volatile reference=0;
int volatile altitudeR_int=0;
int main(void)
{
// initialise interrupt here
while(1)
{
// at here the [b]altitudeR_int [/b] changes according to our sensor
printf("Pump ON \n" );
printf("Altitude= %d ft \n", altitudeR_int);
printf("reference= %d mb \n",reference);
printf("verticalspeed:%u ", verticalspeed);
}
}
ISR(TIMER1_COMPA_vect)
{
verticalspeed=((altitudeR_int-reference)*60);
reference = altitudeR_int;
}
Is this the correct way of using voletile global variables to return the verticalspeed into the main? |
_________________ Location : Singapore
|
| |
|
|
|
|
|
Posted: Nov 07, 2007 - 06:51 AM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
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:
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 [b]altitudeR_int [/b] 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  |
_________________
|
| |
|
|
|
|
|
Posted: Nov 07, 2007 - 01:35 PM |
|


Joined: Jul 18, 2005
Posts: 33138
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
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 |
_________________
|
| |
|
|
|
|
|
Posted: Nov 07, 2007 - 09:47 PM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
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:
Code:
uint8_t SREG_Save = SREG;
cli();
// Atomic variable access here
SREG = SREG_Save;
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  |
_________________
|
| |
|
|
|
|
|
Posted: Nov 09, 2007 - 06:00 AM |
|

Joined: Aug 30, 2007
Posts: 6
|
|
hi Dean,
thanks for ur help ... we are not sure if we have disable our interrupt correctly...
Code:
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 [b]altitudeR_int [/b] 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 ? |
_________________ Location : Singapore
|
| |
|
|
|
|
|
Posted: Nov 09, 2007 - 06:15 AM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
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:
Code:
TIMSK |= (0 << OCIE1A); disable the interrupt
Does nothing - I suggest you read the "Bit Manipulation" tutorial. The correct code is:
Code:
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  |
_________________
|
| |
|
|
|
|
|
Posted: Nov 13, 2007 - 04:32 PM |
|

Joined: Sep 09, 2006
Posts: 7
Location: Maine
|
|
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 |
|
|
| |
|
|
|
|
|
Posted: Nov 20, 2007 - 03:03 PM |
|

Joined: Jun 10, 2006
Posts: 14
|
|
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. |
|
|
| |
|
|
|
|
|
Posted: Nov 24, 2007 - 08:18 PM |
|


Joined: Jan 17, 2007
Posts: 91
Location: Bellevue, NE
|
|
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
|
| |
|
|
|
|
|
Posted: Nov 25, 2007 - 11:12 AM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
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  |
_________________
|
| |
|
|
|
|
|
Posted: Nov 25, 2007 - 01:51 PM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
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 ). 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  |
_________________
|
| |
|
|
|
|
|
Posted: Nov 25, 2007 - 05:07 PM |
|


Joined: Jan 17, 2007
Posts: 91
Location: Bellevue, NE
|
|
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
|
| |
|
|
|
|
|
Posted: Nov 26, 2007 - 05:17 AM |
|

Joined: Nov 19, 2007
Posts: 1
|
|
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 :
Code:
Code:
#include <avr/io.h>
#include "fuelgauge.h"
void main(void)
{
unsigned char counter;
init(); // Initialize the controller
TCCR0A |= (1<< WGM01) | (0 << WGM00);
OCR0A= 0xFF;
TCCR0B |= ((0 << CS02) | (0 << CS01) | (1 << CS00)); // Set up timer at Fcpu/1024
for (;;)
{
counter=TCNT0;
if (TIFR0 & (1 << OCF0A))
{
PINB = 0x07; // Toggle the LED
TIFR0 = (1 << OCF0A);
}
}
}
void init(void)
{
CLKPR = (1 << CLKPCE);
CLKPR = 0;
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB4) ;
PORTB = (1<<PB0)|(1<<PB1)|(1<<PB2);
PINB = 0x00;
}
Code:
Code:
Thanks for all your help !!!
- Umesh |
|
|
| |
|
|
|
|
|
Posted: Nov 26, 2007 - 10:35 AM |
|


Joined: Jul 18, 2005
Posts: 33138
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
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 |
_________________
|
| |
|
|
|
|
|
Posted: Dec 10, 2007 - 08:27 PM |
|

Joined: Dec 10, 2007
Posts: 1
|
|
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: Dec 10, 2007 - 08:35 PM |
|

Joined: Oct 03, 2007
Posts: 55
Location: Kittyhawkistan
|
|
|
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....
FIRST READ: General Information about Posting in the AVR Forum
http://www.avrfreaks.net/index.php?name ... mp;t=18856
ESPECIALLY THE LINK:
http://www.catb.org/~esr/faqs/smart-questions.html
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 |
|
|
| |
|
|
|
|
|
Posted: Dec 11, 2007 - 04:36 PM |
|

Joined: Nov 02, 2007
Posts: 12
|
|
|
|
|
|
|
Posted: Dec 20, 2007 - 05:44 PM |
|

Joined: Dec 20, 2007
Posts: 1
|
|
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?  |
|
|
| |
|
|
|
|
|
Posted: Dec 31, 2007 - 12:14 AM |
|


Joined: Jan 23, 2004
Posts: 6964
Location: Melbourne, Victoria, Australia
|
|
Added part eight - "Overflow as CTC". Writing PWM section now, just need to figure out the best way to go about it.
- Dean  |
_________________
|
| |
|
|
|
|
|
Posted: Jan 01, 2008 - 06:32 AM |
|

Joined: Mar 12, 2007
Posts: 54
|
|
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?
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
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
}
|
|
|
| |
|
|
|
|
|