ADC (1)
ADC (1)
Review of C Programming
Introduction to A-to-D conversion
▪ An ADC samples an analogue signal at discrete times and converts the sampled
signal to digital form.
▪ Obstacle sensor & audio cues in the cane for the blind
❑ Measure distance to nearest object with an ultrasonic sensor
▪ Intelligent clothesline
❑ Use sensors to measure humidity, temperature, and wind speed
▪ The clock rate of the ADC can be different from the CPU clock rate:
❑ One ADC conversion takes 13 ADC clock cycles
❑ An ADC pre-scaler will decide the actual ADC clock rate
ADC unit ─ Relevant pins
8 ADC
input pins
External Vref
Supply voltage to
ADC and Port A
ATmega16 chip
ADC unit ─ Block diagram
ADCCSRA to configure
the ADC unit
ADCMUX to select
the input source
ADCH/ACHL register
to store digital output
8 analog
input pins
ADC Multiplexer Selection Register (ADCMUX)
▪ If the input voltage has a different dynamic range, we can use mode 00 to select an
external reference voltage
Selecting input source and gain factor
ADCH ADCL
ADCH ADCL
▪ The ADC clock is obtained by dividing the CPU clock and a division factor
▪ There are 8 possible division factors, decided by the 3 bits {ADPS2, ADPS1, ADPS0}
▪ Example: Using internal clock of 1Mz and ADC pre-scaler bits of ‘011’, one ADC clock cycle = 8 x CPU
clock cycle = 8 µs
Special Function IO Register (SFIOR)
▪ Three flags in register SFIOR specify the event that will auto-trigger an A-to-D conversion
Steps to use the ADC
1 0 0 0 0 0 0 1
ADEN ADSC ADATE ADIF ADIE ADPS2 ASPS1 ADPS0 ADCSRA
#include <avr/io.h>
int main (void){
unsigned char result;
DDRB = 0xFF; // set port B for output
// Configure the ADC module of the ATmega16
ADMUX = 0b01100000; // REFS1:0 = 01 -> AVCC = 5v as reference,
// ADLAR = 1 -> Left adjust,
// MUX4:0 = 00000 -> ADC0 as input,
ADCSRA = 0b10000001; // ADEN = 1: enable ADC,,
// ADSC = 0: don't start conversion yet,
1
// ADATE = 0: disable auto trigger,
// ADIE = 0: disable ADC interrupt,
// ASPS2:0 = 001: ADC prescaler = 2.
while(1){ // main loop
ADCSRA |= 0b01000000; // Start conversion by setting flag ADSC 2
while (ADCSRA & 0b01000000){;} // Wait until conversion is completed
result = ADCH; // Read the top 8 bits, output to PORTB 3
PORTB = ~result; // Port B connected to LEDs (0 = ON, 1 = OFF)
}
return 0;
}
Using ADC interrupt
▪ In the polling approach shown previously, we must check ADSC flag to know
when an ADC operation is completed
▪ Alternatively, the ADC unit can trigger an interrupt when ADC is done
▪ In the ISR, we can write code to read registers ADCL and ADCH
ISR(ADC_vect){
}
result = ADCH; // Read the top 8 bits, and store in variable result
3
int main (void){
DDRB = 0xFF; // set port B for output
// Configure the ADC module of the ATmega16
ADMUX = 0b01100000; // REFS1:0 = 01 -> AVCC as reference,
// ADLAR = 1 -> L ft dj t eft adjust
// MUX4:0 = 00000 -> ADC0 as input
ADCSRA = 0b10001001; // ADEN = 1: enable ADC,
// ADSC = 0: don't start conversion yet
//
//
ADATE = 0: diable auto trigger,
ADIE = 1: enable ADC interrupt,
1
// ASPS2:0 = 002: pre-scaler = 2
sei(); // enable interrupt system globally
while(1){ // main loop
ADCSRA |= 0b01000000; // start a conversion
PORTB = ~result; // display on port B 2
}
return 0;
}