ADC Working@Atmega328P

Posted by

In this blog, I will discuss minimal programming required for ADC block . This may help embedded beginners to understand implementation of ADC in  Arduino Board using C.

This is in continuation with my last blog post.  I strongly recommend you to read earlier blogs for better understanding . If you find something missing, Please provide feedback in comment box so that I can take corrective action

ADC Block

Step 1: Make sure  ADC is not shut down

  • Power Reduction ADC bit (PRR.PRADC) =0 to enable ADC

Step 2: Select reference voltage = AVcc(5V) and required analog pin from multiplexer

  • ADC Multiplexer Selection register ADMUX.MUX[3:0] to select analog input channel
  • Select VRef  . The ADC count corresponding to VRef is 0x3FF (1023)

Step 3: Enable ADC logic using ADCSRA

  • ADC Control and Status Register A (ADCSRA.ADEN).=1 to enable ADC
  • Voltage reference and input channel selections will not take effect until ADEN is set
  • The 10-bit result , ADCH and ADCL, is by default right adjusted. Set Left Adjust Result bit ADMUX.ADLAR =1 if left adjust is required.

Step 4: Start ADC conversion and wait for its completion

  • A single conversion is started  by setting PRADC=0 and ADC Start Conversion bit, ADSC=1. ADSC will be cleared by hardware when the conversion is completed.

Tested Code

//Define required pins and important registers

int pin_A0=14;
int pin_A1=15;

#define mPRR            (*(volatile uint8_t *)0x64)
#define mADCSRA    (*(volatile uint8_t *)0x7A)
#define mADMUX      (*(volatile uint8_t *)0x7C)
#define bitVal(bitNum)   1 << bitNum
#define VREF_DEFAULT   0x01

//We are using Serial and PinMode initialization from library. You may refer to earlier blogs //about these . Therefore , In this blog only ADC part will be explained

void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(pin_A0, INPUT);
pinMode(pin_A1, INPUT);
}

float analogPin(uint8_t chNo)
{
unsigned int data,tmpH,tmpL;
float avgADC;
float resultV;
data=0;

//Select VREF=01 default Vcc(5V) channel number
mADMUX= (VREF_DEFAULT <<6 ) | (chNo);

//Taking  100 sample reading just for experiment
for(int i=0;i<100;i++)
{
mADCSRA |= bitVal(ADSC); //start ADC conversion

//wait for ADSC flag to be cleared by hardware
while(mADCSRA & bitVal(ADSC));
tmpL = ADCL;
tmpH = ADCH;
data=data+((tmpH << 8)| (tmpL));
delay(10);
}
avgADC=(float)data/100;  //average

//Calculate Analog voltage corresponding to data            resultV= (avgADC*5)/1024;
return resultV;
}

void loop() {
Serial.print(“Input voltage at A0=”);
Serial.println(analogPin(0));
delay(5000);
Serial.print(“Input voltage at A1=”);
Serial.println(analogPin(1));

}

Output

I connected Pin14(A0) to ground and Pin15(A1) to a resister divider voltage=1.72V  measured by Multimeter. Following is the giff file of output 

This is discussed in this Embedkari video.

References : All documents are available here. I am referring to most of these :

 

Thanks for reading till end. Please provide your feedback regarding this article. Also subscribe  Embedkari for other interesting topics. .

Thanks for reading till end. I am trying to improve usability of my  site. Did you find this discussion helpful ? If so,  Please subscribe to YouTube channel Embedkari as well for additional embedded related stuff.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.