This is the quick start guide for the Digital to Analog Converter (DAC), with step-by-step instructions on how to configure and use the driver in a selection of use cases.
The use cases contain several code fragments. The code fragments in the steps for setup can be copied into a custom initialization function, while the steps for usage can be copied into, e.g., the main application function.
DAC use cases
Basic use case - DA conversion on one channel
In this use case, the DAC is configured for:
- Using DAC on port B, channel 0
- 1V from bandgap as reference, left adjusted channel value
- one active DAC channel, no internal output
- conversions triggered by event channel 0
- 1 us conversion intervals
This use case sets up the DAC to perform DA conversions on one channel, with output to a pin, every time it receives events in event channel 0. The output pin may, e.g., be connected to an oscilloscope or an amplifier and speaker.
Setup steps
Prerequisites
- System Clock Management
- Timer/Counter Driver
Example code
The following configuration must be added to the project (typically to a conf_dac.h file, but it can also be added to your main application file):
#define SPEAKER_DAC DACB
#define SPEAKER_DAC_CHANNEL DAC_CH0
#define RATE_OF_CONVERSION 22050
#define NR_OF_SAMPLES 32
A static const sample buffer with one period of a sine wave must be added:
static const uint16_t sine[NR_OF_SAMPLES] = {
32768, 35325, 37784, 40050, 42036, 43666, 44877, 45623,
45875, 45623, 44877, 43666, 42036, 40050, 37784, 35325,
32768, 30211, 27752, 25486, 23500, 21870, 20659, 19913,
19661, 19913, 20659, 21870, 23500, 25486, 27752, 30211,
};
Add to application initialization:
static void evsys_init(void)
{
EVSYS.CH3MUX = EVSYS_CHMUX_TCC0_OVF_gc;
}
void tc_init(void)
{
tc_enable(&TCC0);
tc_set_wgm(&TCC0, TC_WG_NORMAL);
tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc);
}
void dac_init(void)
{
#ifdef XMEGA_DAC_VERSION_1
#endif
}
Add to main()
:
evsys_init();
tc_init();
dac_init();
Workflow
- Create a function
evsys_init()
to intialize the event system clocks and to link the conversion timer to the correct event channel:
static void evsys_init(void)
{
}
- Use the sysclk service to enable the clock to the event system:
- Connect the TCC0 overflow event to event channel 3:
EVSYS.CH3MUX = EVSYS_CHMUX_TCC0_OVF_gc;
- Note
- If the DAC trigger timer is changed from TCC0, the
EVSYS_CHMUX_*
mask here will also need to be altered.
- Create a function
tc_init()
to intialize the DAC trigger timer:
static void tc_init(void)
{
}
- Enable the clock to the DAC trigger timer:
- Configure the DAC trigger timer in normal Waveform Generation mode:
tc_set_wgm(&TCC0, TC_WG_NORMAL);
- Configure the DAC trigger timer period to overflow at at the specified rate of conversion in Hz:
- Configure the DAC trigger timer clock source to use the peripheral bus frequency:
tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc);
- Create a function
dac_init()
to intialize the DAC:
static void dac_init(void)
{
}
- Config struct for the DAC:
- Initialize the dac configuration by reading back the configuration from the peripheral:
- Create and set configuration:
#ifdef XMEGA_DAC_VERSION_1
#endif
dac_write_configuration(&SPEAKER_DAC, &conf);
- Note
- If the DAC trigger event channel is changed from channel 3, the parameter to dac_set_conversion_trigger() here will also need to be altered.
- Enable DAC:
- Initialize the clock system, event system, DAC trigger timer, and the DAC:
evsys_init();
tc_init();
dac_init();
Usage steps
Example code
Add to application C-file:
uint8_t i = 0;
while (1) {
i++;
i %= NR_OF_SAMPLES;
}
Workflow
- Create a local variable to hold the current sine wave lookup table index:
- Wait for DAC channel to be ready for new data:
- Set the current sine wave table element as new channel value:
-
- Note
- Conversion is triggered by the timer/counter
- Get next index in sine wave array to convert, wrapping around at NR_OF_SAMPLES: