INTERNAL ADC OF AVR(lm35)(c) This tutorial is taken from the book
MY EXPERIENCE IN PROGRAMMING AVR MICROCONTROLLER
IN C USING WINAVR/AVRGCC.
you can download it free from the files
section(FILE-AVRBOOK.RAR) of yahoo group-booksbybibinhttp://groups.yahoo.com/group/booksbybibin/
comments about this book on
www.booksbybibin.blogspot.comINTERNAL ADC OF AVR
See the datasheet for the registers. Atmeg32 has 10 bit
ADC having two registers ADCL and ADCH. But we are using it in 8 bit resolution, so
that error will be lowered. But there will always be noise error in the reading. I used
LM35, got error about .01V. See even conversion is of 10 bit resolution and we are
using 8 bits resolution(i.e, first 8 bits leaving last two LSB's). In 8 bit resolution mode
we read ADCH. If you want to read 10 bits then use ADC(see in the include file, you
will understand better). I used internal analog voltage reference of 2.56 volt.
Remember to use a capacitor in the AREF pin, use a .01uF capacitor. The choice of
capacitance will affect the reading. See in the datasheet how to avoid noise better. I
tried with .1uF and .01uF capacitors. Here I am using LM35 temperature sensor to
ADC input.
FOLDER:lm_2-7seg(file-avrbook.rar from yahoo group-booksbybibin)
main
/*----------------------------------------------------------------
-----------------HEADER FILES-------------------------------------
-----------------------------------------------------------------*/
#include "two7seg.c"
/*----------------------------------------------------------------
-----------------FUNCTIONS---------------------------------------
-----------------------------------------------------------------*/
void Init_ADC(void);
int Read_ADC(void);
void main()
{
Init_ADC();
do
{
Ouptut_Display(Read_ADC());
}
while(1);
}
void Init_ADC(void)
{
ADMUX|=(_BV(ADLAR) | _BV(REFS1)| _BV(REFS0)) ;
// RFS1 and RFS0 are for Internal Reference voltage of 2.56V AND 8 BIT CONVERSION
ADMUX&=~(_BV(MUX0)|_BV(MUX1)|_BV(MUX2)|_BV(MUX3)|_BV(MUX4)); //SELECTING CHANNEL0
ADCSRA|=(_BV(ADEN) | _BV(ADPS2) | _BV(ADPS0)) ; //normal conversion without interrupt
ADCSRA&=~(_BV(ADSC)|_BV(ADATE)|_BV(ADIF)|_BV(ADIE)|_BV(ADPS1));//clock/32 speed
}
int Read_ADC(void)
{
ADCSRA|=_BV(ADSC); //start conversion
while(!((ADCSRA&_BV(ADIF))>>ADIF));
return ADCH;
}
7seg.c
/*----------------------------------------------------------------
-----------------HEADER FILES-------------------------------------
-----------------------------------------------------------------*/
#include<avr/io.h>
/*----------------------------------------------------------------
-------------CONNECTION BETWEEN 7 segment AND ATMEGA32-----------
-----------------------------------------------------------------*/
#define DATA_DDR DDRC
#define DATA_PORT PORTC
#define Pin_a 0
#define Pin_b 1
#define Pin_c 2
#define Pin_d 3
#define Pin_e 4
#define Pin_f 5
#define Pin_g 6
#define Pin_Dec 7
#define DATA_MASK 0XFF
/*----------------------------------------------------------------
-----------------FUNCTIONS---------------------------------------
-----------------------------------------------------------------*/
void Init_Ports(void);
void Display(int a);
void delay_ms(unsigned char time_ms);
/*----------------------------------------------------------------
-----------------FUNCTIONS TO INITIALIZE PORTS--------------------
-----------------------------------------------------------------*/
void Init_Ports(void)
{
DATA_DDR = DATA_MASK; //for setting data pin's for output
}
/*----------------------------------------------------------------
-----------------FUNCTIONS TO DISPLAY VALUES----------------------
-----------------------------------------------------------------*/
void Display(int a)
{
switch(a)
{
case 0:
DATA_PORT|=_BV(Pin_g);
DATA_PORT&=~(_BV(Pin_a)|_BV(Pin_b)|_BV(Pin_c)|_BV(Pin_d)|_BV(Pin_e)|_BV(Pin_f));
break;
case 1:
DATA_PORT|=(_BV(Pin_a)|_BV(Pin_d)|_BV(Pin_e)|_BV(Pin_f)|_BV(Pin_g));
DATA_PORT&=~(_BV(Pin_b)|_BV(Pin_c));
break;
case 2:
DATA_PORT|=(_BV(Pin_c)|_BV(Pin_f));
DATA_PORT&=~(_BV(Pin_b)|_BV(Pin_d)|_BV(Pin_e)|_BV(Pin_a)|_BV(Pin_g));
break;
case 3:
DATA_PORT|=(_BV(Pin_e)|_BV(Pin_f));
DATA_PORT&=~(_BV(Pin_c)|_BV(Pin_d)|_BV(Pin_a)|_BV(Pin_b)|_BV(Pin_g));
break;
case 4:
DATA_PORT|=(_BV(Pin_a)|_BV(Pin_d)|_BV(Pin_e));
DATA_PORT&=~(_BV(Pin_c)|_BV(Pin_b)|_BV(Pin_f)|_BV(Pin_g));
break;
case 5:
DATA_PORT|=(_BV(Pin_b)|_BV(Pin_e));
DATA_PORT&=~(_BV(Pin_a)|_BV(Pin_c)|_BV(Pin_d)|_BV(Pin_f)|_BV(Pin_g));
break;
case 6:
DATA_PORT|=(_BV(Pin_a)|_BV(Pin_b));
DATA_PORT&=~(_BV(Pin_c)|_BV(Pin_d)|_BV(Pin_f)|_BV(Pin_g)|_BV(Pin_e));
break;
case 7:
DATA_PORT|=(_BV(Pin_d)|_BV(Pin_e)|_BV(Pin_f)|_BV(Pin_g));
DATA_PORT&=~(_BV(Pin_a)|_BV(Pin_c)|_BV(Pin_b));
break;
case 8:
DATA_PORT&=~(_BV(Pin_a)|_BV(Pin_d)|_BV(Pin_e)|_BV(Pin_c)|_BV(Pin_b)|_BV(Pin_f)|_BV(Pin_g));
break;
case 9:
DATA_PORT|=(_BV(Pin_d)|_BV(Pin_e));
DATA_PORT&=~(_BV(Pin_a)|_BV(Pin_c)|_BV(Pin_b)|_BV(Pin_f)|_BV(Pin_g));
break;
}}
/*----------------------------------------------------------------
--------FUNCTION TO GENERATE DELAY IN MILLISECONDS----------------
-----------------------------------------------------------------*/
void delay_ms(unsigned char time_ms)
{
unsigned short delay_count = F_CPU / 400;
unsigned short cnt;
asm volatile ("\n"
"L_dl1%=:\n\t"
"mov %A0, %A2\n\t"
"mov %B0, %B2\n"
"L_dl2%=:\n\t"
"sbiw %A0, 1\n\t"
"brne L_dl2%=\n\t"
"dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt)
:"r"(time_ms), "r"((unsigned short) (delay_count))
);
}
two7seg.c
/*----------------------------------------------------------------
-----------------HEADER FILES-------------------------------------
-----------------------------------------------------------------*/
#include "7seg.c"
/*----------------------------------------------------------------
-------------CONNECTION BETWEEN 74126 AND ATMEGA32---------------
-----------------------------------------------------------------*/
#define CONTROL_DDR DDRD
#define CONTROL_PORT PORTD
#define Led_1 0
#define Led_2 1
#define CONTROL_MASK 0X03
/*----------------------------------------------------------------
-----------------FUNCTIONS---------------------------------------
-----------------------------------------------------------------*/
void Init126_Ports(void);
void Ouptut_Display(int i);
/*----------------------------------------------------------------
-----------------MAIN FUNCTION------------------------------------
-----------------------------------------------------------------*/
void Ouptut_Display(int i)
{
unsigned int a;
Init126_Ports();
Init_Ports();
CONTROL_PORT|=_BV(Led_1); //switching ON first 7 segment to hold LSB
Display((i%10&0x0f));
//delay_ms(500);
CONTROL_PORT&=~_BV(Led_1); //switching OFF first 7 segment to hold LSB
CONTROL_PORT|=_BV(Led_2); //switching ON first 7 segment to hold LSB
a=i/10;
Display((a%10&0x0f));
//delay_ms(500);
CONTROL_PORT&=~_BV(Led_2); //switching OFF first 7 segment to hold LSB*/
//come fast otherwise display go off
}
void Init126_Ports(void)
{
CONTROL_DDR=CONTROL_MASK; //setting ports for output
CONTROL_PORT&=~(_BV(Led_1)|_BV(Led_2)); //switching off 7 segment at starting
}
See the problem with persistance of vision. Here the temperature varies with time and
it is shown on LED i.e, it is shown a non decimal value.
ADCSRA|=_BV(ADSC); //start conversion
while(!((ADCSRA&_BV(ADIF))>>ADIF));
return ADCH;
Here I am using single conversion mode. I am waiting for the conversion to end and
we are using 8 bit conversion mode. The 8 bit converted value is there in ADCH
register and we are returning the values.
Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.