What is an ADC?
An ADC, or Analog to Digital Converter, allows one to convert an analog voltage to a digital value that can be used by a microcontroller. There are many sources of analog signals that one might like to measure. There are analog sensors available that measure temperature, light intensity, distance, position, and force, just to name a few.How Work ADC in AVR- Microcontroller
The AVR ADC allows the AVR microcontroller to convert analog voltages to digital values with few to no external parts. The ATmega8 features a 10-bit successive approximation ADC.ATmega8 has 7 channel ADC at PortC. The ADC has a separate analog supply voltage pin, AVCC. AVCC must not differ more than ± 0.3V from VCC.. The voltage reference may be externally decoupled at the AREF pin. AVCC is used as the voltage reference. The ADC can also be set to run continuously (the free-running mode) or to do only one conversion.ADC Conversion Formula
Where Vin is the voltage on the selected input pin and Vref the selected voltage referenceHow to configure ADC in ATmega8?
The following Registers are used for implementation of ADC in ATmega8ADC Multiplexer Selection
ADC Multiplexer Selection |
ADLAR Selection
ADC Left Adjust Result The ADLAR bit affects the presentation of the ADC conversion result in the ADC Data Register. Write one to ADLAR to left adjust the result. Otherwise, the result is right adjustedADLAR Selection |
Analog Channel Selection Bits The value of these bits selects which analog inputs are connected to the ADC.
ADCSRA Selection
• Bit 7 – ADEN: ADC Enable
Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off
• Bit 6 – ADSC: ADC Start Conversion
In Single Conversion mode, write this bit to one to start each conversion. In Free Running mode, write this
bit to one to start the first conversion.
• Bit 5 – ADFR: ADC Free Running Select
When this bit is set (one) the ADC operates in Free Running mode. In this mode, the ADC samples and
updates the Data Registers continuously. Clearing this bit (zero) will Terminate Free Running mode.
• Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the Data Registers are updated. The ADC
Conversion Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set. ADIF is cleared
by hardware when executing the corresponding interrupt Handling Vector. Alternatively, ADIF is cleared
by writing a logical one to the flag.
• Bit 3 – ADIE: ADC Interrupt Enable
When this bit is written to one and the I-bit in SREG is set, the ADC Conversion Complete
Interrupt is activated.
• Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits
According to the datasheet, this prescalar needs to be set so that the ADC input frequency is between
50 KHz and 200 KHz. The ADC clock is derived from the system clock with help of
ADPS2:0 These bits
determine the division factor between the XTAL frequency and the input clock to the ADC.
- Set ADC value
- Configure output LED pin
- Configure ADC Hardware
- Enable ADC
- Start Analog to Digital Conversions
- WHILE Forever
IF ADC Value Higher then Set value, Turn on LED ELSE Turn Off LED
Set ADC value
Code: uint8_t ADCValue =128;
Configure output LED pin
Code: DDRB|= (1 << PB1);
Configure ADC Hardware
This is done through setting bits in the control registers for the ADC. First, let's set the prescalar for the ADC. According to the datasheet, this prescalar needs to be set so that the ADC input frequency is between 50 KHz and 200 KHz. The ADC clock is derived from the system clock. With a system frequency of 1MHz, a prescaler of 8 will result in an ADC frequency of 125 Khz. The prescaling is set by the ADPS bits in the ADCSRA register. According to the datasheet, all three ADPS2:0 bits must be set to 011 to get the 8 prescaler.
Code : ADCSRA |= (0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
Next, let's set the ADC reference voltage. This is controlled by the REFS bits in the ADMUX
register. The following sets the reference voltage to AVCC.
Code:
ADMUX |= (1 << REFS0);
To set the channel passed through the multiplexer to the ADC, the MUX bits in the ADMUX
register need to be set accordingly. Since we are using ADC5 here
Code:
ADMUX&=0xF0;
ADMUX|=5;
In order to put the ADC into free-running mode, set the aptly-named ADFR bit in the
ADCSRA register:
Code:
ADCSRA |= (1 << ADFR);
One last settings change will be made to make reading the ADC value simpler. Though the
ADC has a resolution of 10 bits, this much information is often not necessary. This 10 bit
value is split across two 8 bit registers, ADCH and ADCL. By default, the lowest 8 bits of the
ADC value are found in ADCL, with the upper two being the lowest two bits of ADCH. By
setting the ADLAR bit in the ADMUX register, we can left align the ADC value. This puts the
highest 8 bits of the measurement in the ADCH register, with the rest in the ADCL register. If
we then read the ADCH register, we get an 8 bit value that represents our 0 to 5 volt
measurement as a number from 0 to 255. We're basically turning our 10 bit ADC
measurement into an 8 bit one. Here's the code to set the ADLAR bit:
Code:
ADMUX |= (1 << ADLAR);
That completes the setup of the ADC hardware for this example. Two more bits need to be
set before the ADC will start taking measurements.
Enable ADC
To enable the ADC, set the ADEN bit in
ADCSRA:
Code:
ADCSRA |= (1 << ADEN);
Start Analog to Digital Conversions
To start the ADC measurements, the ADSC bit in ADCSRA needs to be set:
Code:
ADCSRA |= (1 << ADSC);
At this point, the ADC would begin continuously sampling the voltage presented on ADC5. The
code to this point would look like this:
WHILE Forever
The only thing left to do is test the ADC value and set the LEDs to display a high / low
indication. Since the ADC reading in ADCH has a maximum value of 255, a test value of th
was chosen to determine whether the voltage was high or low. A simple IF/ELSE statement
in the FOR loops will allow us to turn the correct LED on:
Code
if(ADCH >ADCValue)
{
PORTB |= (1 << PB0); // Turn on LED
}
else
{
PORTB&= ~(1 << PB0); // Turn off LED
}
At the end Complete code is
Code:
#include <avr/io.h>
ADMUX |= (1 << REFS0); // Set ADC reference to AVCC
ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading
ADMUX&=0xF0;
ADMUX|=5; // MUX values needed to be changed to use ADC0
ADCSRA |= (1 << ADFR); // Set ADC to Free-Running Mode
ADCSRA |= (1 << ADEN); // Enable ADC
ADCSRA |= (1 << ADSC); // Start A2D Conversions
while(1) // Loop Forever
{
if(ADCH > ADCValue)
{
PORTB |= (1 << PB0); // Turn on LED1
}
else
{
PORTE &= ~(1 << PB1); // Turn off LED1
}
}
return 0;
}
No comments