//***************************************************************************************
// 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
}
//=================================================================