CC2541 has four oscillators, namely:
- 32MHz external crystal
- 16MHz internal RC oscillator
- 32kHz external crystal
- 32kHz internal RC oscillator
From this we can see that CC2541 has its own oscillator, that is to say, even if the external circuit is not connected to the oscillator, CC2541 can still work. The answer is yes, but as a wireless RF transceiver, only an external 32MHz crystal oscillator can be used, unless you plan to use CC2541 as an ordinary enhanced 51 microcontroller, otherwise a 32MHz external crystal oscillator is indispensable. So what are the differences and uses of these four crystal oscillators?
The 32MHz external crystal oscillator has two functions: providing a clock source for the internal clock and for the RF transceiver
The function of the 16MHz RC internal oscillator is to provide a clock source for the internal clock. Note that it cannot be used for RF transceiver operation.
The 16MHz RC internal oscillator has low power consumption but poor accuracy, which is why it cannot be used in RF transceivers.
The 32kHz external crystal oscillator runs at 32.768KHz, and the 32kHz internal RC oscillator runs at 32.753kHz. These two clocks are mainly used in the Sleep Timer and Watchdog Timer. The internal 32kHz oscillator has low power consumption but low precision. You can choose one of the two at will, but you cannot use them at the same time. In other words, if the accuracy is not required, the external 32kHz crystal oscillator can be disconnected from the circuit.
Note: When the system is powered on, the default setting is to use the internal 16Mhz clock and the internal 32kHz oscillator.
How to select these four oscillators? It is selected by the CLKONCMD clock control command register. The definition of the CLKONCMD register is as follows:
Explain the CLKONCMD register
OSC32K: 32kHz selection bit
OSC: Main clock selection bit
TICKSPD: Divides the master clock and controls the global clock division for Timer 1, Timer 3 and Timer 4. The divider value can be set from 0.25 MHz to 32 MHz. Note that if CLKCONCMD.TICKSPD indicates a frequency higher than the system clock, the actual divider value specified in CLKCONSTA.TICKSPD is the same as the system clock. In short: the clock for Timer 1, 3, 4.
CLKSPD: Divide the main clock and use the divided frequency as the main clock, similar to PLL. Generally, this value is set to 000, that is, the main clock is 32Mhz
When the 32MHz crystal oscillator is selected as the main clock source (CLKONCMD.OSC = 0), the internal clock does not change to 32Mhz all at once. The internal 16MHz RC oscillator is first selected to make the system run. When the 32MHz crystal oscillator is stable, the 32MHz crystal oscillator is used as the main clock. The basis for judging whether it is stable is to look at the "CLKONSTA clock control status register", which is defined as follows
Only when CLKONSTA.OSC == 1 can it be said that the 32Mhz clock has stabilized. Therefore, a wait statement should be added in the program to prevent program execution errors when the clock is not stable.
The clock initialization code is as follows.
1 /****************************************************************
2 *Function name: InitClock
3 * Function: System clock initialization
4 *Entry parameters: None
5 *Export parameters: None
6 *****************************************************************/
7 void InitClock(void)
8 {
9 CLKCONCMD &= ~0x40; // Set the system clock source to 32MHZ crystal oscillator
10 while(CLKCONSTA & 0x40); // Wait for the crystal oscillator to stabilize
11 CLKCONCMD &= ~0x47; //Set the system main clock frequency to 32MHZ
12 }
However, when debugging, I always cannot get the 32MHz clock when calling this function, and the 16MHz working clock remains unchanged. I searched for a long time, but I don't know why the program always stops at the 10th line of code when debugging.
The program is debugged successfully and the system working clock changes to 32MHz. This program will be used in the future. The program code is as follows:
1 /****************************************************************
2 *Function name: SysStartXOSC
3 * Function: System clock initialization
4 *Entry parameters: None
5 *Export parameters: None
6 *****************************************************************/
7 void SysStartXOSC(void)
8 {
9 SLEEPCMD &= ~0x04; // Start all crystal oscillators
10 while (!(SLEEPSTA & 0x40)); // Wait for the crystal oscillator to stabilize
11
12 CLKCONCMD = (CLKCONCMD & 0x80) | 0x49; // Use 16M crystal as the main clock
13 while ((CLKCONSTA & ~0x80) != 0x49 ); // Wait for the main clock to switch to the 16M crystal oscillator
14
15 CLKCONCMD = (CLKCONCMD & ~0x80); // Use external 32K crystal as sleep clock
16 while ( (CLKCONSTA & 0x80) != 0 ); // Wait for the sleep clock to switch to the external 32K crystal oscillator
17
18 CLKCONCMD = (CLKCONCMD & 0x80); // Use 32M crystal as the main clock
19 while ( (CLKCONSTA & ~0x80) != 0 ); // Wait for the main clock to switch to the 32M crystal oscillator
20
21 SLEEPCMD |= 0x04; // Turn off unused crystal
22 }
|