Library 36- DAC Signal generator for STM32F4

For FFT project purpose, I needed simple, really simple signal generator. I don’t have separate device at home, so I made one with STM32F4.

DAC Signal library uses timer for output generation and DMA for transferring data from memory to DAC peripheral. So this library does not use processor for controlling. Everything is behind the scenes.

You can use 4 different signal waves:

  1. Square
  2. Sawtooth
  3. Triangle
  4. Sinus

They are simple, predefined signals. You can adjust signal frequency for specific wave. I tested some frequencies, and sinus worked just well at about 100kHz, but square works great to about 50kHz. Square wave has 50% duty cycle. If you need variable square wave duty cycle, then you should look at my PWM library or PWM tutorial.

This library is not a real signal generator, sinus signal is not going to negative. Signals have fake ground at the middle of DAC max value, so 2047 is fake ground, and sinus is going from 0 to 4095. If you want “negative” effect, then you should add a capacitor in series to the output, this will allow only AC component to go through. Capacitor varies between your signal frequency, but about 680nF should be just OK.



  • Supports 4 different simple predefined waves
  • Selectable signal frequency
  • Supports 2 DAC channels
  • Timer driven DMA
    • TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8 can be used


    • STM32F4xx
    • STM32F4xx RCC
    • STM32F4xx GPIO
    • STM32F4xx DAC
    • STM32F4xx TIM
    • STM32F4xx DMA
  • TM
    • TM GPIO
    • defines.h

Pinout is simple. You only need pins for DAC outputs.

DACx STM32F4 Description
DAC1 PA4 DAC Channel 1
DAC2 PA5 DAC Channel 2

STM32F401 series does not have DAC output, so you can’t use this library there. But others should have it. Pins are fixed, analog, can not be changed.

Functions and enumerations


Example below produces:

  • Triangle wave on DAC Channel 1, pin PA4, with signal frequency 5 kHz
  • Square wave on DAC Channel 2, pin PA5, with signal frequency 10kHz
  • Oscilloscope result with cursor measurements
Triangle wave 5kHz

Triangle wave 5kHz

Square wave 10kHz

Square wave 10kHz

Project is available on Github, download library below.

TM STM32F4 DAC Signal Library


Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Victor

    I am testing exactly this same example on Keil uVision 5.14 using Tilen Majerle’s template (the one …CMSIS_USB_…).
    I found an error on lines 76 and 78 of tm_stm32f4_dac_signal.c, there are two pins typed in uppercase (GPIO_PIN_4 and GPIO_PIN_5), so, the compiler was rising an error, I had success on compiling with the changes seen in the second picture I’ve attached.

    I am running an example using peripherals such RTC, USART1 and USART6 and I couldn’t achieve the same results shown in your post. I don’t have a signal on TM_DAC2 output using TIM5 (As seen in the first picture I’ve attached on this post). After changing the timer interface I got it run (TIM6). Could you explain why this is happening? I’ve read some stuff but I haven’t found a solution.


    • Using my GPIO library, those 2 pins are just fine if they are uppercase!
      Huh, from my head, I have no idea right now.

      Should test this first.

      • Victor Santos

        Hi buddy, I solved the problem, don’t worry.
        I just updated my cloned repository with you libraries and it worked like a charm!


  • Bublo

    Hi Tilen, how to correctly stop generation of signal? I just stop the timer, but I am not shure, that it is correct way. Im missing function for stopping signal generation, and also function for change only the frequency would be great (without all those initializations of DMA.)


    • Just disable DMA and TIM and you are done.

      For changing frequency, you have to select new prescaler and period for timer.
      Basically, I can add these methods too.

      • Bublo

        Ok, I made it just like that. Thanks

      • Bart

        I’ve been trying to make a program that changes the frequency but i realy cant make it work. Please add the method to change the fequency.

  • Simão Ferreira

    I used your codes to generate sine and square and to the output of the DAC the signs come out perfect, but after I connect the signals to a AmpOp LM358 (24V/ 0V) to amplify the signals up to 24V, but after the amplify, from 5kHz/ 10kHz signal becomes a triangle.
    You know how to help me in this case?

  • Shawn

    In my project I need to vary the amplitude of the sine-wave…somehow. I know there is a way to do this by modifying the 32 numbers and include a variable but I am finding it a bit hard to do it. Can you help me? Thanks


    • .c file of DAC SIGNAL library: uint16_t DAC_SIGNAL_Sinus[DAC_SIGNAL_SINUS_LENGTH]

      If you don’t want to modify library directly, add this:

      extern uint16_t DAC_SIGNAL_Sinus[DAC_SIGNAL_SINUS_LENGTH]; in your main as global variable and do operations like normal.

  • linkinrcs


    Thank you for all your work which is very helpful for my project.
    I want to synthesize a triangle wave with my STM32F429. But, the minimum frequency needed is 250kHz (I have to flutter a PLL and I want to add this signal at the input of the VCO).
    I seams that this frequency is too high for the STM32’s DAC.
    I thought to generate a square signal (with a timer) and add a small circuit to integrate the signal. But do you have another idea ?
    Thanks in advance.

  • Mia

    hi TM,
    I use the above program to generate the triangle signal of 1000Hz, but the amplitude is about 1,6v, can i get the signal a little lager like 2,5v? how should i change ?

    • Hi, tell me please, how you measure voltage? Using voltmeter or oscilloscope? I’m sure you use voltmeter which averages voltages in time.

      Use oscilloscope for testing if you did not already.

      • Mia

        oh, yes, i used the voltmeter, i think i should try again with the oscilloscope!!! Thank you very much for your reply.

      • Mia

        Hi TM,

        may i change the output voltage from 0-3.3V to 0.5-3.3V?


  • kuds

    Hi, since your libraries are some of the best sources for trustworthy working and well documented STM source code, I’m often looking up basic structures and approaches to different applications, mostly covered by one of your libraries. So my question is more about how the your library works under the hood than it’s pure application.
    My application is something like the signal generator covered by this library but with an EXTERNAL DAC instead of the internal ones your library uses; board is STM32F4.
    I searched your tm_stm32f4_dac_signal.c file for the point, where you connect the timer that is configured to generate a TRGO trigger in a defined frequency with the DAC. I found out, the internal DAC init structure already provides a possibility to connect the internal DAC to a timer. This is not possible for external DACs I am addressing with SPI+DMA. Can I somehow connect a timer with a single DMA request (not a full transfer!)? So that I just load my waveform into the DMA SPI TX buffer once an then the data are sent to the external DAC just automatically whenever the timer triggers? I don’t have any clue where to look this up in the reference manual. Sorry for being a bit offtopic :-/ and thank’s a million for your help 🙂

    • This is not posible. But you can slow down spi frequency if possible to a value for your samplong and then each sample will have send time the same as time base for triggering dma.

      • kuds

        Thanks for your answer 🙂