AVR analog comparator and avr-gcc example

An Analog comparator is a pretty simple peripheral, but it can give big benefits. Comparator module is included in all Mega series of AVR microcontrollers. Simply speaking, Comparator allows comparing voltage values applied to two pins of microcontrollers. The comparison results are a logical level, which can be read by the program(ACO- Analog Comparator Output bit). There is also the ability to generate an interrupt, which depends on the comparator resulting level. And more- timer T1 can capture this level what allows measuring the signal length of analog signals.

AVR comparator

To use pins as comparator inputs, they must be prepared and configured as input(DDRx=0), and pull-up resistors must be disconnected (PORTx=0). In some models like Atmega48x/88x/168x, Atmega165x, Atmega325x,3250x,645x/6450x, and Atmega640x/128x/1281x/2560x/2561x, there is the ability to disconnect digital buffers of AIN0 and AIN1 pins that allows the use of these pins only for analog signal input – this minimizes overall power consumption.

Digital buffers can be disconnected by writing “1” where bits AIN0D and AIN1D are in register DIDR1:

The Comparator is controlled by one byte ACSR.

Bit No.NameDescription
7ACD0-ON, 1-OFF comparator
6ACGB0 – AIN0 to the positive input of comparator; 1- reference voltage to positive comparator input
5ACOResult of comparing.
4ACIInterrupt flag
3ACIEEnable comparator interrupts
2ACICConnect comparator to timer/counter T1 (1- connected, 0-not)
1,0ACIS1:ACIS0Interrupt conditions select

In general Comparator, the module is a simple comparator. If the voltage in input of AIN0 is bigger than in AIN1, then the result of comparing is equal to 1 and 0 otherwise. The result is stored in ACSR register bit ACO.

If the comparator is not used ACD bit should be set to 1 because it will reduce power consumption. Also, interrupt from the comparator should be disabled. As I mentioned, the comparator can compare voltage to reference voltage if bit ACBG is set. Then positive input of the comparator becomes 1.23V. The second comparator pin can be connected to any pin where ADC input is by using a multiplexer. If Multiplexer is enabled (bit ACME in SFIOR register) and ADC is off, then MUX2..0 in ADMUX register selects the input pin(refer to datasheet).

AVR Comparator C programming example

Let’s write a simple example of using the AVR comparator module. Program is written in C and compiled with AVR-GCC compiler(WinAVR). Program example illustrates when Positive Comparator input is connected to Internal voltage regulator 1.23V by setting ACGB bit in the ACSR register. Also, as negative comparator input is taken, ADC3 input via Multiplexer as indicator LED is connected to PORTD0 pin. If the input voltage is lower than 0.23V, then Diode is OFF, and if the voltage exceeds 1.23V, the diode lights ON. Diode state is changed with ANA_COMP_vect interrupt service routine on ACO bit toggle in ACSR register.

AVR comparator animation

Working program code:

// ***********************************************************
// Project:  Analog Comparator example	
// Module description: Analog comparator example with positive comparator
// input connected to Vref 1.23V. When compared voltage exceed 1.23V LED lighst on.
// When voltage drops bellow - LED turns OFF. Comparator inputis connected to ADC3 pin.
// ***********************************************************
#include <avr\io.h>      
#include <avr\interrupt.h>
#define AINpin PA3
#define LED PD0
void Init(){
	DDRA&=~(1<<AINpin);//as input
	PORTA&=~(1<<AINpin);//no Pull-up
	DDRD|=(1<<LED); //Led pin as output
	PORTD|=(1<<LED);//Initally LED is OFF
	SFIOR|=(1<<ACME);//enable multiplexer
	ADCSRA&=~(1<<ADEN);//make sure ADC is OFF
	ADMUX|=(0<<MUX2)|(1<<MUX1)|(1<<MUX0); //select ADC3 as negative AIN
	(0<<ACD)|	//Comparator ON
	(1<<ACBG)|	//Connect 1.23V reference to AIN0
	(1<<ACIE)|	//Comparator Interrupt enable
	(0<<ACIC)|	//input capture disabled
	(0<<ACIS1)| //set interrupt on output toggle
	sei();//enable global interrupts
// Interrupt handler for ANA_COMP_vect
ISR(ANA_COMP_vect) {
if bit_is_clear(ACSR, ACO)
	PORTD&=~(1<<LED);//LED is ON
	else 	PORTD|=(1<<LED);//LED is OFF
// ***********************************************************
// Main program
int main(void) {
	 while(1) {     // Infinite loop; interrupts do the rest

Comments are closed.