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...")
 
 
(2 intermediate revisions by the same user not shown)
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
  
* 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.
+
    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)
  
* For fastest write to DAC output, this is used;
+
    float output1 = ....  // a float value from -10 to +10
<nowiki>
+
    float output2 = ....  // a float value from -10 to +10
DAC->RD12BDHR = dac_value1 + (dac_value2 << 16);
+
   
</nowiki>
+
    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.
  
* Simple initialization is;
 
<nowiki>
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );
 
  
    DAC_InitTypeDef DAC_InitType={0};
+
== Development Notes ==
    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);
+
* 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.
    DAC_Cmd(DAC_Channel_2, ENABLE);
 
</nowiki>
 

Latest revision as of 10:13, 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

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.