msp430f5529-clock configuration, routine analysis
[Copy link]
There are a total of 9 routines related to clock configuration in the package. In fact, after completing the first few, the rest are just similar.
(1) First, the first and simplest one, because it does not configure the clock at all... However, it is still useful because it shows us the clock status of the microcontroller after power-up.
// ACLK = REFO = 32.768kHz, MCLK = SMCLK = Default 1MHz
#include <msp430.h>
int main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
P1DIR |= BIT1; // P1.1 output
P1DIR |= BIT0; // ACLK set out to pins
P1SEL |= BIT0;
P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;
while(1)
{
P1OUT ^= BIT1;
__delay_cycles(60000); // Delay
}
}
Copy code
When I first started learning, I was very confused about the default clock status after PUC:
After a PUC, the UCS module default configuration is:
XT1 in LF mode
is
selected as the oscillator source for XT1CLK
. and XT1CLK is selected as the FLL reference clock, FLLREFCLK.
On devices that have XIN and XOUT shared with general-purpose I/O, XIN and XOUT pins are set to
general-purpose I/Os and XT1 remains disabled until the I/ O ports are configured for XT1 operation. If
XIN and XOUT are not shared with general-purpose I/O, XT1 is enabled.
When available, XT2IN and XT2OUT pins are set to general-purpose I/Os and XT2 is disabled.
After power-on, it said that ACLK and FLL use XT1 as the source by default, but you don't turn on XT1. That problem bothered me for a long time. I used an oscilloscope to test and found that ACLK was about 327668Hz, but the user manual said later that these two clocks will turn to REFOCLK, which is an internal 32768Hz clock, after XT1LF fails (I didn't read it at that time - -||).
The truth is this:
This is a screenshot I took when pausing the simulation debugging with CCS. The program has been executed to while(1). When I open the register window, I can see that XT1LFOFFG and DCOFFG are set to 1. The former is set because ACLK and FLL are in the default state and have been sourcing from XT1. XT1 is disabled and invalid, so XT1LFOFFG is set. The program can still run because when XT1LF is invalid, these two clocks temporarily source from REFOCLK. Why is the latter also set to 1? It does not source from XT1. Haha, I said in the previous chapter that the DCO in the default state is stabilized by FLL, and the clock source XT1 of FLL has problems, so DCOFFG is set to 1.
Therefore, even if you do not need to adjust the clock of the microcontroller, please configure the clock at the beginning of the program. Develop this habit and at least turn on XT1, because XT1 is much more stable than REFOCLK.
(2) The second example, which is well worth the trouble, sets up the FLL to stabilize the DCO at 8MHz. Oh no! It's 16MHz.
// ACLK = REFO = 32kHz, MCLK = SMCLK = 8MHz
#include <msp430.h>
int main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
P1DIR |= BIT1; // P1. 1 output
P1DIR |= BIT0; // ACLK set out to pins
P1SEL |= BIT0;
P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL | = BIT7;
UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
// Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
//
Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
UCSCTL2 |= 249; // Set DCO Multiplier for 8MHz
/ / (N + 1) * FLLRef = Fdco
// (249 + 1) * 32768 = 8MHz
__bic_SR_register(SCG0); // Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is nx 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle
__delay_cycles(250000 );
while(1)
{
P1OUT ^= BIT0; // Toggle P1.0
__delay_cycles(600000); // Delay
}
}
Copy
lines 18 and 19 of code and change the clock sources of these two clocks to REFO. There is no clock requesting the clock source from XT1, and there is no problem with DCO, so the following do{}while statement can pass. This statement is to detect whether there is a problem with the clock. If the crystal is oscillating but has not reached the working state, it will be in this The loop waits for the crystal to oscillate. XT2OFFG, XT1LFOFFG, DCOFFG, and OFIFG must all be cleared by software. In addition, after POR, OFIFG is set.
For example, if I comment out UCSCTL4 |= SELA_2;, ACLK will also apply for the clock source from REFO, but the program will run differently.
It will be stuck in this loop and cannot get out. Just like the situation (1) above, the default value in the ACLK register is still requesting the clock source from XT1. XT1 does not work and XT1LFOFFG is set.
In fact, there is no need to configure line 20, because the default is 0x0000, and FLL will automatically adjust UCSCTL0.
The essence of this program lies in the 4 lines 30-35 (what? 4 lines?), which are the standard process for configuring FLL. Before adjusting the registers related to FLL, it is very important to disable FLL first, otherwise unpredictable results may occur.
As mentioned in the previous chapter, to use FLL to stabilize DCO, you only need to set the FLL clock and then configure DCORSEL and FLLN. Use the formula:
·fDCOCLK= D × (N + 1) × (fFLLREFCLK÷ n)
·fDCOCLKDIV= (N + 1) × (fFLLREFCLK÷ n)
You can calculate the required value, what? This is different from the comment? Oh, yes, the comment is wrong. In the program, (249 + 1) * 32768 = 8MHz is calculated as fDCOCLKDIV! Not fDCOCLK written in the comment! And the formula in the comment that looks like a formula is nothing at all!
Why did I measure the frequency of about 8MHz as it said? Haha, because it was wrong. SMCLK did not use DCOCLK. It still used DCOCLKDIV by default. So the formula calculated the frequency of SMCLK, but it was wrong twice: 1. (N + 1) * FLLRef = Fdco. 2. SMCLK used DCOCLK. So it went back. I didn't expect that the routine of TI would also make mistakes. I, a rookie, caught it.
In order to expose TI's true identity, I changed line 19 to
UCSCTL4 &= ~SELS_4; //Cancel the default SELS_4
UCSCTL4 |= SELA_2 + SELS_3; //Set SMCLK = DCO
Copy the code
and measure SMCLK, 16.828MHz, which is close to the calculated value, the conclusion is correct! So when you calculate and use DCO, you should pay attention to the existence of DCODIV. In my opinion, DCODIV is more like the boss.
Then I set my sights on DCORSEL, because the information I read kept saying that as long as the four quantities in the formula are set correctly, the desired DCO or DCODIV frequency can be obtained. So why set DCORSEL?
So, I commented out UCSCTL1 = DCORSEL_5;, the default value of RCORSEL is RCORSEL_2, and debugged it again.
It is found that DCOFFG is set, but the frequency of SMCLK is only 2.456MHz, which is not the calculated value!
The function of DCORSEL is to set the frequency range of DCO. For details, see the following table in the datasheet:
It can be seen that when DCORSEL = 2, the maximum DCO is only 7.38MHz, which is less than the 16MHz we want.
In other words, even if FLL is used to stabilize DCO, the approximate range of DCO, i.e. DCORSEL, still needs to be set!
So, I set DCORSEL = 3 and adjusted it once
DCOOFFG is still set, and the SMCLK frequency is only 4.654MHz. Looking at the table, when DCORSLE = 3, the maximum DCO is 14.0, which has not yet reached the calculated value.
After setting DCORSEL to 4, everything works fine. I tried 5, 6, and 7 and they all worked fine. The calculated value of 16.384MHz is included in these ranges. So the conclusion is correct! Again, even if you use FLL to stabilize the DCO, the approximate range of the DCO, i.e. DCORSEL, still needs to be set! This range only needs to include the target value.
(3) I finally finished working on Example 2. The following examples are just changing the clock source and frequency. They are not worth studying anymore. However, these are my conclusions after reading them all.
In routines 3 and 4, FLL is still set, but the value in 3 is changed, do{}while is placed below, DCODIV is still used, and the comments are still wrong...
XT1 is enabled in 4, using these 3 codes:
P5SEL |= BIT4+BIT5; // Port select XT1
UCSCTL6 &= ~(XT1OFF); // XT1 On
UCSCTL6 |= XCAP_3; // Internal load cap
Copy code
Open XIN and XOUT
Set 0XT1OFF
To be honest, I don't know how to choose the capacitor, but 12pf is selected here, so let's go with 12pf. In fact, the default value in XCAP after power-on is XCAP_3, so you don't need to configure it here
After enabling XT1, don't forget to wait for it to start oscillating:
// Loop until XT1 fault flag is cleared
do
{
UCSCTL7 &= ~XT1LFOFFG; // Clear XT1 fault flags
}while (UCSCTL7&XT1LFOFFG); // Test XT1 fault flagCopy
code
There is nothing else to say, let me talk about the awesomeness of XT1. Here the calculated values of ACLK and SMCLK are
ACLK = 32768Hz, SMCLK = 2457600Hz.
I measured it out.
ACLK = 32767.5Hz, SMCLK = 2457560Hz.
Very high precision, and very stable, the value has never changed. Compared with the REFO, the frequency will always have an error of a few tenths to a few tenths of a percent and will fluctuate, so of course the XT1 is better.
(4) Well, after writing so much, this is all I can share. Let’s stop here regarding the clock.
|