1 | //******************************************************************************
|
2 | // MSP430F22x4 Demo - DCO Calibration Constants Programmer
|
3 | //
|
4 | // NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION
|
5 | // CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL
|
6 | // CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED.
|
7 | //
|
8 | // Description: This code re-programs the F2xx DCO calibration constants.
|
9 | // A software FLL mechanism is used to set the DCO based on an external
|
10 | // 32kHz reference clock. After each calibration, the values from the
|
11 | // clock system are read out and stored in a temporary variable. The final
|
12 | // frequency the DCO is set to is 1MHz, and this frequency is also used
|
13 | // during Flash programming of the constants. The program end is indicated
|
14 | // by the blinking LED.
|
15 | // ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
|
16 | // //* External watch crystal installed on XIN XOUT is required for ACLK *//
|
17 | //
|
18 | // MSP430F22x4
|
19 | // ---------------
|
20 | // /|\| XIN|-
|
21 | // | | | 32kHz
|
22 | // --|RST XOUT|-
|
23 | // | |
|
24 | // | P1.0|--> LED
|
25 | // | P2.1|--> SMLCK = target DCO
|
26 | //
|
27 | // A. Dannenberg
|
28 | // Texas Instruments Inc.
|
29 | // April 2006
|
30 | // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
|
31 | //******************************************************************************
|
32 | #include "msp430x22x4.h"
|
33 |
|
34 | #define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz
|
35 | #define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz
|
36 | #define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz
|
37 | #define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz
|
38 |
|
39 | unsigned char CAL_DATA[8]; // Temp. storage for constants
|
40 | volatile unsigned int i;
|
41 | int j;
|
42 | char *Flash_ptrA; // Segment A pointer
|
43 | void Set_DCO(unsigned int Delta);
|
44 |
|
45 | void main(void)
|
46 | {
|
47 | WDTCTL = WDTPW + WDTHOLD; // Stop WDT
|
48 | for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization
|
49 | P1OUT = 0x00; // Clear P1 output latches
|
50 | P1DIR = 0x01; // P1.0 output
|
51 | P2SEL |= 0x02; // P2.1 SMCLK output
|
52 | P2DIR |= 0x02; // P2.1 output
|
53 |
|
54 | j = 0; // Reset pointer
|
55 |
|
56 | Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants
|
57 | CAL_DATA[j++] = DCOCTL;
|
58 | CAL_DATA[j++] = BCSCTL1;
|
59 |
|
60 | Set_DCO(DELTA_12MHZ); // Set DCO and obtain constants
|
61 | CAL_DATA[j++] = DCOCTL;
|
62 | CAL_DATA[j++] = BCSCTL1;
|
63 |
|
64 | Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants
|
65 | CAL_DATA[j++] = DCOCTL;
|
66 | CAL_DATA[j++] = BCSCTL1;
|
67 |
|
68 | Set_DCO(DELTA_1MHZ); // Set DCO and obtain constants
|
69 | CAL_DATA[j++] = DCOCTL;
|
70 | CAL_DATA[j++] = BCSCTL1;
|
71 |
|
72 | Flash_ptrA = (char *)0x10C0; // Point to beginning of seg A
|
73 | FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator
|
74 | FCTL1 = FWKEY + ERASE; // Set Erase bit
|
75 | FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits
|
76 | *Flash_ptrA = 0x00; // Dummy write to erase Flash seg A
|
77 | FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
|
78 | Flash_ptrA = (char *)0x10F8; // Point to beginning of cal consts
|
79 | for (j = 0; j < 8; j++)
|
80 | *Flash_ptrA++ = CAL_DATA[j]; // re-flash DCO calibration data
|
81 | FCTL1 = FWKEY; // Clear WRT bit
|
82 | FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit
|
83 |
|
84 | while (1)
|
85 | {
|
86 | P1OUT ^= 0x01; // Toggle LED
|
87 | for (i = 0; i < 0x4000; i++); // SW Delay
|
88 | }
|
89 | }
|
90 |
|
91 | void Set_DCO(unsigned int Delta) // Set DCO to selected frequency
|
92 | {
|
93 | unsigned int Compare, Oldcapture = 0;
|
94 |
|
95 | BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8
|
96 | TACCTL2 = CM_1 + CCIS_1 + CAP; // CAP, ACLK
|
97 | TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear
|
98 |
|
99 | while (1)
|
100 | {
|
101 | while (!(CCIFG & TACCTL2)); // Wait until capture occured
|
102 | TACCTL2 &= ~CCIFG; // Capture occured, clear flag
|
103 | Compare = TACCR2; // Get current captured SMCLK
|
104 | Compare = Compare - Oldcapture; // SMCLK difference
|
105 | Oldcapture = TACCR2; // Save current captured SMCLK
|
106 |
|
107 | if (Delta == Compare)
|
108 | break; // If equal, leave "while(1)"
|
109 | else if (Delta < Compare)
|
110 | {
|
111 | DCOCTL--; // DCO is too fast, slow it down
|
112 | if (DCOCTL == 0xFF) // Did DCO roll under?
|
113 | if (BCSCTL1 & 0x0f)
|
114 | BCSCTL1--; // Select lower RSEL
|
115 | }
|
116 | else
|
117 | {
|
118 | DCOCTL++; // DCO is too slow, speed it up
|
119 | if (DCOCTL == 0x00) // Did DCO roll over?
|
120 | if ((BCSCTL1 & 0x0f) != 0x0f)
|
121 | BCSCTL1++; // Sel higher RSEL
|
122 | }
|
123 | }
|
124 | TACCTL2 = 0; // Stop TACCR2
|
125 | TACTL = 0; // Stop Timer_A
|
126 | BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK
|
127 | }
|