Society of Robots - Robot Forum
Software => Software => Topic started by: superchiku on April 09, 2008, 12:20:30 AM
-
i wanted to test the interrupt routine of the avr adc in which i wrote a simple program where i selected 2 channels of admux and stored the adc converted values of each channel in 1 variable but i got problem, the values of the adc were not consistent , i mean if i change the value of 1 channel , the value for other channel would also change.
IN NORMAL CONVERSION MODE U JUST WAIT UNTIL THE ADIF BIT IS SET BUT SINCE HERE IT IS CLEARED BY HARDWARE I DONT KNOW HOW TO KNOW IF A CONVERSION HAS BEEN MADE AND AN INTERRUPT HAS BEEN CALLED , PLZZ HELP ME SOLVE THIS PROBLEM
the code is like this
# include<stdio.h>
#include <avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
unsigned int a,b,c;
int main(void)
{
ADCSRA|=(1<<ADEN)|(1<<ADATE);//enable adc & auto trigger
ADCSRA|=(1<<ADPS1)|(1<<ADPS0);//set prescaler to 8
ADCSRA|=(1<<ADIE);//enable interrupts
SFIOR|=_BV(ADTS2)|_BV(ADTS1)|_BV(ADTS0);/free runnin
sei();//enable global interrupts
ADCSRA|=(1<<ADSC);//start adc conversion
while(1)
{
c=1;
ADMUX=0x61;//select channel 1
c=2;
ADMUX=0x62;//select channel 2
}
return(0);
}
ISR(ADC_vect)
{
if(c==1)
{
a=ADCH;//write adc value of channel1 in a
}
if(c==2)
{
b=ADCH;//write adc value of channel2 in b
}
}
iam using an atmega16 with internal 1mhz clock
-
I DONT KNOW HOW TO KNOW IF A CONVERSION HAS BEEN MADE AND AN INTERRUPT HAS BEEN CALLED ,
can you make your question a little more clearer?
i didnt get it quite well but what is your interrupt trigger source? how many hertz?
to know if an interupt has been called just show a specific value on a port in the interupt routine....
-
the trigger source will be a normal sensor like a ldr or a sharp ir , i needed to know how do u effectively change channels in an interrupt driven adc code so that i will get exact readings for each channel and store them in an variable and these values will only be changed if their equivalent channels triggers source will give different analog readings
-
i mean to say like in normal conversion routines without using interrupts we wait until the ADIF BIT IS SET THEN WE store the value in a variable , change channel and start another conversion but in case of interrupts the adif bit is cleared by hardware so thats where the problem comes coz my algorithm never realises where to know that a conversion has been done and store the accurately the digital value in a variable.
so i was asking what should be the algorithm so that ill be able to when an adc conversion has been made and an interrupt routine called???
-
You need code that goes something like this
unsigned int a,b,c;
int main(void)
{
ADCSRA|=(1<<ADEN)|(1<<ADATE);//enable adc & auto trigger
ADCSRA|=(1<<ADPS1)|(1<<ADPS0);//set prescaler to 8
ADCSRA|=(1<<ADIE);//enable interrupts
SFIOR|=_BV(ADTS2)|_BV(ADTS1)|_BV(ADTS0);/free runnin
c=1;
ADMUX=0x61;//select channel 1
sei();//enable global interrupts
ADCSRA|=(1<<ADSC);//start adc conversion
while(1);
return(0);
}
ISR(ADC_vect)
{
if(c==1)
{
a=ADCH;//write adc value of channel1 in a
c=2;
ADMUX=0x62;//select channel 2
}
else
{
b=ADCH;//write adc value of channel2 in b
c = 1;
ADMUX=0x61;//select channel 1
}
}
-
yes i tried that too but that too give errors , i saw in the datasheet that u can only change reference if:
1. adate or aden bit is cleared
2.minimum 1 cycle after a interrupt call
3. "i dont remember"
so i tried to clear aden bits i got the answer but i dont think it iwas reliable so if u think there can a better code then pllzzz rectify this one# include<stdio.h>
#include <avr/io.h>
#include<avr/interrupt.h>
unsigned int a,b,c,d;
int main(void)
{
ADCSRA|=(1<<ADATE);
ADCSRA|=(1<<ADPS1)|(1<<ADPS0);
ADCSRA|=(1<<ADIE);
SFIOR=(1<<ADTS1);
sei();
c=1;
ADMUX=0x61;
ADCSRA|=(1<<ADEN);
ADCSRA|=(1<<ADSC);
while(1)
{
}
return(0);
}
ISR(ADC_vect)
{
if(c==1)
{
ADCSRA&=~(1<<ADEN);
a=ADCH;
c=2;
ADMUX=0x62;
d=ADMUX;
ADCSRA|=(1<<ADEN);
while(!(ADCSRA&(1<<ADIF)));
}
if(c==2)
{
ADCSRA&=~(1<<ADEN);
b=ADCH;
c=1;
ADMUX=0x61;
d=ADMUX;
ADCSRA|=(1<<ADEN);
while(!(ADCSRA&(1<<ADIF)));
}
}