Thursday, June 3, 2010

Calibrating the MSP430 Very Low Power Oscillator

The MSP430F2xxx contains an internal 12kHz very low power low frequency oscillator (VLO). The frequency varies by part, temperature, and supply voltage. On an MSP430F248 the VLO runs at approx. 9.4kHz and on an MSP430F2274 it's approx. 12kHz.
On the MSP430F2274 datasheet (page 38) the base frequency varies between 4kHz-20kHz and has a temp drift of 0.5%/degC and a supply voltage drift of 4%/V.

So in order to make it useful we need to calibrate it. The method below will calibrate the VLO against the main oscillator. The accuracy of this calibration routine will only be as accurate as the main oscillator. If you're using one of the calibrated DCO frequencies (+/- 1%) then the end result will be the VLO within about 2% of actual. This will be more accurate if the main oscillator is sourced from a crystal.

This calibration routine uses Timer A in the capture mode to capture the number of main clock cycles between subsequent ACLK cycles. This routine only counts one pulse, for more consistency you may want to count multiple ACLK cycles and average them.

/** Calibrate VLO. Once this is done, the VLO can be used semi-accurately for timers etc.
Once calibrated, VLO is within ~2% of actual when using a 1% calibrated DCO frequency and temperature and supply voltage remain unchanged.
@return VLO frequency (number of VLO counts in 1sec)
@pre SMCLK is 4MHz
@pre MCLK is 8MHz
@pre ACLK sourced by VLO (BCSCTL3 = LFXT1S_2; in MSP430F2xxx)
@note Calibration is only as good as MCLK source. Obviously, if using the internal DCO (+/- 1%) then this value will only be as good as +/- 1%. YMMV.
@note On MSP430F248 or MSP430F22x2 or MSP430F22x4, must use TACCR2. On MSP430F20x2, must use TACCR0.
Check device-specific datasheet to see which module block has ACLK as a compare input.
For example, see page 23 of the MSP430F24x datasheet or page 17 of the MSP430F20x2 datasheet, or page 18 of the MSP430F22x4 datasheet.
@note If application will require accuracy over change in temperature or supply voltage, recommend calibrating VLO more often.
@post Timer A settings changed
@post ACLK divide by 8 bit cleared
unsigned int calibrateVlo()
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

BCSCTL1 |= DIVA_3; // Divide ACLK by 8
TACCTL2 = CM_1 + CCIS_1 + CAP; // Capture on ACLK
TACTL = TASSEL_2 + MC_2 + TACLR; // Start TA, SMCLK(DCO), Continuous
while ((TACCTL0 & CCIFG) == 0); // Wait until capture

TACCR2 = 0; // Ignore first capture

while ((TACCTL2 & CCIFG) == 0); // Wait for next capture
unsigned int firstCapture = TACCR2; // Save first capture

while ((TACCTL2 & CCIFG) ==0); // Wait for next capture

unsigned long counts = (TACCR2 - firstCapture); // # of VLO clocks in 8Mhz
BCSCTL1 &= ~DIVA_3; // Clear ACLK/8 settings

vloFrequency = ((unsigned int) (32000000l / counts));
return vloFrequency;