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.

Frequency of Sinewave using DMA controller

Other Parts Discussed in Thread: MSP430FG4618

Hi All,

I am new to MSP430, and need some of your help in possibly a very simple problem.

I am trying to generate a sine wave using MSP430FG4618 experimenter's board.  The MCU has a 8 MHz CPU, the MCLK= SMCLK=1MHz, and ACLK=32 kHZ.

I used the example program in the MSP430FG461X, to generate sine/cosine wave with 32 steps using DMA controller and DAC12.  I successfully got the sine wave, but what I don't understand is how the frequency of the wave is determined.  I tried to change/measure the frequency by changing the Clock periods of TACCR0, because thats what I thought was the way to change the frequency.   The frequency of the sine wave I got was:

Clock Period of TACCR0 Frequency

2 4.096 kHz

20 1.645 kHz

100 328.9 Hz

I can't figure out whats determining the frequency, there doesn't seem to be a linear relationship. I would really appreciate any help in this matter

 

The program is:

//////////////////////////////////////////////////////

 

#include "msp430xG46x.h"

//------------------------------------------------------------------------------

// 12-bit Sine Lookup table with 32 steps

//------------------------------------------------------------------------------

// 12-bit Cosine Lookup table with 32 steps

void main(void)

{

  volatile unsigned int i;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

  FLL_CTL0 |= XCAP14PF;                     // Configure load caps

  ADC12CTL0 = REF2_5V + REFON;              // Internal 2.5V ref

  TACCR0 = 13600;                           // Delay to allow Ref to settle

  TACCTL0 |= CCIE;                          // Compare-mode interrupt.

  TACTL = TACLR + MC_1 + TASSEL_2;          // Up mode, SMCLK

  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts

  TACCTL0 &= ~CCIE;                         // Disable timer interrupt

  __disable_interrupt();                    // Disable Interrupts

  DMACTL0 = DMA0TSEL_5 + DMA1TSEL_5;        // DAC12IFG triggers

  DMA0SA = (int)Sin_tab;                    // Source block address

  DMA0DA = DAC12_0DAT_;                     // Destination single address

  DMA0SZ = 0x020;                           // Block size

  DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word

  DMA1SA = (int)Cos_tab;                    // Source block address

  DMA1DA = DAC12_1DAT_;                     // Destination single address

  DMA1SZ = 0x020;                           // Block size

  DMA1CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word

  DAC12_0CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC + DAC12GRP;

  DAC12_1CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC;

  TACCTL1 = OUTMOD_3;                       // TACCR1 set/reset

  TACCR1 = 1;                              // TACCR1 PWM Duty Cycle

  TACCR0 = 100-1;                           // Clock period of TACCR0

  TACTL = TASSEL_2 + MC_1;                  // SMCLK, contmode

  while(1)

  {

    __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0

  }

}

 

#pragma vector = TIMERA0_VECTOR

__interrupt void TA0_ISR(void)

{

  TACTL = 0;                                // Clear Timer_A control registers

  __bic_SR_register_on_exit(LPM0_bits);     // Exit LPMx, interrupts enabled

}

 

 

 

/////////////////////////////////////

 

  • It's a rather weird setup.

    The DMA occurs as soon as the DAC0 reports that it is ready for accepting the next value.
    However, the DAC is instructed to wait with loading the last value to output until rising edge of Timer_A.OUT1.

    This output is set when TAR counts to TACCR1 (==1)and is reset when TAR counts to TACCR0.

    The formula for the trigger frequency would be FTR =FCLK/((CCR0+1)*steps).

    For FCLK=1.05MHz (a typical default SMCLK/MCLK value), FTR based on CCR0+1 is
    100: 328Hz
    20: 1640Hz
    2: 16408Hz

    For CCR0=20/100, the values are okay. (the difference is caused by default frequency variations - I actually picked 1.05Mhz because it fits :) teh range is 1.0 to 1.2MHz)

    The anomaly is for CCR0==2. There is a limiting factor in transfer speed, depending on MCLK. The minimum DMA cycle time is 4 MCLK cycles and there are two transfers, so 8 MCLK cycles are the minimum.
    For MCLK = 1.05MHz, the maximum is 1.05MHz/8 transfers. This is 131250 transfers. With 32 transfer per wave, you get a maximum of 4101Hz. It will stay constant for all CCR0 values from 2 (on 1 you'll probably stall the system) to 8.

  • Thank You Jens,

    I think I got your point. This makes all sense now.

    I was overlooking the 4 cycles per instruction stuff.

  • hey guyz , i need help, can some 1 help me plzzz

  • my problem also involves generating a sine wave , can sme1 help me out 

  • You need precalculated sine table and chip with DAC and DMA. Look for DMA+DAC sample in source code examples. Something like this:

    #include <msp430.h>
    
    //-------------------------------------------------------------------------------
    // 12-bit Sine Lookup table with 32 steps
    //-------------------------------------------------------------------------------
    
    const int Sin_tab[32] = { 2048, 2447, 2831, 3185, 3495, 3750, 3939, 4056,
                              4095, 4056, 3939, 3750, 3495, 3185, 2831, 2447,
                              2048, 1648, 1264,  910,  600,  345,  156,   39,
                                 0,   39,  156,  345,  600,  910, 1264, 1648
                            };
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
      ADC12CTL0 = REFON;                        // Internal reference
      __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) Sin_tab);
                                                // Source block address
      __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &DAC12_0DAT);
                                                // Destination single address
      DMA0SZ = 0x020;                           // Block size
      DMACTL0 = DMA0TSEL_5;                     // DAC12IFG trigger
      DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word
      DAC12_0CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC;
      TACCTL1 = OUTMOD_3;                       // TACCR1 set/reset
      TACCR1 = 01;                              // TACCR1 PWM Duty Cycle
      TACCR0 = 032-1;                           // Clock period of TACCR0
      TACTL = TASSEL_2 + MC_1;                  // SMCLK, contmode
      __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0
    }
    
    
    

  • shashvat bhola said:
    hey guyz , i need help, can some 1 help me plzzz

    "help"

    Was this sufficient? Or do you need ore help?

    "help, help, help" - this should do.

    if you don't write what your problem is (I guess you need help because you have a problem?) then nobody can help you.

    If you say
    "I have a problem but I won't tell you what it is",
    I can only say
    "I have lots of solutions and likely the one you need, but I don't know which one will fit your problem, so I won't give you any"

**Attention** This is a public forum