The MCHP_DACC_SAMx block provides access to the Digital-to-Analog Converter Controller (DACC) available in SAM E5x, SAM E7x, and SAM C2x microcontrollers. This peripheral enables high-quality analog voltage generation for applications including waveform synthesis, precision voltage references, audio output, and control signal generation.
10-bit or 12-bit resolution (device-dependent)
Dual-channel independent or differential output modes
Up to 1 MSPS conversion rate
Internal or external voltage reference options
Built-in waveform generation capabilities
DMA support for continuous waveform streaming
Low glitch energy and monotonic output
| Family | Representative Devices | Resolution | Channels | Max Rate |
|---|---|---|---|---|
| SAM E5x | SAME54P20A, SAME53J18A | 12-bit | 2 (DAC0, DAC1) | 1 MSPS |
| SAM E7x | SAME70Q21B, SAMV71Q21B | 12-bit | 2 (DAC0, DAC1) | 1 MSPS |
| SAM C2x | SAMC21G18A, SAMC20G18A | 10-bit | 2 (DAC0, DAC1) | 350 kSPS |
Output Modes: The DACC supports both single-ended outputs (DAC0 and DAC1 independent) and differential output mode (DAC0 - DAC1), providing flexibility for various signal generation requirements.
Configuration: Independent DAC channels
Configuration: Differential voltage output
Configuration: Automatic waveform synthesis
| Parameter | Options/Values | Description |
|---|---|---|
| DIFF | • Single-Ended Outputs | • Differential Outputs |
| DAC0_OUTPUT_PIN | • Not used | • DAC0 / Port / Pin[xx] |
| DAC0_INITIAL_OUTPUT | Numeric value (0-4095 for 12-bit) | Initial DAC0 output value at startup. For 12-bit DAC: V_OUT = (value/4095) × VREF. For 10-bit DAC: V_OUT = (value/1023) × VREF. Ensures defined output state before first update from block input. |
| DAC0_INPUT | • on (Enable input port) | • off (Fixed output) |
| DAC0_INPUT_SAT | • on (Enable saturation) | • off (No saturation) |
| DAC1_OUTPUT_PIN | • Not used | • DAC1 / Port / Pin[xx] |
| DAC1_INITIAL_OUTPUT | Numeric value (0-4095 for 12-bit) | Initial DAC1 output value (single-ended mode). Sets starting voltage on DAC1 pin. |
| DAC1_INPUT | • on | • off |
| DAC1_INPUT_SAT | • on | • off |
| DAC0_FORCED_OUTPUT_PIN | Display only (differential mode) | Shows DAC0 pin assignment in differential mode. Pin is forced active and cannot be disabled when differential mode selected. |
| DAC1_FORCED_OUTPUT_PIN | Display only (differential mode) | Shows DAC1 pin assignment in differential mode. Both pins required for differential output. |
| DACC_DIFF_INITIAL_OUTPUT | Numeric value (differential mode) | Initial differential output value. Represents signed differential voltage. V_DIFF = (value/4095) × VREF - VREF/2 (for bipolar centered output). |
| DAC_INPUT_DIFF | • on | • off |
| DAC_INPUT_DIFF_SAT | • on | • off |
The block supports 2 input datatype representations:
| Input Type | Range | Description |
|---|---|---|
| Float | 0.0 to 1.0 (single-ended) or -1.0 to 1.0 (differential) | Normalized voltage, block scales internally |
| Integer | 0 to 4095 (12-bit) or 0 to 1023 (10-bit) | Raw DAC counts, direct register write |
⚠️ Important: The block performs no range checking on inputs. Users must clamp values before the block input (e.g., using a Saturation block) to prevent overflow, regardless of datatype.
Normalized control—the block handles scaling internally. Use range [0, 1] for single-ended mode or [-1, 1] for differential mode.
Hardware Considerations: SAM devices (Cortex-M4F) have single-precision FPU—float inputs are processed efficiently.
Values written directly to DAC registers—no runtime computation. Valid range: 0–4095 (12-bit: E5x/E7x) or 0–1023 (10-bit: C2x). Users handle scaling:
Scaling formula: DAC_count = (Voltage / VREF) × Max_Count
// DAC Control Register DACC_CR = (SWRST « 0); // Software reset (write 1 to reset) // DAC Mode Register (DACC_MR) DACC_MR = (DIFF « 23) | // Differential mode (0=single, 1=diff) (PRESCALER « 8) | // Prescaler for DAC clock (STARTUP « 24) | // Startup time selection (MAXS « 0) | // Max speed mode (WORD « 4) | // Transfer mode (0=half-word, 1=word) (REFRESH « 8); // Refresh period for output
// Enable DAC channels independently DACC_CHER = (1 « 0) | // Enable DAC0 (1 « 1); // Enable DAC1 // Set initial output values DACC_CDR0 = 2048; // DAC0 initial (mid-scale for 12-bit) DACC_CDR1 = 2048; // DAC1 initial (mid-scale) // Runtime updates DACC_CDR0 = new_value_dac0; // Update DAC0 output DACC_CDR1 = new_value_dac1; // Update DAC1 output // Voltage calculation: // V_DAC0 = (DACC_CDR0 / 4095) × VREF (for 12-bit) // V_DAC1 = (DACC_CDR1 / 4095) × VREF
// Enable differential mode DACC_MRbits.DIFF = 1; // Enable both DAC channels (required for differential) DACC_CHER = 0x03; // Enable DAC0 and DAC1 // Set differential output // For centered bipolar output (±VREF/2): int16_t diff_value = 0; // 0 = center (0V differential) // Convert signed value to DAC codes: uint16_t dac0_code = 2048 + (diff_value / 2); // Positive side uint16_t dac1_code = 2048 - (diff_value / 2); // Negative side DACC_CDR0 = dac0_code; DACC_CDR1 = dac1_code; // Differential voltage: // V_DIFF = V_DAC0 - V_DAC1 // = [(dac0_code - dac1_code) / 4095] × VREF // = (diff_value / 4095) × VREF
Application: Precision 1.65V reference for ADC bias // Configuration: // - DIFF = “Single-Ended Outputs” // - DAC0_OUTPUT_PIN = “DAC0 / PB13 / Pin[57]” (enabled) // - DAC0_INITIAL_OUTPUT = 2048 (mid-scale for 12-bit) // - DAC0_INPUT = “off” (static reference) // - DAC1_OUTPUT_PIN = “Not used” // - VREF = 3.3V (internal or external) // Initial configuration: DACC_MRbits.DIFF = 0; // Single-ended mode DACC_CHER = 0x01; // Enable DAC0 only DACC_CDR0 = 2048; // 2048/4095 × 3.3V = 1.65V // Result: // DAC0 pin outputs stable 1.65V for ADC single-ended biasing // No code execution needed after initialization // Low drift, low noise reference voltage
Application: Balanced command voltage for motor driver // Configuration: // - DIFF = “Differential Outputs” // - DAC0_FORCED_OUTPUT_PIN = “DAC0 / PB13 / Pin[57]” // - DAC1_FORCED_OUTPUT_PIN = “DAC1 / PD0 / Pin[89]” // - DACC_DIFF_INITIAL_OUTPUT = 0 (0V differential) // - DAC_INPUT_DIFF = “on” (runtime control) // - DAC_INPUT_DIFF_SAT = “on” (prevent overflow) // Motor speed command: -100% to +100% // Convert to differential DAC value: float motor_command = 0.75; // 75% forward // Map -1.0 to +1.0 → -2048 to +2048 (12-bit centered) int16_t diff_value = (int16_t)(motor_command * 2048.0); // Block input receives diff_value // Block automatically converts to DAC0/DAC1 codes: uint16_t dac0 = 2048 + diff_value/2; // High side uint16_t dac1 = 2048 - diff_value/2; // Low side // Differential output: // V_DIFF = (diff_value / 2048) × (VREF/2) // For 75% command: V_DIFF = 0.75 × 1.65V = 1.24V // Motor driver receives balanced differential command // Noise on both lines cancels in differential input
| Specification | 10-bit DAC | 12-bit DAC | Impact |
|---|---|---|---|
| Step Size | VREF / 1024 | (~3.2mV @ 3.3V) | VREF / 4096 |
| INL | ±2 LSB typical | ±2 LSB typical | Linearity error (±6.4mV or ±1.6mV) |
| DNL | ±1 LSB typical | ±1 LSB typical | Step uniformity (monotonic guaranteed) |
| Settling Time | 1-3 μs | 1-3 μs | Time to reach final value |
Reference Selection:
// Maximum update rates (device-dependent): // SAM E5x/E7x: Up to 1 MSPS (1 μs per update) // SAM C2x: Up to 350 kSPS (2.86 μs per update) // Update rate limited by: // 1. DAC settling time (~1-3 μs) // 2. CPU/DMA transfer speed // 3. Application sample rate requirements // For high-speed waveforms (>100 kHz): // - Use DMA for CPU-free updates // - Pre-calculate waveform samples // - Minimize ISR overhead // - Consider external DAC for >1 MSPS
| Issue | Possible Causes | Solution |
|---|---|---|
| No output voltage | • DAC not enabled | • Pin not configured |
| Incorrect output voltage | • Wrong VREF | • Incorrect DAC value |
| Noisy output | • No output filter | • Poor PCB layout |
| Slow settling | • Large capacitive load | • Insufficient output current |
| Differential mode issues | • One channel disabled | • Incorrect DAC codes |
| Distorted waveform | • Update rate too low | • Insufficient samples |