From Stm32World Wiki
Jump to navigation Jump to search

The CH32V307 is equipped with two 12-bit DACs, with quite fast settling times. There is an Output Buffer which is needed to drive any load with lower impedance than a few hundred kilo-ohms.

Simple Setup

We just want to write data to a register and have that go to the output.

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );      // Enable CLOCK for the DAC peripheral
   DAC_InitTypeDef DAC_InitType={0};                         // Initialization data structure
   DAC_InitType.DAC_Trigger=DAC_Trigger_None;                // No trigger --> Value written to physical output one clock after value written to register
   DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;  // DAC can generate SawTooth (they call triangle) and Noise automatically. We don't want that.
   DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Enable;    // Enable the Output Buffer as we have a 10kohm load
   DAC_Init(DAC_Channel_1,&DAC_InitType);                    // Initialize Channel 1
   DAC_Init(DAC_Channel_2,&DAC_InitType);                    // Initialize Channel 2
   DAC_Cmd(DAC_Channel_1, ENABLE);                           // Enable Channel 1
   DAC_Cmd(DAC_Channel_2, ENABLE);                           // Enable Channel 2

DMA Setup

It is possible to let the DMA feed the DAC channels and we write the data in a memory buffer asynchronously to the DMA transfer. This can drastically improve timing jitter and in some cases allow smaller inner loops to process/generate the output signal wanted. The most common technique is to generate an interrupt at "half buffer" and "end buffer", indicating the respective half of buffer is available to be written to.

   TODO:// Code here

Write to DAC

We have data in 16-bit variables, and the 12 bits are left-aligned, i.e. 0-4095 is the value to write. (NOTE: right-aligned data seemed to be much slower to write)

   float output1 = ....   // a float value from -10 to +10
   float output2 = ....   // a float value from -10 to +10
   uint16_t ch1 = (uint16_t) ((output1 - 10.0f) * 204.7f);  // ch1 is value from 0 to 4095
   uint16_t ch2 = (uint16_t) ((output2 - 10.0f) * 204.7f);  // ch2 is value from 0 to 4095
   DAC->RD12BDHR = ch1 + (ch2 << 16);  // Write both channels in one operation.

Development Notes

  • The output impedance is a concern. Without the Output Buffer enabled, >100kohm impedance for the load is needed. Even WITH Output Buffer enabled, a 1kohm load is not really possible, both high and low end of range is not reached, which is a bit strange. 10kohm hasn't been tested yet, but datasheet indicates that a 5kohm load should be fine.