DAC upper reference voltage set to 200 mV when using DMA?

Hey Guys,
So I just finished up a program that pushes a sine wave to the DAC on the photon using DMA. However, I have a strange issue. It would appear that the max voltage (4095) corresponds to ~180 mV when output by the DAC with DMA vs. 4095 corresponding to 3.3 V with standard analog writes. I measured the waveform with a scope and I can ensure that it is being is generated properly (with the correct number of divisions and frequency), except for the shift in the upper reference voltage. (Albeit there is some clipping due to the 50 mV lower limit on output writes, but this is an easy fix). I was wondering if I did something strange in my code, or if there is an option to set a external or internal reference for the DAC that I didn’t see.

void dacDMAConfig (uint16_t bufferSize, uint16_t *buffer) {
    Serial.printlnf("Configuring DAC DMA");

    //Enable dma clk.
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

    /* DMA1 Stream5 channel7 configuration */

    DMA_InitTypeDef DMA_InitStructure;

    DMA_InitStructure.DMA_BufferSize = bufferSize;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &_DAC->DHR12L1;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_Channel = DMA_Channel_7; // Stream5 Channel7 = DAC1

    DMA_Init(DMA1_Stream5, &DMA_InitStructure);

    /* Enable DMA1 Stream5 */
    DMA_Cmd(DMA1_Stream5, ENABLE);

void dacConfig (uint16_t bufferSize, uint16_t *buffer) {
    Serial.printlnf("Configuring DAC");
    dacDMAConfig(bufferSize, buffer);

    // DAC clk enable.
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    /* DAC channel1 Configuration */

    DAC_InitTypeDef DAC_InitStructure;
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T5_TRGO;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

    DAC_Init(DAC_Channel_1, &DAC_InitStructure);

void dacStart () {

    /* Enable DAC Channel1 */
    DAC_Cmd(DAC_Channel_1, ENABLE);

    /* Enable DMA for DAC Channel1 */
    DAC_DMACmd(DAC_Channel_1, ENABLE);

    Serial.printlnf("Starting DAC");

Anyway, this one has me stumped, so any help would be appreciated.


I have not seen this behaviour when I tested it.
What kind of load have you got on your DAC?
Of what frequency is your signal?
Can you try DAC1 (A3) or a different Photon to rule out a damaged DAC?

I am just using a standard scope input with 1 M input impedance.

I have tested it for 100 samples/sec all the way up to 100k samples per second. The results are the same.

I unfortunately do not have a second photon on hand. But I will try the other DAC.

Also make sure you haven’t got the x10 attenuation set on your probe :wink:

@ScruffR Made that mistake enough times. :rofl: It was the first thing I checked… I have absolutely no idea why is is happening. It is the same result on the other DAC. Vref+ cannot be lower than 1.8V so that suggests that there is some kind of scaling unit being enabled. Unfortunately, I cannot seem to find any mention of such a unit in the reference manual. I checked to see if the internal reference for the ADC was being enabled, but no luck there either. It works 100% as expected when using analogWrite(), so I am not sure what could possibly be causing this drastic change in the output voltage.

Figured it out!

Ends up that the DAC accepts 16 bit values. I was passing 12 bit values up to 4096. I am not sure where the 12 bit or 16 bit modes come into play, but the added precision resulted in the wave being much smaller than expected.


Doh’ I had already intended to post this link to refere you to the speaker library (where this is mentioned) but then realised you already found that lib, so I didn’t.
Should have done it anyway to save you the time