STM32 DAC Peripheral Comparison: F1 vs F4 Series and Advanced Usage Patterns

STM32 microcontrollers integrate a versatile Digital-to-Analog Converter (DAC) block whose capabilities evolve significantly across product lines. This article contrasts the DAC implementations found in the STM32F1 and STM32F4 families, then walks through practical firmware techniques that exploit the peripheral’s advanced modes.

STM32F1 DAC: Entry-Level 12-Bit Output

The F1 series offers a straightforward 12-bit DAC with up to two independent channels. Key traits include:

  • 4096 discrete output levels (12-bit resolution).
  • Dual-channel support for simultaneous enalog generation.
  • Flexible trigger matrix: TIMx, EXTI, or software.
  • Built-in noise and triangle-wave generators for basic waveform synthesis.
  • Double-buffered data register to prevent glitches during updates.
  • Low-power retention while the core sleeps.

F1 Quick-Start Firmware

/* Minimal F1 setup using HAL */
DAC_HandleTypeDef hDac1;
DAC_ChannelConfTypeDef cfg = {0};

__HAL_RCC_DAC_CLK_ENABLE();                 /* Turn on the DAC clock */
__HAL_RCC_GPIOA_CLK_ENABLE();               /* PA4/PA5 often carry DAC_OUT1/2 */

/* Configure PA4 as analog */
GPIO_InitTypeDef gpio = { .Pin = GPIO_PIN_4, .Mode = GPIO_MODE_ANALOG };
HAL_GPIO_Init(GPIOA, &gpio);

hDac1.Instance = DAC;
HAL_DAC_Init(&hDac1);

cfg.DAC_Trigger        = DAC_TRIGGER_NONE;  /* Immediate update */
cfg.DAC_OutputBuffer   = DAC_OUTPUTBUFFER_ENABLE;
HAL_DAC_ConfigChannel(&hDac1, &cfg, DAC_CHANNEL_1);

HAL_DAC_SetValue(&hDac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);
HAL_DAC_Start(&hDac1, DAC_CHANNEL_1);      /* Mid-scale output = VREF/2 */

STM32F4 DAC: Higher Performence and Richer Feature Set

The F4 line extends the DAC with:

  • Up to three 12-bit channels (some variants expose 16-bit via oversampling).
  • Faster settling time and lower THD+N.
  • Sample-and-hold stage for each channel, allowing output freeze during MCU sleep.
  • Factory or user trimming registers for offset/gain correction.
  • Dedicated DMA streams for continuous waveform streaming.
  • Interleaved and dual synchronous modes for advanced signal generation.

F4 Initialization Snippet

/* F4 example with DMA-ready configuration */
DAC_HandleTypeDef hDac2;
DAC_ChannelConfTypeDef cfg = {0};

__HAL_RCC_DAC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/* PA4 = DAC_OUT1, PA5 = DAC_OUT2 */
GPIO_InitTypeDef gpio = { .Pin = GPIO_PIN_4 | GPIO_PIN_5, .Mode = GPIO_MODE_ANALOG };
HAL_GPIO_Init(GPIOA, &gpio);

hDac2.Instance = DAC;
HAL_DAC_Init(&hDac2);

cfg.DAC_Trigger               = DAC_TRIGGER_T6_TRGO;  /* TIM6 triggers DMA */
cfg.DAC_OutputBuffer          = DAC_OUTPUTBUFFER_ENABLE;
cfg.DAC_SampleAndHold         = DAC_SAMPLEANDHOLD_DISABLE;
cfg.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
cfg.DAC_UserTrimming          = DAC_TRIMMING_FACTORY;
HAL_DAC_ConfigChannel(&hDac2, &cfg, DAC_CHANNEL_1);

Advanced Operating Modes

Dual Simultaneous Output

Enable DAC_CR_EN1 | DAC_CR_EN2 and load identical data into both channels. Useful for stereo audio or differential drive.

Interleaved Mode

Alternate samples between CH1 and CH2 to double the effective sample rate. Requires precise timer pacing and DMA double-buffering.

Waveform Generators

  • Noise: Programmable 12-bit LFSR produces pseudo-random patterns.
  • Triangle: Configurable amplitude and frequency, ideal for ADC testing.

Calibration Workflow

  1. Force DAC output to mid-scale (0x800).
  2. Measure actual voltage with a high-resolution meter.
  3. Compute offset and gain error.
  4. Write trim values to DAC_CCR and DAC_MCR.

Streaming Data via DMA

Continuous playback from a circular buffer:

uint16_t sineBuffer[64] = { /* pre-computed 12-bit sine */ };

HAL_DAC_Start_DMA(&hDac2, DAC_CHANNEL_1,
                  (uint32_t *)sineBuffer, 64,
                  DAC_ALIGN_12B_R);

/* TIM6 triggers DMA at desired sample rate */
TIM_MasterConfigTypeDef timCfg = {
    .MasterOutputTrigger = TIM_TRGO_UPDATE,
    .MasterSlaveMode     = TIM_MASTERSLAVEMODE_DISABLE
};
HAL_TIMEx_MasterConfigSynchronization(&htim6, &timCfg);
HAL_TIM_Base_Start(&htim6);

Practical Tips

  • Always enable the DAC output buffer unless driving a high-impedance load; disabling it reduces offset error but increases settling time.
  • Route analog pins away from fast-switching digital signals to minimize crosstalk.
  • Use the MCU’s internal reference when absolute accuracy matters; VDDA noise can couple into the DAC.
  • Check DAC_SR flags in interrupt context to detect underrun or DMA errors.

Tags: STM32 DAC STM32F1 STM32F4 HAL

Posted on Sat, 17 Oct 2026 16:14:18 +0000 by curt3006