8 Appendix
Generating Constant Analog Signal Code Example
/* 3.33 MHz (needed for delay) */
#define F_CPU (3333333UL)
/* DAC value */
#define DAC_EXAMPLE_VALUE (0x20)
/* VREF Startup time */
#define VREF_STARTUP_MICROS (25)
#include <avr/io.h>
#include <util/delay.h>
void VREF_init(void);
void DAC0_init(void);
void DAC0_setVal(uint8_t val);
void VREF_init(void)
{
/* Voltage reference at 4.34V */
VREF.CTRLA |= VREF_DAC0REFSEL_4V34_gc;
/* DAC0/AC0 reference enable: enabled */
VREF.CTRLB |= VREF_DAC0REFEN_bm;
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_MICROS);
}
void DAC0_init(void)
{
/* Disable digital input buffer */
PORTA.PIN6CTRL &= ~PORT_ISC_gm;
PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
/* Disable pull-up resistor */
PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;
/* Enable DAC, Output Buffer, Run in Standby */
DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
}
void DAC0_setVal(uint8_t val)
{
DAC0.DATA = val;
}
int main(void)
{
VREF_init();
DAC0_init();
DAC0_setVal(DAC_EXAMPLE_VALUE);
while (1)
{
;
}
}
Generating Sine Wave Signal Code Example
/* 3.33 MHz (needed for delay) */
#define F_CPU (3333333UL)
/* VREF Startup time */
#define VREF_STARTUP_MICROS (25)
/* Number of steps for a sine wave period */
#define SINE_WAVE_STEPS (100)
/* Sine wave amplitude */
#define SINE_AMPLITUDE (127)
/* Sine wave DC offset */
#define SINE_DC_OFFSET (128)
/* 2*PI */
#define M_2PI (2 * M_PI)
/* Frequency of the sine wave */
#define OUTPUT_FREQ (50)
/* Step delay for the synthesis loop */
#define STEP_DELAY_MICROS ((1000000 / OUTPUT_FREQ) / SINE_WAVE_STEPS)
#include <avr/io.h>
#include <util/delay.h>
#include <math.h>
/* Buffer to store the sine wave samples */
uint8_t sineWave[SINE_WAVE_STEPS];
void sineWaveInit(void);
void VREF_init(void);
void DAC0_init(void);
void DAC0_setVal(uint8_t val);
void sineWaveInit(void)
{
for(uint16_t i = 0; i < SINE_WAVE_STEPS; i++)
{
sineWave[i] = SINE_DC_OFFSET + SINE_AMPLITUDE * sin(i * M_2PI / SINE_WAVE_STEPS);
}
}
void VREF_init(void)
{
/* Voltage reference at 4.34V */
VREF.CTRLA |= VREF_DAC0REFSEL_4V34_gc;
/* DAC0/AC0 reference enable: enabled */
VREF.CTRLB |= VREF_DAC0REFEN_bm;
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_MICROS);
}
void DAC0_init(void)
{
/* Disable digital input buffer */
PORTA.PIN6CTRL &= ~PORT_ISC_gm;
PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
/* Disable pull-up resistor */
PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;
/* default value */
DAC0.DATA = SINE_DC_OFFSET;
/* Enable DAC, Output Buffer, Run in Standby */
DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
}
void DAC0_setVal(uint8_t val)
{
DAC0.DATA = val;
}
int main(void)
{
uint16_t i = 0;
VREF_init();
DAC0_init();
sineWaveInit();
while (1)
{
DAC0_setVal(sineWave[i++]);
i = i % SINE_WAVE_STEPS;
_delay_us(STEP_DELAY_MICROS);
}
}
Reading DAC Internally With ADC Code Example
/* 3.33 MHz (needed for delay) */
#define F_CPU (3333333UL)
/* VREF Startup time */
#define VREF_STARTUP_MICROS (25)
#include <avr/io.h>
#include <util/delay.h>
void VREF_init(void);
void DAC0_init(void);
void ADC0_init(void);
uint16_t ADC0_read(void);
void DAC0_setVal(uint8_t val);
void VREF_init(void)
{
/* Voltage reference at 4.34V */
VREF_CTRLA |= VREF_DAC0REFSEL_4V34_gc;
/* DAC0/AC0 reference enable: enabled */
VREF_CTRLB |= VREF_DAC0REFEN_bm;
/* Voltage reference at 4.34V */
VREF_CTRLA |= VREF_ADC0REFSEL_4V34_gc;
/* ADC0 reference enable: enabled */
VREF_CTRLB |= VREF_ADC0REFEN_bm;
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_MICROS);
}
void DAC0_init(void)
{
/* Enable DAC */
DAC0.CTRLA = DAC_ENABLE_bm;
}
void ADC0_init(void)
{
ADC0.CTRLC = ADC_PRESC_DIV4_gc /* CLK_PER divided by 4 */
| ADC_REFSEL_INTREF_gc /* VDD reference */
| ADC_SAMPCAP_bm; /* Sample Capacitance Selection: enabled */
ADC0.CTRLA = ADC_ENABLE_bm /* ADC Enable: enabled */
| ADC_RESSEL_10BIT_gc; /* 10-bit mode */
/* Select ADC channel */
ADC0.MUXPOS = ADC_MUXPOS_DAC0_gc;
}
uint16_t ADC0_read(void)
{
/* Start ADC conversion */
ADC0.COMMAND = ADC_STCONV_bm;
/* Wait until ADC conversion done */
while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )
{
;
}
/* Clear the interrupt flag by writing 1: */
ADC0.INTFLAGS = ADC_RESRDY_bm;
return ADC0.RES;
}
void DAC0_setVal(uint8_t val)
{
DAC0.DATA = val;
}
int main(void)
{
uint8_t dacVal = 0;
volatile uint16_t adcVal = 0;
VREF_init();
DAC0_init();
ADC0_init();
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_MICROS);
DAC0_setVal(dacVal);
while (1)
{
adcVal = ADC0_read();
/* do something with the adcVal */
dacVal++;
DAC0_setVal(dacVal);
}
}
Using DAC as Negative Input for AC Code Example
/* 3.33 MHz (needed for delay) */
#define F_CPU (3333333UL)
/* 1.4V output @ VREF = 1.5V */
#define DAC_DATA_1V4 (239)
/* VREF Startup time */
#define VREF_STARTUP_MICROS (25)
#include <avr/io.h>
#include <util/delay.h>
void VREF_init(void);
void DAC0_setVal(uint8_t val);
void DAC0_init(void);
void AC0_init(void);
void VREF_init(void)
{
/* Voltage reference at 1.5V */
VREF.CTRLA |= VREF_DAC0REFSEL_1V5_gc;
/* DAC0/AC0 reference enable: enabled */
VREF.CTRLB |= VREF_DAC0REFEN_bm;
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_MICROS);
}
void DAC0_setVal(uint8_t val)
{
DAC0.DATA = val;
}
void DAC0_init(void)
{
/* Disable digital input buffer */
PORTA.PIN6CTRL &= ~PORT_ISC_gm;
PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
/* Disable pull-up resistor */
PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;
/* Enable DAC, Output Buffer, Run in Standby */
DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
}
void AC0_init(void)
{
/* Negative input from DAC0 */
/* Positive input from pin PA7 */
AC0.MUXCTRLA = AC_MUXNEG_DAC_gc
| AC_MUXPOS_PIN0_gc;
/* Enable, Output on PA5, Low Power mode */
AC0.CTRLA = AC_ENABLE_bm
| AC_OUTEN_bm
| AC_RUNSTDBY_bm
| AC_LPMODE_bm;
}
int main(void)
{
/* Voltage divider -> VDD/2 input on PA7 */
/* AC output on LED on PA5 */
/* LED turns OFF when battery is below 2.8V (PA7 below 1.4V) */
VREF_init();
DAC0_init();
AC0_init();
/* 1.4V output @ VREF = 1.5V */
DAC0_setVal(DAC_DATA_1V4);
while (1)
{
;
}
}
