CH32V307-DAC
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
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.
- For fastest write to DAC output, this is used;
DAC->RD12BDHR = dac_value1 + (dac_value2 << 16);
- Simple initialization is;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); DAC_InitTypeDef DAC_InitType={0}; DAC_InitType.DAC_Trigger=DAC_Trigger_None; DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None; DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Enable; DAC_Init(DAC_Channel_1,&DAC_InitType); DAC_Init(DAC_Channel_2,&DAC_InitType); DAC_Cmd(DAC_Channel_1, ENABLE); DAC_Cmd(DAC_Channel_2, ENABLE);