I am trying my first ADC to run. Using ICCAVR application builder, I can get the adc_init
void adc_init(void)
{
ADCSRA = 0x00; //disable adc
ADMUX = 0x00; //select adc input 0
ACSR = 0x80;
ADCSRB = 0x00;
ADCSRA = 0xE6;
}
I have very faundamental questions though, if you guys don’t mind.
(Q1). Which register do I read when I read ( poll) the ADC 8-bit value.
(Q2). How do I know the value?? for e.g is the value 255 whatever? I don’t have lcd to write to??
Would be a great help
Cheers:
Check out the datasheets at atmel.com for details, but usually the ADC result registers are called ADCL and ADCH. If you only need an 8-bit result, setting bit5 of ADMUX will left-align the 10-bit result in those registers, so then you can just read ADCH alone.
Make sure you wait until the conversion finishes before reading the result (bit6 of ADCSRA will clear when it’s done).
And for testing, the easiest way I know is to use PWM to change the brightness of an LED according to the result.
connect a serial port to the mega, with a setting of 9600, 8 Data, 1 Stop, No Parity
this is assuming you have a 8MHZ crystal connected to it.
#include <mega88.h>
// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x40
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
// Declare your global variables here
void main(void)
{
// Declare your local variables here
unsigned int ad_result;
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: Off
// ADC4: Off, ADC5: Off
DIDR0=0x3F;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA3;
ADCSRB&=0xF8;
while (1)
{
ad_result = read_adc(0); // read chnl 0
printf("AtoD Value = %u\r\n",ad_result);
};
}
Assigning the adc read value to change the pulse width and quick check the ADC functioning. Hm…nn… great, I was not aware of this idea.
I will have go at the windows Hyperterminal and write the ADC values too.
Thanks Hips guys
Cheers
Sorry!
Should check the data sheet first.
I have to read the registers ADCH and ADCL. But not sure how to verify them. I want to make sure the conversion is correct!!
Thanks
Something wierd is going on. I typed the previous last reply on 8th June and it poped up yesteray ( 11th of june). Please ignore my last posting ( that starts with “sorry !”) as I have alread recieved some cool suggestions.
chao
Hi,
Any idea why this is not working? I am trying to read 8 bit value from ADCH and assign it for pwm. My PWM is working. Looks like I am not getting and adc value in ADCH.
Thanks!
void main()
{
init_devices();
while(1)
{
if ( CHKFLAG( ADCSRA,6) == 0 )// check the conversion is complete
{
OCR2B =ADCH; // asign the ADC value as duty cycle to the pwm
}
}
void adc_init(void)
{
ADCSRA = 0x00; //disable adc
ADMUX = 0x00; //select adc input 0
SETFLAG(ADMUX,5); // read only 8 bit from ADCH
ACSR = 0x80;
ADCSRB = 0x00;
ADCSRA = 0xE6;
}
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
adc_init();
timer2_init();
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK0 = 0x00; //timer 0 interrupt sources
TIMSK1 = 0x00; //timer 1 interrupt sources
TIMSK2 = 0x00; //timer 2 interrupt sources
PCMSK0 = 0x00; //pin change mask 0
PCMSK1 = 0x00; //pin change mask 1
PCMSK2 = 0x00; //pin change mask 2
PCICR = 0x00; //pin change enable
PRR = 0x00; //power controller
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
I got it to work finally. I found out that if I enable ADCSRA, bit 4 (ADIF), the adc does not work. just wonder why?
I have one more faundamental question. When I set the ADMUX values to choose which adc channel to use in the while(1) loop my adc did not work Hence ADMUX values are in adc_init function in the main at the start. Now I want to use the multiple channels how do I go about changing the ADMUX values( which part of the code)?? bit cconfused :? please help
Cheers