//***************************************************************************************

// TimerA with interrupts

//   Use 32.768 KHz crystal for TIMERA and SIMCLK but use DCO for MCLK

//          TIMERA can use ACLK without requiring that SIMCLK also be ACLK

//

// MSP430G2211

// Jed Margolin  3/14/2016.

//  Built with Code Composer Studio v6

//***************************************************************************************

#include <msp430.h>

//#include <msp430G2211.h>

 

#define DELTA_1MHZ    244                       // 244 x 4096Hz = 999.4Hz

#define DELTA_8MHZ    1953                     // 1953 x 4096Hz = 7.99MHz

#define DELTA_12MHZ   2930                    // 2930 x 4096Hz = 12.00MHz

#define DELTA_16MHZ   3906                    // 3906 x 4096Hz = 15.99MHz

 

#define TIME 100

#define DCOUNT 8

 

void wait(unsigned int);

void wait2(void);

void Set_DCO(unsigned int Delta);

 

volatile unsigned int timer_flag = 0;

//=======================================================

int main(void)

{

            unsigned char caldata1, caldata2;                  // Temp. storage for constants

            volatile unsigned int k = 0;

 

            WDTCTL = WDTPW + WDTHOLD;          // Stop WDT

 

            wait(1000);                             // give the crystal 500ms to stabilize

 

            P1SEL  |= BIT0;                     // ACLK out

//          P1SEL2 &= ~(BIT0);

            P1DIR  |= BIT0;

 

            P1SEL  &= BIT1;                   // In

//          P1SEL2 |= BIT1;                    // not used by msp430g2211

            P1REN |= BIT1;                      // pullup/pulldown enabled

            P1OUT |= BIT1;                     //

            P1DIR &= ~(BIT1);               // In

 

            P1SEL  |= BIT2;                     // Out

//          P1SEL2 |= BIT2;                    // not used by msp430g2211

            P1DIR |= BIT2;                       //

 

            P1SEL  &= ~(BIT3);              // Out - for testing

//          P1SEL2 &= ~(BIT3);             // not used by msp430g2211

            P1DIR |= BIT3;                       //

 

            P1SEL  |= BIT4;                     // Out for SMCLK so we know it's working

//          P1SEL2 &= ~(BIT4);             // not used by msp430g2211

            P1DIR |= BIT4;                       //

 

            P1SEL  &= ~(BIT5);              // In

//          P1SEL2 &= ~(BIT5);             // not used by msp430g2211

            P1REN |= BIT5;                      // pullup/pulldown enabled

            P1OUT |= BIT5;                     // pullup

            P1DIR &= ~(BIT5);               //

 

            P1SEL  &= ~(BIT6);              // Out - for testing

//          P1SEL2 &= ~(BIT6);             // not used by msp430g2211

            P1DIR |= BIT6;                       // P1.6 output

 

// Lock the DCO to the 32.768 KHz crystal - 8 MHz

            Set_DCO(DELTA_8MHZ);   // Set DCO and obtain constants

            caldata1 = DCOCTL;             // for debugging

            caldata2 = BCSCTL1;

 

            CCTL0 = CCIE;               // CCR0 interrupt enabled

    CCR0 = 1000-1;                     //  1/32.768 KHz = 30.5175 us; 30.5175us * 1000 = 30.5175ms

    TACTL |= TACLR;                 // clear timer

    TACTL = TASSEL_1 + MC_1;    // ACLK, upmode, clear timer

 

    __bis_SR_register(GIE);                // Enable interrupts

 

            while (1)                     // main loop

            {

                        if(timer_flag)

                        {

                                    P1OUT ^= BIT6;

                                    timer_flag = 0;

                        }

 

            }  // end while main loop

}  // end main

//==========================================================

// Timer A0 interrupt service routine

#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A (void)

{

            timer_flag = 1;

}

//==========================================================

void wait(unsigned int time)

{

    volatile unsigned int i,j;

 

    for(i=time; i>0; i--)

    {

            for(j=382; j>0; j--);

            {

            }

    }

 

 return;

}

 //==========================================================

void wait2()

{

volatile unsigned int i;

 

            for(i=0; i<48; i++){}

            return;

}

//========================================================

void Set_DCO(unsigned int Delta)            // Set DCO to selected frequency

{

  unsigned int Compare, Oldcapture = 0;

 

  BCSCTL1 |= DIVA_3;                                 // ACLK = LFXT1CLK/8

  TACCTL0 = CM_1 + CCIS_1 + CAP;        // CAP, ACLK

  TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear

 

  while (1)

  {

    while (!(CCIFG & TACCTL0));                // Wait until capture occured

    TACCTL0 &= ~CCIFG;                             // Capture occured, clear flag

    Compare = TACCR0;                                 // Get current captured SMCLK

    Compare = Compare - Oldcapture;            // SMCLK difference

    Oldcapture = TACCR0;                              // 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

    }

  }

  TACCTL0 = 0;                                 // Stop TACCR0

  TACTL = 0;                                      // Stop Timer_A

 

  BCSCTL1 &= ~DIVA_3;                // ACLK is divide by 1

}

//=================================================================