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

// uart test - TX

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

//

// MSP430G2553

// Jed Margolin  3/14/2016.

 

//  Built with Code Composer Studio v6

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

// main.c

 

#include <msp430.h>

//#include <msp430G2553.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);

void uart_init(void);

void uartsetup_4800(void);

void uart_send_byte(unsigned char byte);

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

int main(void)

{

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

            volatile unsigned char k = 0;

            volatile unsigned char m = 0;

            volatile unsigned char n = 0;

 

            WDTCTL = WDTPW + WDTHOLD;           // Stop watchdog timer

 

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

 

            P1SEL  |= BIT0;                     // ACLK

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

            P1DIR  |= BIT0;

 

            P1SEL  |= BIT1;                     // RX In

            P1SEL2 |= BIT1;

            P1REN |= BIT1;                      // pullup/pulldown enabled

            P1OUT |= BIT1;

            P1DIR &= ~(BIT1);               // In

 

            P1SEL  |= BIT2;                     // TX Out

            P1SEL2 |= BIT2;

            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

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

            P1DIR |= BIT6;                       // pullup

 

            P1DIR &= ~(BIT7);               // In - 60Hz phase

            P1OUT |= BIT7;                     // pullup

            P1SEL  &= ~(BIT7);              //

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

            P1REN |= BIT7;                      // pullup/pulldown enabled

 

// Enable the crystal

// BCSCTL1 comes out of reset with:

//                      XT2OFF = 1 (MSP430G2553 and MSP430G2211 don't have XT2)

//                      XTS = 0 (LFXT1 = Low Frequency mode)

//                      DIVAx = 0 (ACLK Divider = 1)

//                      RSELx = 7 (Range Select - should be for DCO only)

 

            BCSCTL3 |= LFXT1S_0 + XCAP_3;

            // LFXT1S = 0 (32768 crystal on LFXT1)

            // XCAP = 3 (12.5pF)

 

            while(IFG1 & OFIFG)            // OFIFG is Bit1 in IFG1 (Interrupt Flag Register)

                                                                        // and means oscillator fault

            {

                        IFG1 &= ~OFIFG;      // keep resetting it until it doesn't need to be reset

                        wait2();

            }

 

// We are going to leave SCG1 and SCG0 off

//          _bis_SR_register(SCG1 + SCG0);     // Set bits SCG1  and SCG0

//  SCG1 (System Clock Generator 1) When set turns off the SMCLK

//  SCG0 (System Clock Generator 0) When set turns off the DCO dc generator if DCOCLK is not used for MCLK or SMCLK

//  We will leave DCO dc generator on just in case

 

// end of setup for crystal

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

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

            P1OUT |= BIT6;

 

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

            caldata1 = DCOCTL;             // for debugging

            caldata2 = BCSCTL1;

 

            P1OUT &= ~(BIT6);

 

//          BCSCTL2 = 0x00;                  // SMCLK = DCO

            BCSCTL2 = 0x08;                  // SMCLK = ACLK

// SELMx(7,6) = 0 0   MCLK is DCO

// DIVMx(5,4) = 0 0   MCLK divider is /1

// SELS(3)    = 1         SMCLK is LFXT1CLK or VLOCLK

// DIVSx(2,1) = 0 0     SMCLK is /1, will be 32.768 KHz

// DCOR(0)    = 0        not present

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

// Initialize the uart

// At 4800 baud, the bit time is 208.3 us, the actual bit time is modulated to make it average out

            uartsetup_4800();

            uart_init();                              // no interrupts for either RX or TX

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

            m = 32;                                   // updata uart data every m times

            while (1)                                 // main loop

            {

 

                        P1OUT |= BIT6;         // trigger for 'scope

                        wait2();

                        P1OUT &= ~(BIT6);

 

                        uart_send_byte(n);

 

                        for(k=10; k>0; k--)     // toggle at full speed to show that DCO is working

                        {

                                    P1OUT |= BIT6;

                                    P1OUT &= ~(BIT6);

                        }

 

                        if(m-- == 0)

                        {

                                    n++;

                                    m=32;

                        }

                        wait(3);

 

            }  // end main loop

}  // end main

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

void wait(unsigned int time)

{

    volatile unsigned int i,j;

 

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

    {

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

            {

            }

    }

 

 return;

} // end main

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

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

 }

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

void uart_init(void)

{

            IE2 &= ~UCA0RXIE;            // default: Disable USCI_A0 RX interrupt

            IE2 &= ~UCA0TXIE;             // default: Disable USCI_A0 TX interrupt

}

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

// Low-Frequency Baud Rate Mode

// Read chapter 15.3.10 of msp430x2xxx user's guide for baud rate generation

void uartsetup_4800(void)

{

            P3SEL = 0x30;                       // P3.4,5 = USCI_A0 TXD/RXD, No need to set direction

            UCA0CTL1 |= UCSSEL_1;    // CLK = ACLK

            UCA0BR0 = 0x06;                 // 6 = INT(6.83), 32.768KHz/4800 = 6.8

            UCA0BR1 = 0x00;                                                                   //

            UCA0MCTL = UCBRS2 + UCBRS1 + UCBRS0;  // Modulation UCBRSx = 7 = round(0.83 * 8)

            UCA0CTL1 &= (~UCSWRST);                                              // ** Initialize USCI state machine

            UCA0CTL0 |= 0x80;              // odd parity

}

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

// Sends a single byte out through UART

void uart_send_byte(unsigned char byte)

{

            while (!(IFG2&UCA0TXIFG));         // USCI_A0 TX buffer ready?

            UCA0TXBUF = byte;                         // TX -> RXed character

}

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

// USCI A0/B0 Transmit ISR

#pragma vector=USCIAB0TX_VECTOR

__interrupt void USCI0TX_ISR(void)

{

            IE2 &= ~UCA0TXIE;                         // Disable USCI_A0 TX interrupt

}

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