United International University: EEE 424: Microprocessor and Interfacing Laboratory Experiment#5
United International University: EEE 424: Microprocessor and Interfacing Laboratory Experiment#5
United International University: EEE 424: Microprocessor and Interfacing Laboratory Experiment#5
1. Objective
The objective of this experiment is to familiarize the students with the use of Analogue to Digital
converter (ADC) of ATmega32.
Vin D0
Digital
Start Output
Conversion D10
GND
4. Registers to be used for ADC
a) ADC Data Register
The converted data is stored in a register called ADCW which is a 16-bit register, its lower byte and
higher bites can be accessed from 8-bit registers ADCL and ADCH respectively. The 10-bit digital data is
stored in 16-bit ADCW register and the data can be stored either in right or in left adjusted form.
ADCW
ADCH ADCL
ADEN – ADC enable bit (ADC will not all work if this bit not made high)
ADSC – ADC start conversion bit (by making this bit high the conversion process is started)
ADATE – ADC auto trigger enable bit (is made high if the ADC to be triggered automatically)
ADIF – ADC interrupt flag (as explained in the earlier section)
ADIE – ADC interrupt enable bit (if somebody wants to use ISR of ADC, this bit is to be high)
ADPS2:ADPS0 – Combination of this three bits decide the pre-scaling of clock for the ADC
000 – fosc
001 – fosc/2
010 – fosc/4
011 – fosc/8
100 – fosc/16
101 – fosc/32
110 – fosc/64
111 – fosc/128
ADMUX
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
REFS1:0 – Selection of Voltage Reference. 00-AREF, 01-AVCC, 10-NOT USED, 11-internal 2.56V
ADLAR – right or left adjusted data in ADCW register, 0- right and 1- left adjustment
MUX4:0 – Combination of these 5 bits makes the selection of input channel (single ended) or channels
(for differential input)
The combinations for the channel selection are given below:
When ADLAR = 0
When ADLAR = 1
For single ended input:
1. Steps of programming
Step #1: Make the pin for the selected ADC channel as Input pin
Step #2: Enable the ADC
Step #3: Select the conversion speed
Step #4: Select voltage reference and ADC input channels
Step #5: Set the Start Conversion bit, ADSC
Step #6: Wait for some time and continuously monitor the ADIF bit.
Step #7: After ADIF bit is found to be high; ADCL and ADCH bytes are read
Step #8: If want to read the selected channel again go to step 5
6. An Experiment with the ADC
A variable voltage source will be connected to one of the channel of ADC. It is channel ADC0 (1st
channel). The analogue voltage will be converted into digital form by the ADC. The voltage read and
after converting into decimal will be displayed on LCD. Reference voltage will be connected to AVCC. The
prescaler is chosen as 128. So, for 16 MHz crystal, ADC frequency will be 16 MHz/128 = 125 kHz
8. The code
The CodeVision code for the experiment is as follows:
#include <mega32.h>
#include <delay.h>
#include <stdlib.h>
#include <alcd.h>
interrupt [ADC_INT] void adc_isr(void)
{
float adc_data;
char disp[16];
// Read the AD conversion result
adc_data=ADCW/204.8;
ftoa(adc_data,2,disp);
lcd_gotoxy(0,0);
lcd_puts(disp);
}
void main(void)
{
ADMUX=0b01000000;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) |
(1<<ADPS0);
lcd_init(16);
#asm("sei")
while (1)
{
delay_us(10);
ADCSRA |= (1<<ADSC);
delay_ms(1000);
}
}
Note that Step size – Vref/210. In this experiment, Vref=AVCC so, step size = 5/1024=1/204.8
9. Temperature Sensor
The temperature sensors produce analogue voltage corresponding to temperature. We shall do an
experiment with a commonly used sensor called LM35. The features are as follows:
11. The code for the reading analogue voltage from a temperature sensor
#include <mega32.h>
#include <delay.h>
#include <stdlib.h>
#include <alcd.h>
interrupt [ADC_INT] void adc_isr(void)
{
float adc_data;
char disp[16];
// Read the AD conversion result
adc_data=ADCW*1.5/10.24;
ftoa(adc_data,2,disp);
lcd_gotoxy(0,0);
lcd_puts(disp);
}
void main(void)
{
ADMUX=0b00000000;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) |
(1<<ADPS0);
lcd_init(16);
#asm("sei")
while (1)
{
delay_us(10);
ADCSRA |= (1<<ADSC);
delay_ms(1000);
}
}