This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F28377S: TMS320F28377S

Part Number: TMS320F28377S
Other Parts Discussed in Thread: CONTROLSUITE

Tool/software: Code Composer Studio

Hi

How buffered DAC clock is configured? The DAC diagram on page 1343 of TRM shows SYSCLK as input clock for DAC. On the clock tree on page 99 SYSCLK is derived from CPU without any division or multination. So it looks like DAC clock is SYSCLK that I presume for F28377S LaunchPad is 200 MHz. and cannot be changed. On the other hand DAC clock should allow for 2 us settling time for DAC and cannot be so fast. What is the right clock for buffered DAC?

Thanks vadim

  • I maybe mistaken about 200 MHz SYSCLK because when I connect SYSCLK to GPIO73 I measure only 25 MHz.
    thanks vadim
  • It is indead 200 MHz. The XCLKOUT connected to GPIO73 is devided by 8 at the reset. When XCLKOUTDIVSEL is set to 1 it shows 200 MHz
    thanks vadim
  • Hi Vadim,

    Please look at the response to this post https://e2e.ti.com/support/microcontrollers/c2000/f/171/p/587244/2157011#2157011.

    In addition, the buffered DAC requires >= 2us settling time between writes to the DACVALS register for proper operation. Basically, what this means is if you write a value to the buffered DAC, the output voltage is only guaranteed to be good 2us later.  

  • Thanks Frank,
    I am the customer who is looking for answers and put that diagram. To me DAC will not work with 200 MHz SYSCLK if settling time is 2 us. I have to divide it for the DAC. The DAC manual states “Ability to synchronize with PWMSYNC”. I searched for PWMSYNC signal in ePWM block but could not find it, the closest match is EPWMxSYNCO. What signal from ePWM module should I use? I am trying to output sine wave from DAC. I have a look up table. Each element of the LUT seems to be written in DACVALS with SYSCLK timing of 200 MHz. I need it to be udated with the sampling frequency say 200 kHz. I presume I can program ePWM to provide PWMSYNC 200k signal to load DACVALS to DACVALA but I as well need to make sure that the LUT element is not changed many times in DACVALS because SYSCLK is much faster. Could you please advice?
    Thanks vadim
  • Vadim,

    The 2us settling time in the DS is for full scale settling time with the DAC transitioning from 0.3v to 3.0v. Settling time for smaller steps will be much shorter than 2us but we don't characterize smaller transition settling times so I can't give you a number. The 2us settling time will be the absolute worst case for all transitions.

    To generate a sine with the DAC, the easiest solution will be to setup a timer interrupt and within that timer interrupt, you update the DACVALS register. This takes the least amount of hardware resources (timer) but is however cpu intensive because of the need to service the interrupt so the maximum output frequency you can obtain from the DAC will be lower. So the way this works is, let's assume you've already created your 360 array sine table and setup the timer to interrupt every 1us. It will take 360us to sweep through one period of the sine table effectively giving you a sine wave of 1/360us = 2.7KHz. We have a controlSUITE example buffdac_sine that uses this approach. You should take a look at that.

    The other way to generate a sine with the DAC is to have the DMA update the DAC. The CPU will not be involved in this. You will need the DMA and an interrupt source for this. The way this will work is, you create your sine table, for instance 360 array sine table. You map the DMA source and destination pointers to the sine table and DACVAL respectively and configure the DMA source pointer to wrap around when it reaches the end of the sine table. You setup an interrupt source for the DMA and whenever the interrupt happens, the DMA transfers the next word in the sine table to DACVAL and wraps around when it reaches the end of the array. To increase the output frequency of the sine with this approach, you can either increase the step size of the DMA source pointer, increase the interrupt frequency or reduce the length of the sine table.

  • Thanks Frank for your help! I tried CPUTIMER0 to update DACVALS. I have been looking at the buff_DAC example for quite some time. I need quite high frequency of 100-200 kHz but was not able to get it from that example that uses sgen library and generally with CPUTIMER approach. A couple things I found. The amplitude of the sine is 300 mV regardless of external 3.3V or internal reference. Why is it not close to 0-3.3 when I set gain of 1 in sgen? The mathematics described in the sgen librarary does not work.
    “The standard THD sine generators are implemented using direct table look-up technique and
    it uses 16-bit modulo counter. Although a 16-bit counter is used, the upper byte (8-bits) is
    used to index the 256-point look-up table and hence to obtain the SIN value. Thus, by
    changing how quickly values overflow from lower byte (i.e., manipulating step value) the
    frequency of the sine wave can be changed. Modulo counter ignores the overflow or carry out
    of 16-bit counter and retains only the remainder”
    F = step/2^16*Tisr
    I measured ISR it is .25us
    step = Fmax* 2^16/timer clock
    I set Fmax 40000
    Timer 800000
    Freq 40000
    I measured only 20 kHz. If I increase Fmax and Freq to 60 kHz the measured frequency became lower.
    Thanks vadim
  • Hey Vadim,

    It looks like the DAC isn't getting a reference voltage so you can't rely on any frequency measurements from it's output. The buffdac_sine example uses VDAC by default as the DAC reference. You can either supply the reference voltage through ADC channel B0 or just as easily change the DAC reference in the code from 'REFERENCE_VDAC' to 'REFERENCE_VREF'. To verify that the DAC is working correctly, you can run the buffdac_enable example and by default, you should see an output voltage of 1.65v with a 3.3v reference.

    As I highlighted before, the buffdac_sine example has a lot of overhead and isn't necessarily written for speed but instead to demonstrate one of the ways you can generate a signal with the DAC. It's been a while since I run that example but if memory serves me correctly, you should be able to attain 200 KHz. You would need to set the sampling frequency to be greater than twice the output frequency. This will probably almost consume all the CPU bandwidth.

    If high frequency is your objective, after you get this working, I think you should consider going the DMA route. Let me know if switching the reference gives you a good voltage.

  • Hi Frank,
    I think I was wrong expecting Vmax to be close to VDAC ref of 3.3V. Page 1343 says Vdac=DACVALA*DACREF/4096. DACVALA can be only half or less of 4096. So the max is 3.3V/2 and I am getting this value. I still cannot figure out the frequency. I followed your advice and set up a buffer with 360 steps.
    When the clock is set to 50k the sine frequency is 70 Hz It should be 50000/360 =138 twice lower. The interrupt routine takes .26us, should not affect much at this sampling rate; 500k 700Hz; 1MHz 1.4 kHz; 1.5 MHz 2.1 MHz;2 MHz 2.38; 5MHz 2.38kHz; 50MHz 2.38kHz. It looks like the interrupt routine that lasts 50 cycles limit the max frequency. Here is my code. What do I miss in evaluating the frequency?
    Thanks vadim
    //###########################################################################

    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "sgen.h" // Signal Generation Headerfile
    #include "math.h"

    //
    // Defines
    //

    #define REFERENCE 1
    #define CPUFREQ_MHZ 200
    #define DAC_NUM 1

    //
    // Globals
    //
    Uint32 samplingFreq_hz = 5000;
    Uint32 MAX = 2048;
    Uint32 length = 359;
    Uint16 buff[360];
    Uint16 sgen_out = 0;
    Uint16 ndx = 0;
    float cpuPeriod_us = 0;
    Uint32 interruptCycles = 0;
    float interruptDuration_us = 0;
    float samplingPeriod_us = 0;
    void configureDAC(Uint16 dac_num);

    interrupt void cpu_timer0_isr(void);

    //
    // Main
    //
    void main(void)
    {
    //
    // Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xS_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Disable CPU interrupts
    //
    DINT;

    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags are cleared.
    // This function is found in the F2837xS_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Clear all interrupts and initialize PIE vector table:
    //
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();

    //
    // Map Cpu Timer0 interrupt function to the PIE vector table
    //
    EALLOW;
    PieVectTable.TIMER0_INT = &cpu_timer0_isr;
    EDIS;

    //
    // Initialize variables
    //
    cpuPeriod_us = (1.0/CPUFREQ_MHZ);
    samplingPeriod_us = (1000000.0/samplingFreq_hz);


    //
    // Configure DAC
    //
    configureDAC(DAC_NUM);


    //Calculate buffer
    for(ndx=0; ndx<length+1; ndx++)
    {
    buff[ndx]=(round(MAX+(MAX-1)*sin(6.28*ndx/length)));
    }
    ndx = 0;

    // Initialize Cpu Timers
    //
    InitCpuTimers();

    //
    // Configure Cpu Timer0 to interrupt at specified sampling frequency
    //
    ConfigCpuTimer(&CpuTimer0, CPUFREQ_MHZ, samplingPeriod_us);

    //
    // Start Cpu Timer0
    //
    CpuTimer0Regs.TCR.all = 0x4000;

    //
    // Enable interrupt
    //
    IER |= M_INT1;
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    EINT;
    ERTM;


    while(1)
    {

    }
    }



    //
    // configureDAC - Enable and configure the requested DAC module
    //
    void configureDAC(Uint16 dac_num)
    {
    EALLOW;

    DacaRegs.DACCTL.bit.DACREFSEL = REFERENCE;
    DacaRegs.DACOUTEN.bit.DACOUTEN = 1;
    DacaRegs.DACVALS.all = 0;

    DELAY_US(10); // Delay for buffered DAC to power up

    EDIS;
    }


    //
    // cpu_timer0_isr - Timer ISR that writes the sine value to DAC
    //
    interrupt void cpu_timer0_isr(void)
    {
    //
    // Start Cpu Timer1 to indicate begin of interrupt
    //
    CpuTimer1Regs.TCR.all = 0x0000;

    //
    // Write current sine value to buffered DAC
    //

    ndx++;

    sgen_out = buff[ndx];
    DacaRegs.DACVALS.all = sgen_out;
    ndx = ndx % length;
    //
    // Acknowledge this interrupt to receive more interrupts from group 1
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    //
    // Stop Cpu Timer1 to indicate end of interrupt
    //
    CpuTimer1Regs.TCR.all = 0x0010;

    //
    // Calculate interrupt duration in cycles
    //
    interruptCycles = 0xFFFFFFFFUL - CpuTimer1Regs.TIM.all;

    //
    // Calculate interrupt duration in micro seconds
    //
    interruptDuration_us = cpuPeriod_us * interruptCycles;

    //
    // Reload Cpu Timer1
    //
    CpuTimer1Regs.TCR.all = 0x0030;
    }

    //
    // End of file
    //
  • Hey Vadim,

    The DAC can output rail-to-rail voltage but due to the buffer on the output, voltages would be non-linear towards the rails. With the code that you provided (sampling frequency = 5KHz), you should see an approximately 0v to 3.3v, 13.8Hz sine wave. Are you not seeing that?

  • Hi Frank,
    No I do not see it. If I try buffered_adc_enable file I have the following for dacval
    0000 120 mV
    500 280 mV
    1000 480 mV
    1500 680 mV
    2000 920 mV
    2500 1080 mV
    3000 1280 mV
    3500 1480mV
    4000 1680mV
    Thanks vadim
  • Hey Vadim,

    That doesn't look right. For debug purposes, can you change the reference in the buffdac_enable code to "VDAC" and supply 3.3v to pin B0? Also, has the Launchpad been modified in any way?