//****************************************************************************** // MSP430G2xx2 Demo - DCO Calibration Constants Programmer // // NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION // CONSTANTS LOCATED IN INFOA WITH NEW VALUES USE ONLY IF THE ORIGINAL // CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED // // Description: This code re-programs the G2xx2 DCO calibration constants // A software FLL mechanism is used to set the DCO based on an external // 32kHz reference clock After each calibration, the values from the // clock system are read out and stored in a temporary variable The final // frequency the DCO is set to is 1MHz, and this frequency is also used // during Flash programming of the constants The program end is indicated // by the blinking LED // ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO // //* External watch crystal installed on XIN XOUT is required for ACLK *// // // MSP430G2xx2 // // /|\| XIN|// | | | 32kHz // |RST XOUT|// | | // | P1.0| > LED // | P1.4| > SMLCK = target DCO // // A Dannenberg // Texas Instruments Inc // May 2010 // Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 3.42A //****************************************************************************** #include "msp430g2452.h" #define #define #define #define DELTA_1MHZ DELTA_8MHZ DELTA_12MHZ DELTA_16MHZ 244 1953 2930 3906 unsigned char CAL_DATA[8]; volatile unsigned int i; int j; char *Flash_ptrA; void Set_DCO(unsigned int Delta); void main(void) { WDTCTL = WDTPW + WDTHOLD; for (i = 0; i < 0xfffe; i++); P1OUT = 0x00; P1SEL = 0x10; P1DIR = 0x11; // // // // 244 x 4096Hz = 999.4Hz 1953 x 4096Hz = 7.99MHz 2930 x 4096Hz = 12.00MHz 3906 x 4096Hz = 15.99MHz // Temp storage for constants // Segment A pointer // // // // // Stop WDT Delay for XTAL stabilization Clear P1 output latches P1.4 SMCLK output P1.0,4 output j = 0; // Reset pointer Set_DCO(DELTA_16MHZ); CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; // Set DCO and obtain constants Set_DCO(DELTA_12MHZ); CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; // Set DCO and obtain constants Set_DCO(DELTA_8MHZ); CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; // Set DCO and obtain constants Set_DCO(DELTA_1MHZ); CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; // Set DCO and obtain constants Flash_ptrA = (char *)0x10C0; FCTL2 = FWKEY + FSSEL0 + FN1; FCTL1 = FWKEY + ERASE; FCTL3 = FWKEY + LOCKA; *Flash_ptrA = 0x00; FCTL1 = FWKEY + WRT; Flash_ptrA = (char *)0x10F8; for (j = 0; j < 8; j++) *Flash_ptrA++ = CAL_DATA[j]; FCTL1 = FWKEY; FCTL3 = FWKEY + LOCKA + LOCK; // // // // // // // while (1) { P1OUT ^= 0x01; for (i = 0; i < 0x4000; i++); } Point to beginning of seg A MCLK/3 for Flash Timing Generator Set Erase bit Clear LOCK & LOCKA bits Dummy write to erase Flash seg A Set WRT bit for write operation Point to beginning of cal consts // re-flash DCO calibration data // Clear WRT bit // Set LOCK & LOCKA bit // Toggle LED // SW Delay } void Set_DCO(unsigned int Delta) { unsigned int Compare, Oldcapture = 0; // Set DCO to selected frequency BCSCTL1 |= DIVA_3; TACCTL0 = CM_1 + CCIS_1 + CAP; TACTL = TASSEL_2 + MC_2 + TACLR; // ACLK = LFXT1CLK/8 // CAP, ACLK // SMCLK, cont-mode, clear while (1) { while (!(CCIFG & TACCTL0)); TACCTL0 &= ~CCIFG; Compare = TACCR0; Compare = Compare - Oldcapture; Oldcapture = TACCR0; // // // // // if (Delta == Compare) break; else if (Delta < Compare) { DCOCTL ; if (DCOCTL == 0xFF) if (BCSCTL1 & 0x0f) BCSCTL1 ; } else { DCOCTL++; if (DCOCTL == 0x00) if ((BCSCTL1 & 0x0f) != 0x0f) BCSCTL1++; } } TACCTL0 = 0; TACTL = 0; Wait until capture occured Capture occured, clear flag Get current captured SMCLK SMCLK difference Save current captured SMCLK // If equal, leave "while(1)" // DCO is too fast, slow it down // Did DCO roll under? // Select lower RSEL // DCO is too slow, speed it up // Did DCO roll over? // Sel higher RSEL // Stop TACCR0 // Stop Timer_A BCSCTL1 &= ~DIVA_3; } // ACLK = LFXT1CLK