Difference between revisions of "CH32V307-DAC"

From Stm32World Wiki
Jump to navigation Jump to search
(Created page with "Category:CH32Category:RISC-VCategory:CH32V307Category:MCU{{metadesc|CH32V307xx RISC-V MCU}} The CH32V307 is equipped with two 12-bit DACs, with quite fast set...")
 
Line 3: Line 3:
 
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.
 
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.
  
= Development Notes=
+
    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.
 
* 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.

Revision as of 10:09, 3 July 2022


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);