Overview
The Analog to Digital Converter (ADC) convert analog voltage value to a digital representation that the micro-processor could understand. Most of modern micro-controller has at least one built-in ADC module that can be use by software configuration. The most common ADC resolution is between 8-bit and 12-bit with an acceptable conversion rate.
The resolution give more precise digital data for the micro-controller. However its reference voltage and lower clock also effect the precision of the analog input value. Some 32-bit micro-controller especially the STM32 micro-controller series has an ADC module with the resolution of 12-bit with the conversion rate up to 2MSPS. Some 16-bit dsPIC micro-controller series has an ADC module with the resolution of 10-bit and 1~2MSPS conversion rate.
Commonly we use the ADC to read temperature value, flex sensor and strain gauge etc.
ATMega644P ADC Programming Example
The ADC of the ATMega644P has a 10-bit analog to digital converter with the maximum conversion rate up to 15kSPS. It has up to 8 analog input channel (ADC7:ADC0) via PortA. The conversion triggers by user software (set ADC to start) or by any interrupt sources.
![]() |
| Analog-to-digital Converter Block Schematic |
The software configuration of the ADC module of AVR micro-controller is simpler than other micro-controllers. It has a few registers to configure.
I don't write its detail here since the ADC process of the ATMega644P is very similar to the ATMega32.
ADC and LED Example 1
In this introductory example the ATMega644P read the analog input from ADC0(PA0). The 10-bit ADC result will converts to 8-bit by shifting right that will display on PORTB.
C Source Code:
- /*
- * 9-ADC_LED.c
- *
- * Created: 1/30/2026 3:28:06 PM
- * Author : Admin
- */
- #include <avr/io.h>
- int main(void)
- {
- DDRB=0xFF;
- //PA0 or ADC0 as an analog input
- DDRA=0;
- //Turn on the ADC module
- ADCSRA=(1<<ADEN);
- uint16_t temp;
- while (1)
- {
- //Start the conversion
- ADCSRA|=(1<<ADSC);
- //Wait for the completion
- while((ADCSRA&(1<<ADSC))==1);
- //Read the result
- temp=ADCL+(ADCH<<8);
- PORTB=temp>>2;
- }
- }
Proteus Simulation:
![]() |
| Proteus Simulation #1 |
AVR Prototype Board Test:
ADC and LED Example 2
I use this prototype board's LED and POT to make a LED shifting using the ADC voltage level. It's very similar to a ring counter. However I need to convert between ADC value counter value.
Source Code:
- /*
- * 9-ADC_BarGraph.c
- *
- * Created: 1/30/2026 4:21:13 PM
- * Author : Admin
- */
- #include <avr/io.h>
- int main(void)
- {
- DDRB=0xFF;
- //PA0 or ADC0 as an analog input
- DDRA=0;
- //Turn on the ADC module
- ADCSRA=(1<<ADEN);
- long temp,div;
- while (1)
- {
- //Start the conversion
- ADCSRA|=(1<<ADSC);
- //Wait for the completion
- while((ADCSRA&(1<<ADSC))==1);
- //Read the result
- temp=ADCL+(ADCH<<8);
- div=(temp*8)/1024;
- PORTB=(1<<div);
- }
- }
Proteus Schematic and Simulation:
![]() |
| Proteus Schematic and Simulation |
AVR Prototype Board Test:
ADC and LED Example 2
There are two on-board ADC inputs, POT and LM35 temperature sensor. The LCD will display the analog input from POT(ADC0) and LM35(ADC1). The LM35 temperature (in degree Celsius) is equivalent to 10mV that's 2 in digital value (+5.0VDC voltage reference).
![]() |
| LM35DZ in TO-92 Package |
Source Code:
- /*
- * 9-ADC_LCD.c
- *
- * Created: 1/30/2026 4:47:25 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <stdio.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- void adc_init(void){
- /*Set PA0 and PA1 to input*/
- DDRA&=~(1<<0);
- DDRA&=~(1<<1);
- ADCSRA=(1<<ADEN);
- /*Select AD0*/
- ADMUX=0x03;
- }
- unsigned int read_adc(char channel){
- //Select Channel
- ADMUX=channel;
- //Start Convsersion
- ADCSRA|=(1<<ADSC);
- //Wait for Completion
- while(ADCSRA&(1<<ADSC));
- //Get the 10-bit values
- return (ADCL+(ADCH<<8));
- }
- int main(void)
- {
- /* Replace with your application code */
- lcd_init();
- lcd_text("ATMega644P ADC");
- lcd_xy(1,2);
- lcd_text("POT AND LM35");
- adc_init();
- _delay_ms(1000);
- lcd_clear();
- unsigned int temp;
- float voltage;
- char msg[16];
- lcd_command(0x0C);
- while (1)
- {
- //Read POT
- temp=read_adc(0);
- //Convert To Voltage
- voltage=temp*5.0/1023;
- sprintf(msg,"ADC0: %4d %.2fV",temp,voltage);
- lcd_xy(1,1); lcd_text(msg);
- //Read LM35
- temp=read_adc(1);
- voltage=temp*5.0/1023;
- voltage*=100;
- sprintf(msg,"Temp: %0.1f%cC",voltage,223);
- lcd_xy(1,2); lcd_text(msg);
- _delay_ms(1000);
- }
- }
Proteus Schematic:
![]() |
| Proteus Schematic |
AVR Prototype Board:
![]() |
| Program Tested on my AVR Prototype Board |
Unfortunately I bough some fake LM35DZ due to their local availability and low cost, around 0.50USD. The original LM35DZ temperature chip costs around 1USD. However some online store also sell this chip in bulk price at very low cost.
I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.
![]() |
| 10 PCBs for only 5USD |
For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.
![]() |
| PCBWay Instant Quote |













No comments:
Post a Comment