The code snippet below shows how to initialize the ADC and how to use the
V
DD as an internal input to measure the voltage which is powering the
device. It also uses USART to transmit the results in such a manner that it may be
graphed by the Data Visualizer. See Section
Get Code Examples from GitHub for
instructions on how to download the code, and Section
Plotting Graph in Data Visualizer for
instructions on how to set up the graph in Data
Visualizer.
#define F_CPU 3333333ul
#include <avr/io.h>
#include <util/delay.h>
#include <math.h>
#define TIMEBASE_VALUE ((uint8_t) ceil(F_CPU*0.000001))
#define ADC_MAX_VALUE ((1 << 12) - 1)
#define BAUD_RATE 9600
#define BAUD_REG_VAL ((float)(64 * F_CPU / (16 * (float)BAUD_RATE)) + 0.5)
static uint16_t adc_reading;
static float voltage;
void adc_init()
{
ADC0.CTRLA = ADC_ENABLE_bm;
ADC0.CTRLB = ADC_PRESC_DIV2_gc;
ADC0.CTRLC = ADC_REFSEL_1024MV_gc | (TIMEBASE_VALUE << ADC_TIMEBASE_gp);
ADC0.CTRLE = 17;
ADC0.MUXPOS = ADC_MUXPOS_VDDDIV10_gc;
ADC0.COMMAND = ADC_MODE_SINGLE_12BIT_gc;
}
void usart_init()
{
PORTB.DIRSET = PIN2_bm;
USART0.CTRLB = USART_TXEN_bm;
USART0.BAUD = BAUD_REG_VAL;
}
void USART_send_DV(float *float_ptr)
{
uint8_t *byte_ptr = (uint8_t *) float_ptr;
while(!(USART0.STATUS & USART_DREIF_bm));
USART0.TXDATAL = 0x33;
for(uint8_t i = 0; i < sizeof(float); i++)
{
while(!(USART0.STATUS & USART_DREIF_bm));
USART0.TXDATAL = byte_ptr[i];
}
while(!(USART0.STATUS & USART_DREIF_bm));
USART0.TXDATAL = ~0x33;
}
int main(void)
{
adc_init();
usart_init();
while(1)
{
ADC0.COMMAND |= ADC_START_IMMEDIATE_gc;
while(!(ADC0.INTFLAGS & ADC_SAMPRDY_bm));
adc_reading = ADC0.SAMPLE;
voltage = (float)(adc_reading * 1.024 * 10) / ADC_MAX_VALUE;
USART_send_DV(&voltage);
_delay_ms(500);
}
}