Back

//******************************************************************************
//  MSP430F6x Demo - Basic Clock, Implement Auto RSEL SW FLL
//
//  Description: Set DCO clock to (Delta)*(4096) using software FLL. DCO clock
//  is output on P1.4 as SMCLK.  DCO clock, which is the selected SMCLK source
//  for timer_A is integrated over LFXT1/8 (4096) until SMCLK is equal to Delta
//  CCR2 captures ACLK.  To use Set_DCO Timer_A must be operating in continous
//  mode.  Watch crystal for ACLK is required for this example.  Delta must be
//  kept in a range that allows possible DCO speeds.  Minimum Delta must ensure
//  that Set_DCO loop can complete within capture interval. Maximum delta can be 
//  calculated by f(DCOx7) / 4096.  f(DCOx7) can be found in device specific
//  datasheet. ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
//  //* External watch crystal installed on XIN XOUT is required for ACLK *//
//
//         MSP430F261x/241x
//         ---------------
//     /|\|            XIN|-
//      | |               | 32kHz
//      --|RST        XOUT|-
//        |               |
//        |           P1.4|--> SMLCK = target DCO
//
//  B. Nisargax
//  Texas Instruments Inc.
//  September 2007
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include "msp430x26x.h"

//formula is DELTA*ACLK = frequency you want!!
//#define DELTA 2930                      // target DCO = DELTA*(4096) = 12MHz
#define DELTA 2445                        // target DCO = DELTA*(4096) = 10MHz
//#define DELTA 900                       // target DCO = DELTA*(4096) = 3686400
//#define DELTA 256                       // target DCO = DELTA*(4096) = 1048576
//#define DELTA 70                        // target DCO = DELTA*(4096) = 286720

volatile unsigned int i;

void Set_DCO(void);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  for (i = 0; i < 0xfffe; i++);             // Delay for XTAL stabilization
  P1DIR |= 0x10;                            // P1.4 output
  P1SEL |= 0x10;                            // P1.4 SMCLK output
  Set_DCO();                                // Set DCO

  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupt
}

void Set_DCO(void)                          // Set DCO to selected frequency
{
  unsigned int Compare, Oldcapture = 0;

  BCSCTL1 |= DIVA_3;                        // ACLK= LFXT1CLK/8 = 4096Hz
  TACCTL2 = CM_1 + CCIS_1 + CAP;            // CAP, ACLK
  TACTL = TASSEL_2 + MC_2 + TACLR;          // SMCLK, cont-mode, clear

  while (1)
  {
    while (!(CCIFG & TACCTL2));             // Wait until capture occured
    TACCTL2 &= ~CCIFG;                      // Capture occured, clear flag
    Compare = TACCR2;                       // Get current captured SMCLK
    Compare = Compare - Oldcapture;         // SMCLK difference
    Oldcapture = TACCR2;                    // Save current captured SMCLK

    if (DELTA == Compare)
      break;                                // If equal, leave "while(1)"
    else if (DELTA < Compare)
    {
      DCOCTL--;                             // DCO is too fast, slow it down
      if (DCOCTL == 0xFF)                   // Did DCO roll under?
        if (BCSCTL1 & 0x0f)
          BCSCTL1--;                        // Select lower RSEL
    }
    else
    {
      DCOCTL++;                             // DCO is too slow, speed it up
      if (DCOCTL == 0x00)                   // Did DCO roll over?
        if ((BCSCTL1 & 0x0f) != 0x0f)
          BCSCTL1++;                        // Sel higher RSEL
    }
  }
  TACCTL2 = 0;                              // Stop TACCR2
  TACTL = 0;                                // Stop Timer_A
  BCSCTL1 &= ~DIVA_3;                       // ACLK = LFXT1CLK = 32.768KHz
}