Using and Testing the AVR® MCU ADC
In this video:
- Provide a block diagram overview of the AVR® MCU's 10-bit Successive Approximation Analog-to-Digital Converter (ADC).
- Input voltage reference options and input channels.
- Discuss prescale and conversion timing requirements, keeping the ADC clock between 50 and 200 kHz, setting a prescalar of 64, since we have a F_CPU = 8 MHz.
- Set the range of the ADC by setting the voltage reference (to AVcc).
- Open a new project and set writing ADC_init ( ) using the datasheet as a coding reference.
- Choose ADC1 as ADC input channel, connected to port C1 on the ATmega328P Xplained mini.
- Configure the options in the ADC status and control register and ADC Auto Trigger Enable (ADATE).
- Toggle an LED in the ADC ISR, so that we have a line of code to set a breakpoint on.
- Connect a potentiometer to vary the voltage on the ADC pin.
- Debug to verify the register configuration.
- Example reading on the ADC result register: 0x156, or 342.
- Vin = ADC * Vref / 1024 = 342 * 3.297 = 1.1011 measured by ADC, 1.104 measured by voltmeter, so 2.9 mV error or 1 LSB.
- "AVR120: Characterization and Calibration of the ADC on the AVR MCU".
Procedure
Review the ADC Block Diagram
As we have done in previous lessons, we will start by reviewing the ADC block diagram from the datasheet. It shows us that we will need to configure the ADC through three registers.
Review Important Considerations
- The device's successive approximation circuitry requires an input clock frequency between 50kHz and 200kHz to get maximum resolution.
- The frequency of the CPU must be at least 100kHz in order for the prescaler to generate and acceptable clock frequency.
- In order to get the full range of the ADC the voltage reference we should set the AVCC equal to VCC
- After the conversion is complete, the conversion result can be found in the ADC Result Registers (ADCL, ADCH). The formula is for a single ended conversion...
Start a New Project in MPLAB X IDE
Create a new project just like in previous lessons and and add a new AVR main.c file to it. It should similar to this:
Initialize the ADC
Create a function called ADC_init() and call it from main.c. In this function we will configure the registers introduced in Step 1.
The ADMUX Register is shown along with a table to help us set the appropriate bits to set AVCC as our voltage reference
We will set AVCC equal to VCC so we need to set the bit for REFS0 in our ADC_init() function. We will also choose ADC1 as our input channel. The bit to set is indicated in the table as shown: T
Here is the updated code:
{
ADMUX |= (1 << REFS0) | (1 << MUX0); //AVCC equal to VCC and ADC1 input
}
The datasheet tells us that the ADC1 channel is on Pin 24 (PC1). This is the pin we will connect to the wiper of the potentiometer when we start testing the ADC.
Now we need to set some bits in the ADC Status register (ADCSRA). Most of the bits will be set in this register
Since we have enabled interrupts in this register, we need to add the interrupt header toward the beginning of our program and add sei() to our ADC_init function.
{
ADMUX |= (1 << REFS0) | (1 << MUX0); //AVCC equal to VCC and ADC1 input
ADCSRA |= (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
sei();
}
Here is the full code for the lesson:
#include <avr/interrupt.h>
#define LED_ON PORTB |= (1<<PORTB5)
#define LED_OFF PORTB &= ~(1<<PORTB5)
#define LED_TOGGLE PINB |= (1<<PINB5)
ISR(ADC_vect)
{
LED_TOGGLE;
}
void ADC_init(void)
{
ADMUX |= (1 << REFS0) | (1 << MUX0); //AVCC equal to VCC and ADC1 input
ADCSRA |= (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
sei();
}
int main(void) {
ADC_init();
while (1) {
}
}
Wire up the Potentiometer
Connect a potentiometer as shown. The wiper should go to PC1 and the remaining two connections to VCC and GND.
Program the Device for Debugging
Press the Debug Project button at the top of the MPLAB X IDE GUI.
Now, place a breakpoint at the LED_TOGGLE macro inside the ISR.
If working properly, you should see the LED toggle each time PLAY is pressed at the top of the MPLAB X IDE GUI.
Add a Watch Variable
Add the ADC special function register to the Watch window. When an ADC conversion is complete, the result is found in this 16-bit register.
Try moving the potentiometer all the way to clockwise and selecting PLAY. Now, turn it all the way to the other extreme and run it again. You should have seen the ADC values swing from 0x03FF to 0x0000.