Last active
January 4, 2016 09:19
-
-
Save gshrikant/8601604 to your computer and use it in GitHub Desktop.
ADC peripheral driver for ATmega328P
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* adc.c | |
* | |
* Analog-Digital Conversion example | |
* | |
* Hardware: ATMega328P at 16 MHz | |
* Toolchain: avr-gcc v4.3.3 | |
* Editor: Eclipse Kepler (4.0) with GNU Make | |
* Usage: | |
* Include and edit settings in adc.h and compile using 'make all' | |
* | |
* Created on: 22-Jan-2014 | |
* Author: Shrikant Giridhar | |
*/ | |
#include "adc.h" | |
/* Debug Mode; Set on Release */ | |
#define _DEBUG 1 | |
#if _DEBUG | |
#include <util/delay.h> | |
#include <stdlib.h> | |
#include "uart.h" | |
#endif | |
// Select channel of your choice | |
#define ADC_CHANNEL CHANNEL_3 | |
/*! Sets up ADC reference voltage, channel and output format */ | |
void initADC(void) | |
{ | |
// Set selected channel as input | |
DDRC &= ~_BV(ADC_CHANNEL); | |
PORTC &= ~_BV(ADC_CHANNEL); | |
// AVCC reference; right-adjusted; channel selection | |
ADMUX |= (AVCC << REFS0) | (ADC_CHANNEL << MUX0); | |
ADCSRA = (PRESCALAR_4 << ADPS0); | |
ADC_ENABLE(); | |
} | |
/*! \brief Retrieves converted data; blocking function */ | |
uint16_t getConvData(void) | |
{ | |
/* | |
* There are a couple of ways of checking if the conversion is over. | |
* 1. In a single-ended conversion, the ADSC is cleared as soon as the | |
* conversion is over otherwise it stays high. | |
* 2. The ADIF bit is set on conversion complete. | |
* 3. The ADIF bit could set off an interrupt to indicate end of conversion. | |
* | |
* Note that the first method wouldn't be useful if ADC is free-running, in | |
* which case methods 2 or 3 would be appropriate. | |
* | |
*/ | |
uint16_t result; | |
ADC_START(); | |
// while (ADCSRA & _BV(ADSC)); | |
while(!ADC_DONE()); // Stay here while conversion completes | |
// ADC data update is blocked on reading ADCL, keeps read atomic | |
// result = (uint16_t) (ADCL + (ADCH << 8)); | |
// Otherwise, just read the 16-bit register, ADCW | |
result = (uint16_t) (ADCW); | |
return result; | |
} | |
#if _DEBUG | |
int main(void) | |
{ | |
char adcData[10]; | |
uint16_t result; | |
initADC(); | |
initUART(); | |
while(1) | |
{ | |
result = getConvData(); | |
itoa(result, adcData, 10); | |
writeString(adcData); | |
putByte(' '); | |
putByte('\r'); | |
putByte('\n'); | |
} | |
return 0; | |
} | |
#endif | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* adc.h | |
* | |
* Created on: 23-Jan-2014 | |
* Author: Shrikant Giridhar | |
*/ | |
#ifndef ADC_H_ | |
#define ADC_H_ | |
#include <avr/io.h> | |
#include <stdint.h> | |
/* Auto-trigger options */ | |
#define AUTO_TRIG 0 | |
#if AUTO_TRIG | |
/* Define auto-triggering sources */ | |
#define FREE_RUNNING (0x00) | |
#define AN_COMPARATOR (0x01) | |
#define EXT_IRQ (0x02) | |
#define TMR0_COMPA (0x03) | |
#define TMR0_OVF (0x04) | |
#define TMR1_COMPB (0x05) | |
#define TMR1_OVF (0x06) | |
#define TMR1_CAP (0x07) | |
#endif | |
/* ADC Channel Selection */ | |
#define CHANNEL_0 (PINC0) | |
#define CHANNEL_1 (PINC1) | |
#define CHANNEL_2 (PINC2) | |
#define CHANNEL_3 (PINC3) | |
#define CHANNEL_4 (PINC4) | |
#define CHANNEL_5 (PINC5) | |
/* Reference voltage settings */ | |
#define AREF (0x00) | |
#define AVCC (0x01) | |
#define BAND_REF (0x03) | |
/* ADC Clock settings */ | |
#define PRESCALAR_2 (0x01) // ADC_CLK = CLK/2 | |
#define PRESCALAR_4 (0x02) // ADC_CLK = CLK/4 | |
#define PRESCALAR_8 (0x03) // ADC_CLK = CLK/8 | |
#define PRESCALAR_16 (0x04) // ADC_CLK = CLK/16 | |
#define PRESCALAR_32 (0x05) // ADC_CLK = CLK/32 | |
#define PRESCALAR_64 (0x06) // ADC_CLK = CLK/64 | |
#define PRESCALAR_128 (0x07) // ADC_CLK = CLK/128 | |
/* Useful Macros */ | |
#define POWER_DOWN() (PRR |= _BV(PRADC)) | |
#define ADC_ENABLE() (ADCSRA |= _BV(ADEN)) | |
#define ADC_DISABLE() (ADCSRA &= ~_BV(ADEN)) | |
#define ADC_START() (ADCSRA |= _BV(ADSC)) | |
#define ADC_DONE() (ADCSRA & _BV(ADIF)) | |
#define ADC_INTEN() (ADCSRA |= _BV(ADIE)) | |
#define AUTO_EN() (ADCSRA |= (AUTO_TRIG << ADATE)) | |
/* Prototypes */ | |
void initADC(void); | |
uint16_t getConvData(void); | |
#endif /* ADC_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment