Back
//******************************************************************************
// MSP430x26x Demo - Basic Clock, VLO-Driven Timer with VLO Compensation
//
// This example toggles P1.0 approx. every second, using a timer driven by the
// VLO. The VLO freq can vary between 4kHz-20kHz, so the timer compare value
// must be adjusted to compensate, in order to produce a one-second interval.
// So in effect, this code performs a kind of "calibration" of the VLO. This
// is done by counting the number of 1MHz DCO pulses in one ACLK=VLO/8 period,
// assigned to dco_delta. VLO is /8 in order to increase the number of DCO
// pulses in one ACLK pulse, increasing the resolution of the measurement,
// and therefore the accuracy of the one-second interval. Since 1,000,000
// DCO pulses at 1MHz are required to produce a one-second interval, the
// number of VLO/8 pulses in one second is given by 1M/dco_delta. This value
// is loaded into TACCR0 as the timer compare value.
// MSP430x2xx devices are shipped with calibration values in info memory that,
// when used by software, allow the DCO to operate within approx. +/-1% of
// common values such as 1MHz. (See the datasheet for add'l information.)
// Through the algorithm shown here, this accuracy is extended to the VLO. An
// additional source of error in this algorithm is that the VLO/8 freq will
// most likely not be evenly divisible by the DCO freq, and therefore up to
// one DCO pulse may be lost. At nominal values, there are 400 1MHz DCO
// pulses in one 2.5kHz VLO/8 pulse, so losing one clock pulse produces
// ~0.25% error, in addition to the error tolerance of the calibrated DCO.
// ACLK = VLO/8, MCLK = SMCLK = 1MHz
//
// MSP430F261x/241x
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | |
// | P1.0/ACLK|-->LED 1 second interrupt
//
//
// B. Nisarga
// Texas Instruments Inc.
// September 2007
// Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include <msp430x26x.h>
unsigned int dco_delta;
// Function Prototype
unsigned int measureVLO( void );
void main(void)
{
WDTCTL = WDTPW +WDTHOLD; // Stop Watchdog Timer
P1DIR |= 0x01; // P1.0 output
dco_delta = measureVLO(); // dco delta = number of
// 1MHz cycles in 8 VLO cycles
//Clock settings: DCO freq = 1MHz; ACLK = VLO/8
// Timer A interval interrupt setup
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = (1000000 / dco_delta);
TACTL = TASSEL_1 + MC_1; // ACLK, upmode
P1OUT = 0x01;
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt
}
// Timer_A0 Interrupt Vector
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0(void)
{
P1OUT ^= 0x01; // Toggle P1.0
}
// This function measures the number of 1MHz clock pulses in 8 VLO cycles
unsigned int measureVLO( void )
{
static unsigned int start_count, stop_count;
// Clock settings to achieve the good resolution for VLO freq measurement
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
TACCTL2 = CM_1+CCIS_1+CAP; // CAP, ACLK
TACTL = TASSEL_2+MC_2+TACLR; // SMCLK, cont-mode, clear
BCSCTL3 |= LFXT1S_2; // ACLK = VLO
BCSCTL2 = 0x0;
BCSCTL1 |= DIVA_3; // ACLK = VLO/8
TACCTL2 &= ~CCIFG; // Clear capture flag
while (!(CCIFG & TACCTL2)); // Test capture flag to skip 1st cycle
TACCTL2 &= ~CCIFG; // Clear capture flag
while (!(CCIFG & TACCTL2)); // Test capture flag to skip 2nd cycle
start_count = TACCR2; // save hardware captured value
TACCTL2 &= ~CCIFG; // Clear capture flag
while (!(CCIFG & TACCTL2)); // Test capture flag to capture a good clock
TACTL &= ~MC_3; // Stop timer
stop_count = TACCR2;
return(stop_count - start_count); // return
}
|