Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Using ADC of ATMega328 by Interrupts

Status
Not open for further replies.

habibparacha

Junior Member level 2
Joined
Oct 25, 2010
Messages
24
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Activity points
1,482
Hi all,

I am trying to use the ADC of ATMega 328 using its ADC interrupt service routine but it is not working. When I use it without the ISR by just calling the ADC_read() function than it works fine but I have to use it by using the ADC interrupt. The problem is it doesn't even enter the ISR even the global interrupt is also set. I am using PORTB as an indicator whether it goes into particular code area or not.
Infact I am not able to get into any ISR not event the Timer0 Overflow.

Please help Its urgent.

Code:
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>

volatile uint8_t lower;
volatile uint8_t higher;

unsigned int ADC_read(unsigned char ch)
{ 
	ch= ch & 0b00000111;
	ADMUX=(1<<REFS0)|ch;  // reading specified number of pin
 	ADCSRA|=(1<<ADSC);
	while(!(ADCSRA & (1<<ADIF))); 
	ADCSRA|=(1<<ADIF);
	//lower=ADCL;		// ADC registor lower bits
	//higher=ADCH;		// ADC registor upper bits
	//PORTB= ~PORTB;

}

void ADC_init(void)
{
	ADMUX=(1<<REFS0); 
	ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADIE);
	sei();
}


ISR(ADC_vect)
{   
	PORTB=~PORTB;
	lower = ADCL;
	higher = ADCH;	
	
}	

int main(void)
{		
    DDRC=0x00; //initialize as input
	DDRB=0xff;
	DDRD=0xc2;
	PORTB=0xff;
	PORTD=0xff;

	ADC_init();
	
	while(1)
	{
		ADC_read(0);
	}		
}
 
Last edited:

in the following function remove the red lines and it will work fine

Code:
unsigned int ADC_read(unsigned char ch)
{ 
	ch= ch & 0b00000111;
	ADMUX=(1<<REFS0)|ch;  // reading specified number of pin
 	ADCSRA|=(1<<ADSC);
	[COLOR="#FF0000"]while(!(ADCSRA & (1<<ADIF))); [/COLOR]
	[COLOR="#FF0000"]ADCSRA|=(1<<ADIF);[/COLOR]
	//lower=ADCL;		// ADC registor lower bits
	//higher=ADCH;		// ADC registor upper bits
	//PORTB= ~PORTB;

}

The interrupt will execute when the ADIF flag is set and it will be cleared by hardware, there is no point in using a loop to check it and clear it manually.

It is also a good idea to add a small delay of a few us after the channel change and before you start the conversion.

Alex
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top