Learning STM32 (3) - Power supply, clock, reset circuit

Publisher:HaifeengLatest update time:2018-05-13 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Stm32 clock analysis

Most of the analysis materials come from the opendev forum. All I did was add some of my own analysis and collation. Due to my limited personal ability, omissions are inevitable. I welcome your corrections.

1. Hardware connection issues

[Reprint] Understanding of STM32 clock


If you use the internal RC oscillator instead of an external crystal oscillator, please proceed as follows:

1) For products with 100 or 144 pins, OSC_IN should be grounded and OSC_OUT should be left floating.
2) For products with less than 100 pins, there are two ways to connect:
   i) OSC_IN and OSC_OUT are grounded through 10K resistors. This method can improve EMC performance.
   ii) Remap OSC_IN and OSC_OUT to PD0 and PD1 respectively, and then configure PD0 and PD1 as push-pull outputs and output '0'. This method can reduce power consumption and save 2 external resistors (compared to i above).

 

//8.eewimg.cn/news/uploadfile/2018/0513/20180513033919725.jpg

The analysis of the above figure is as follows:

Important clocks:
  The relationship between PLLCLK, SYSCLK, HCKL, PCLK1, PCLK2 should be clarified;
      1. HSI: high-speed internal clock signal The clock (8M frequency) in the STM32 microcontroller has poor accuracy
      2. HSE: high-speed external clock signal High-precision source (1) HSE external crystal/ceramic resonator (crystal oscillator) (2) HSE user external clock        
      3. LSE: low-speed external crystal 32.768kHz mainly provides an accurate clock source Generally used as an RTC clock
in STM32, there are five clock sources, HSI, HSE, LSI, LSE, PLL.
  ①, HSI is a high-speed internal clock, RC oscillator, with a frequency of 8MHz.
  ②, HSE is a high-speed external clock, which can be connected to a quartz/ceramic resonator, or an external clock source, with a frequency range of 4MHz~16MHz.
  ③, LSI is a low-speed internal clock, RC oscillator, with a frequency of 40kHz.
  ④. LSE is a low-speed external clock connected to a quartz crystal with a frequency of 32.768kHz.
  ⑤. PLL is a phase-locked loop frequency multiplication output, and its clock input source can be selected as HSI/2, HSE or HSE/2. The frequency multiplication can be selected from 2 to 16 times, but its maximum output frequency must not exceed 72MHz.
  The 40kHz LSI is used for the independent watchdog IWDG, and it can also be selected as the clock source of the real-time clock RTC. In addition, the clock source of the real-time clock RTC can also be selected as LSE, or 128-division of HSE. The clock source of RTC is selected by RTCSEL[1:0].
  There is a full-speed USB module in STM32, and its serial interface engine requires a clock source with a frequency of 48MHz. This clock source can only be obtained from the PLL output, and can be selected as 1.5 division or 1 division, that is, when the USB module needs to be used, the PLL must be enabled and the clock frequency is configured to 48MHz or 72MHz.
  In addition, STM32 can also select a clock signal to output to the MCO pin (PA8), which can be selected as the 2-division of the PLL output, HSI, HSE, or system clock.
  The system clock SYSCLK is the clock source for most components in STM32. The system clock can be selected as PLL output, HSI or HSE. The maximum frequency of the system clock is 72MHz. It is divided by the AHB divider and sent to each module for use. The AHB divider can select 1, 2, 4, 8, 16, 64, 128, 256, 512 divisions. The clock output by the AHB divider is sent to 5 major modules:
  ①, sent to the HCLK clock used by the AHB bus, core, memory and DMA.
  ②, sent to the system timer clock of Cortex after 8 division.
  ③, sent directly to the idle running clock FCLK of Cortex.
  ④, sent to the APB1 divider. The APB1 divider can be divided into 1, 2, 4, 8, or 16 frequency divisions. One of its outputs is used by the APB1 peripheral (PCLK1, maximum frequency 36MHz), and the other is sent to the timer (Timer) 2, 3, or 4 frequency multipliers. The frequency multiplier can be selected as 1 or 2 times, and the clock output is used by timers 2, 3, and 4.
  ⑤. Sent to the APB2 divider. The APB2 divider can be divided into 1, 2, 4, 8, or 16 frequency divisions. One of its outputs is used by the APB2 peripheral (PCLK2, maximum frequency 72MHz), and the other is sent to the timer (Timer) 1 frequency multiplier. The frequency multiplier can be selected as 1 or 2 times, and the clock output is used by timer 1. In addition, the APB2 divider has one output for the ADC divider, which is sent to the ADC module after division. The ADC divider can be divided into 2, 4, 6, or 8 times.
  Among the above clock outputs, many have enable control, such as AHB bus clock, core clock, various APB1 peripherals, APB2 peripherals, etc. When you need to use a module, remember to enable the corresponding clock first.
  It should be noted that the timer multiplier, when the APB division is 1, its multiplier value is 1, otherwise its multiplier value is 2.
  The devices connected to APB1 (low-speed peripherals) are: power interface, backup interface, CAN, USB, I2C1, I2C2, UART2, UART3, SPI2, window watchdog, Timer2, Timer3, Timer4. Note that although the USB module requires a separate 48MHz clock signal, it should not be the clock for the USB module to work, but only the clock provided to the serial interface engine (SIE). The clock for the USB module to work should be provided by APB1.
  The devices connected to APB2 (high-speed peripherals) are: UART1, SPI1, Timer1, ADC1, ADC2, all ordinary IO ports (PA~PE), and second function IO ports.
Registers involved:
RCC register structure, RCC_TypeDeff, is defined in the file "stm32f10x_map.h" as follows:
typedef struct 

vu32 CR; //HSI, HSE, CSS, PLL, etc. enable
vu32 CFGR; //PLL, etc. clock source selection and division coefficient setting
vu32 CIR; // Clear/enable clock ready interrupt
vu32 APB2RSTR; //APB2 line peripheral reset register
vu32 APB1RSTR; //APB1 line peripheral reset register
vu32 AHBENR; //DMA, SDIO, etc. clock enable
vu32 APB2ENR; //APB2 line peripheral clock enable
vu32 APB1ENR; //APB1 line peripheral clock enable
vu32 BDCR; //Backup domain control register
vu32 CSR;            
} RCC_TypeDef;
  The specific definition and usage of these registers can be found in the chip manual, because C language development does not need to deal with them directly. Of course, if you can understand and remember them, it will undoubtedly be beneficial.
    If the external crystal oscillator is 8Mhz and the maximum operating frequency is 72Mhz, it is obviously necessary to use PLL multiplier 9 times. These settings need to be completed in the initialization stage. For the convenience of explanation, the RCC setting function of the routine is used and explained in the form of Chinese comments:


static void RCC_Config(void)
{

   
    RCC_DeInit();

   
    RCC_HSEConfig(RCC_HSE_ON);

   
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if (HSEStartUpStatus == SUCCESS)
    {
       
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

       
        FLASH_SetLatency(FLASH_Latency_2);

       
        RCC_HCLKConfig(RCC_SYSCLK_Div1);

       
        RCC_PCLK2Config(RCC_HCLK_Div1);

       
        RCC_PCLK1Config(RCC_HCLK_Div2);

       
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);

       
        //This sentence is missing in the above routine, but it is very important
        
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

       
        RCC_PLLCmd(ENABLE);


       
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {}

       
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

       
        while (RCC_GetSYSCLKSource() != 0x08)
        {}
    }
    
    //Enable the peripheral interface bus clock. Pay attention to the affiliation of each peripheral. Different chips have different allocations. You can check the manual when the time comes
    . RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                           RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
                           RCC_APB2Periph_AFIO, ENABLE);
}
       From the above program, it can be seen that the setting of the system clock is relatively complicated. The more peripherals there are, the more factors need to be considered. At the same time, this setting also has rules to follow, and the setting parameters are also in order and specification. This should be noted in the application. For example, the setting of PLL needs to be before enabling. Once the PLL is enabled, the parameters cannot be changed.
       After this setting, for the case of an external 8Mhz crystal oscillator, the system clock is 72Mhz, the high-speed bus and low-speed bus 2 are both 72Mhz, the low-speed bus 1 is 36Mhz, the ADC clock is 12Mhz, and the USB clock can achieve 48Mhz data transmission after 1.5 division.
       The general clock setting needs to consider the source of the system clock first, whether it is an internal RC, an external crystal or an external oscillator, and whether a PLL is needed. Then consider the internal bus and the external bus, and finally consider the clock signal of the peripherals. Follow the principle of multiplying the frequency first as the CPU clock, and then dividing the frequency from the inside to the outside, and the lower level accommodates the upper level.  

 

 

Clock Control Register (RCC_CR)


31~26

25

24

23~20

19

18

17

16

reserve

PLLRDY

PLLON

reserve

CSSON

HSEBYP

HSERDY

HSEON


eg:RCC->CR|=0x00010000; //External high-speed clock enable HSEON

 RCC->CR|=0x01000000; //Enable PLLON

 RCC->CR>>25; //Wait for PLL to lock

Clock Configuration Register (RCC_CFGR)


31:27

26:24

23

22

21:18

17

16

reserve

MCO[2:0]

reserve

USBPRE

PLLMUL[3:0]

PLLXTPRE

PLLSRC

15:14

13:11

10:8

7:4

3:2

1:0

ADCPRE[1:0]

PPRE2[2:0]

PPRE1[2:0]

HPRE[3:0]

SWS[1:0]

SW[1:0]


 


Position 26:24

MCO: Microcontroller clock output

Set to '1' or cleared to 0 by software.

0xx: no clock output;

100: system clock (SYSCLK) output;

101: internal RC oscillator clock (HSI) output;

110: external oscillator clock (HSE) output;

111: PLL clock is divided by 2 and output.

Position 22

USBPRE: USB prescaler

Set to 1 or clear to 0 by software to generate a 48MHz USB clock. This bit must be valid before enabling the USB clock in the RCC_APB1ENR register. If the USB clock is enabled, this bit cannot be cleared.

0: PLL clock is divided by 1.5 times as USB clock

1: PLL clock is directly used as USB clock

Position 21:18

PLLMUL: PLL multiplication factor

The PLL multiplication factor is determined by software settings. It can only be written when the PLL is turned off.

Note: The output frequency of PLL cannot exceed 72MHz

0000: PLL 2x frequency output 1000: PLL 10x frequency output

0001: PLL 3x frequency output 1001: PLL 11x frequency output

0010: PLL 4x frequency output 1010: PLL 12x frequency output

0011: PLL 5x frequency output 1011: PLL 13x frequency output

0100: PLL 6x frequency output 1100: PLL 14x frequency output

0101: PLL 7x frequency output 1101: PLL 15x frequency output

0110: PLL 8x frequency output 1110: PLL 16x frequency output

0111: PLL 9x frequency output 1111: PLL 16x frequency output

Position 17

PLLXTPRE: HSE divider for PLL entry

Set to '1' or clear to '0' by software to divide HSE as PLL input clock. This bit can only be written when PLL is turned off.

0: HSE does not divide the frequency

1: HSE 2-way

Bit 16

PLLSRC: PLL input clock source (PLL entry clock source)

Set to '1' or clear to '0' by software to select the PLL input clock source. This bit can only be written when the PLL is turned off.

0: HSI oscillator clock is divided by 2 and used as PLL input clock

1: HSE clock is used as PLL input clock.

Position 15:14

ADCPRE[1:0]: ADC prescaler

Set to 1 or clear to 0 by software to determine the ADC clock frequency

00: PCLK2 divided by 2 is used as ADC clock

01: PCLK2 divided by 4 is used as ADC clock

10: PCLK2 divided by 6 is used as ADC clock

11: PCLK2 divided by 8 is used as ADC clock

Position 13:11

PPRE2[2:0]: APB high-speed prescaler (APB2)

Set to '1' or clear to '0' by software to control the prescaler factor of the high-speed APB2 clock (PCLK2).

0xx: HCLK is not divided

100: HCLK divided by 2

101: HCLK divided by 4

110: HCLK divided by 8

111: HCLK 16-division

Position 10:8

PPRE1[2:0]: APB low-speed prescaler (APB1)

Set to '1' or clear to '0' by software to control the prescaler factor of the low-speed APB1 clock (PCLK1).

Warning: The software must ensure that the APB1 clock frequency does not exceed 36MHz.

0xx: HCLK is not divided

100: HCLK divided by 2

101: HCLK divided by 4

110: HCLK divided by 8

111: HCLK 16-division

Position 7:4

HPRE[3:0]: AHB prescaler

Set to '1' or clear to '0' by software to control the pre-scaling factor of the AHB clock.

0xxx: SYSCLK is not divided

1000: SYSCLK divided by 2 1100: SYSCLK divided by 64

1001: SYSCLK divided by 4 1101: SYSCLK divided by 128

1010: SYSCLK divided by 8 1110: SYSCLK divided by 256

1011: SYSCLK divided by 16 1111: SYSCLK divided by 512

Position 3:2

SWS[1:0]: System clock switch status

Set to '1' or cleared to '0' by hardware to indicate which clock source is used as the system clock.

00: HSI is used as the system clock;

01: HSE is used as the system clock;

10: PLL output as system clock;

11: Not available.

Bit 1:0

SW[1:0]: System clock switch

Set to '1' or clear to '0' by software to select the system clock source.

00: HSI is used as the system clock;

01: HSE is used as the system clock;

10: PLL output as system clock;

11: Unavailable


eg: RCC->CFGR=0x00000400; //APB1=DIV2;APB2=DIV1 (no frequency division);AHB=DIV1 (no frequency division);

Set the clock process according to the STM32 library function:

RCC_DeInit(); //Set the RCC register to default value

RCC_HSEConfig(RCC_HSE_ON); //Turn on the external high-speed clock crystal

HSEStartUpStatus = RCC_WaitForHSEStartUp(); //Wait for the external high-speed clock crystal to work

if(HSEStartUpStatus == SUCCESS) //External ready

{

       //Add here PLL ans system clock config

       RCC_HCLKConfig(RCC_SYSCLK_Div1); //Set AHB clock to non-divided

       RCC_PCLK2Config(RCC_HCLK_Div1); //Set APB2 clock to non-divided

       RCC_PCLK1Config(RCC_HCLK_Div2); //Set APB1 clock frequency to 2

       RCC_ADCCLKConfig(RCC_PCLK2_Div6); //Set ADC clock frequency to six

       //Set the PLL clock to multiply the 8M clock by 9 times to 72M

RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);

RCC_PLLCmd(ENABLE); //Enable PLL

 

FlagStatus Status;

Status = RCC_GetFlagStatus(RCC_FLAG_PLLRDY);

if(Status == RESET)

{

       ……

}

RCC_SYSCLKConfig(RCC-SYSCLKSource_PLLCLK); //Set PLL output to system clock

while(RCC_GetSYSCLKSource()!=0x08) //Test whether PLL is used as system clock and wait for verification to complete

{}

}

else

{

       //Add here some code to deal with this error

}

// Enable the peripheral interface bus clock

RCC_APB2PeriphClockCmd() / RCC_APB1PeriphClockCmd()

 

 

 

Specific configuration process:

first step:

Reset and configure the vector table.

Function MYRCC_DeInit();

The following function is analyzed:

(1) Set the peripheral reset register: RCC->APB1RSTR = 0x00000000

This register contains the reset settings of peripherals such as DAC, power reset, timer, etc. A bit of 1 indicates that the corresponding peripheral is reset. The register data is cleared when the machine is powered on.

(2) Set the peripheral reset register: RCC->APB2RSTR = 0x00000000

Same as the first step of setting the peripheral reset register.

answer:

RCC->APB1RSTR = 0x00000000; //Reset ends     
RCC->APB2RSTR = 0x00000000;  
What does "reset ends" mean here? ? I commented it out and found that it can still run

1 is reset. 0 is of course not reset. If
not reset, then the reset is over.

(3) Sleep mode Flash and SRAM clocks are enabled, others are turned off. Used to use SRAM. SRAM is equivalent to the memory of a PC.

STm32 has three startup modes:

1. ISP mode. This mode is that after STM32 is reset, it executes the BOOTLOADER program that is fixed inside (it is fixed and we cannot read or write it.), and then waits for serial port data to realize the serial port bootloader function.
This mode will not start from the user storage area (unless it is controlled by the serial port to start from 0X08000000), so after updating the code, it needs to be set to other modes (FLASH mode). 
2. FLASH startup mode. This mode starts directly from 0X08000000, which is the startup method of the code we wrote ourselves. This should be used in normal situations. 
3. SRAM startup mode. I have not used this mode. It starts from 0X20000000, that is, before the sram mode starts, you must make sure that there is code in the SRAM, otherwise it will freeze.

 

RCC->AHBENR = 0x00000014

(4) Set the peripheral clock enable register:

RCC->APB1ENR = 0x00000000;

RCC->APB2ENR = 0x00000000; Turn off all peripherals

(5) Enable internal high-speed HSION.

RCC->CR |=0x00000001;

The clock startup process of stm32.
The startup process is: 
1. First use the internal clock (this is why you can download the code without connecting the crystal oscillator).
2. Try to turn on the external clock. 
3. If it is successfully turned on, use the external clock, otherwise use the internal clock. 
4. Do other things. 
Of course, you need to write the code to implement the above code yourself. Of course, the internal clock is the default clock, and you don’t have to turn it on.

(6) Reset SW, HPRE, PPRE1, PPRE2, ADCPRE, MCO

RCC->CFGR &= 0xF8FF0000;

What does this step mean? My understanding is that the Cfgr register is mainly used to control the clock division, see the figure below:

http://my.csdn.net/uploads/201204/15/1334498438_3253.JPG


Through the configuration of this step:

First, configure MCO to have no output. What is MCO? It means that the internal clock of stm32 can be output through the IO port pin. As shown in the figure above, there are four types of mco outputs for the configuration of cfgr, namely, output after dividing pllclk by two, hsi (on-chip clock) output, etc.

Secondly: configure ADCPRE is the ADC of the AHB divider line surface in the above figure

Next: configure ppre2, which is the high-speed external clock APB2. Set it to non-divided frequency. The high-speed external clock mainly drives some high-speed peripherals. This is introduced in the APB2ENR clock control register.

Again: configure PPRE1, configure the low-speed external clock division, and set APB1 to no division.

Again: configure HPRE. These bits are mainly used to configure the frequency division coefficient of the AHB register. Here it is also set to no frequency division. That is to say, the SYSCLK in the above figure is not divided by AHB.

Finally: configure SW and SWS. This means that HIS is enabled as the system clock.

At this point, after analysis, we know that RCC->CFGR &= 0xF8FF0000; is mainly used to configure the settings of various dividers such as ahb, and to use the on-chip clock as the internal clock of the system.

(6) Close HSEON, CSSON, PLLON

RCC->CR &= 0xFEF6FFFF;

By analyzing the CR register, we can see that this register mainly involves three clocks: PLL, CSS, and HSE.

(7) Reset HSEBYP.

RCC->CR &= 0xFFFBFFFF; What is the purpose of this step? According to page 57 of the data sheet, the external clock source HSE has two modes. When HSEBYP is set to 0, the external crystal is selected as the external clock source. This clock is more accurate and of course it is related to the external circuit. Of course, because HSEON has been set to off in step (6), HSEBYP can be set freely in this step.

(8)       复位PLLSRC,PLLXTPRE,PLLMUL and USBPRE

RCC->CFGR &= 0xFF80FFFF;

Note: In this section you may have questions like:

RCC->CFGR &= 0xFF80FFFF;
PLLSRC=0 The HSI oscillator clock is divided by 2 and used as the PLL input clock
PLLXTPRE=0, the HSE divider is used as the PLL input, and the HSE is not divided
. Is there no conflict?

The answer is: the last configuration shall prevail. That is, the last configuration will change the previous configuration, so the last configuration shall prevail.

That is to say, there are other codes that define it later. So why do we need to repeat the configuration?

Sometimes it is useful. For example, if you want to overclock the stm32 for a while and then resume normal operation, this is useful.

(9) Disable all interrupts

RCC->CIR = 0x00000000;

(10) Configuration vector table

#ifndef VECT_TAB_RAM

 MY_NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);

#else

 MY_NVIC_SetVectorTable(NVIC_VextTab_FLASH,0x0);

#endif

 

The following is an analysis of the function:

//Function: Set the vector table offset address

//NVIC_VectTab: base address

//Offset: offset

void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)  

   //Check parameter validity
 assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
 assert_param(IS_NVIC_OFFSET(Offset));    
 SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80); //Set NVIC vector table offset register
 //Used to identify whether the vector table is in the CODE area or the RAM area
}
The first two lines are used to check the parameter validity, which will not be analyzed here. Focus on the third line

What is the use of configuring this vector table? See the explanation of the vector table on page 113 of the CortexM3 Definitive Guide

here

#define NVIC_VectTab_RAM             ((u32)0x20000000)

#define NVIC_VectTab_FLASH           ((u32)0x08000000)

The value of Offset is 0x0, which is the offset address. The address must be divisible by 64 * 4 = 256. For details, please refer to page 113 of the authoritative manual.

 SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//Set the NVIC vector table offset register. The questions are as follows:

SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80); //Set the vector table offset register of NVIC.
Since it is to set the vector table offset of NVIC, why do we need to OR it with NVIC_VectTab? Isn't it enough to just set OFFSET? In addition, only BIT [28:7] of VTOR setting is effective. There won't be enough space for so many bits after ORing, right?

This is the base address. 
For 7~28, can you define a 28-bit data?

VTOR setting only has BIT [28:7]. Check if (u32) 0x1FFFFF80 is [28:7] in binary format.
Then read the following paragraph:


   On page 104 of the <>, there is this paragraph:
    There is a register in the NVIC called the "vector table offset register" (at address 0xE000_ED08), and the vector table can be located by modifying its value. But it must be noted that there are requirements for the starting address of the vector table: you must first find out how many vectors there are in the system, and then increase this number to an integer power of 2, and the starting address must be aligned to the latter's boundary. For example, if there are 32 interrupts in total, there are 32+16 (system exceptions) = 48 vectors in total, and the value after increasing to an integer power of 2 is 64, so the address
must be divisible by 64*4=256, so the legal starting address can be: 0x0, 0x100, 0x200, etc.
    The vector table offset register, that is, SCB->VTOR. Its 29th bit is used to identify whether the vector table is in the CODE area or the RAM area, so 0X1, that is, the highest 3 bits are not moved, which is easy to understand. But the lower bits, according to the understanding of the above paragraph, STM32 has 60 interrupts, plus 16 of CM3, a total of 76 interrupts, expanded to the power of 2, that is 128, and then multiplied by 4, get 512, that is 0X200. According to this calculation, the legal offset address should be 0X0, 0X200, 0X400, 0X600... Therefore, it should be &0X1FFF FE00 here.
    The above is my understanding. In fact, it is &0X1FFF FF80; I also have doubts about this.

Answer: The authoritative guide of cortex-m3 says that bit 28-7 is the starting address of the vector table. So the lower 7 bits are not used, so &0X80 is used to clear the lower 7 bits. But here, writing &0X1FFF FE00 can also achieve the purpose of clearing. As for the address must be an integer of 512, just pay attention to the parameter offset.

 

Let's go back to the Stm32_Clock_Init() function on page 61 of the book STM32:

After the above configuration is completed, start configuring the external clock.

The current implementation of the MinisTM32 development board uses a high-speed external clock as the clock source. After MYRCC_Deinit(), the external clock source is turned off first, and then after cfgr is reconfigured, the high-speed external clock is ready to be turned on.

(11) RCC->CR |= 0x00010000; external high-speed clock enables HSEON. As mentioned earlier, the last setting is used as the reference, so from this step on, HSE is used as the external clock.

(12) Wait for the external clock to be ready

While(!(RCC->CR>>17)); (Actually, the effect of this step is the same as while(RCC->CR&(u32)(1<<17));, because bits 18 to 31 in MYRCC_Deinit() are all 0. Of course, in the forum http://www.openedv.com/posts/list/1943.htm, the 23rd post also admitted that While(!(RCC->CR>>17) is a bit rash to write like this. The 23rd post wrote

In this regard, Atom also said that it is more appropriate to write (RCC-CR>>17)&0X01, but I feel that RCC-CR>>17 is inaccurate. For example, if the 18th bit is 1, then after shifting right by 17 bits, regardless of whether the clock is ready, the result of the expression "RCC-CR>>17" is always true. In this case, while (! (RCC-CR>>17)) is meaningless, right? So writing (RCC-CR>>17)&0X01 is the most accurate.

)

(13) Configure APB1/2 = DIV2 and AHB = DIV1

RCC->CFGR = 0x00000400;

(14) Set PLL frequency division

PLL -=2;

RCC->CFGR = PLL <<18;

Set PLL 9x

There is also a problem involved here, as follows

Actually, here today Lin Meimei asked a more professional question, that is, PLL is a u8 data type, why can it be right shifted 18 bits here? Isn't it already exceeded? Actually, we can understand it by looking at the assembly code, the assembly code is as follows: 219: RCC->CFGR|=PLL<<18; //Set PLL value 2~16 0x08000618 4608 MOV r0,r1 0x0800061A 6840 LDR r0,[r0,#0x04] 0x0800061C EA404084 ORR r0,r0,r4,LSL #18 0x08000620 6048 STR r0,[r1,#0x04] As you can see, this shift operation is performed in R0 and R1. Both r0 and r1 are 32-bit registers, so the shift operation here will not cause an error (the result is assigned to the 32-bit register: RCC->CFGR).

(15) FLASH->ACR |= 0x32 //flash 2 delay cycles. FLASH->ACR|=0x32 is to make the frequency match.

//For details, see "STM32 Flash Programming"

(16) Open PLLON

RCC->CR|=0x01000000;

(17) Waiting for PLL to lock

while(!((RCC->CR>>25)&0x01));

(18) PLL as system clock

RCC->CFGR |= 0x00000002;

(19) Wait for PLL to be successfully set as system clock

Unsigned char Temp = 0;

While(Temp!=0x02)

{

   Temp = RCC->CFGR>>2;

   Temp &= 0x03;

}

In fact, this code is to judge SWS and wait for the system clock to be successfully converted to PLL clock.

 

Combined with the above analysis, it is clear that the STM32 clock is always configured. The main flow chart is as follows:

In fact, I personally feel that there are some unnecessary configurations of the routines in mini32, so I changed some of them myself and found that it can also run in the marquee program. Currently, I have only tested it in the marquee program:

 

first step:

     RCC->APB1RSTR = 0x00000000; //Reset ends                  

     RCC->APB2RSTR = 0x00000000;

Step 2:

    RCC->AHBENR = 0x00000014; //Sleep mode flash and SRAM clock enable. Others are off.

Step 3: Turn off all peripheral clocks

    RCC->APB2ENR = 0x00000000; //Peripheral clock is turned off.                    

    RCC->APB1ENR = 0x00000000; 

Why is this step necessary? Because when configuring registers such as cfgr and cr, some peripheral clocks need to be turned off.

the fourth step:

  RCC->CR &= 0xFEF2FFFF; //The main function of this patch is to turn on the internal HSION and turn off HSE, CSS, PLLON

Step 5: Set the frequency division register, configure the frequency division, and enable PLLSRC ON

 

RCC->CFGR=0X00000400; //APB1/2=DIV2;APB2=DIV1;AHB=DIV1; According to the Chinese manual,

The maximum of apb1 is 36MHZ, so it needs to be divided here. Because after this setting, the output of PLLMUL is 72MHZ, so here we need to make APB1/2=DIV2 which is 36MHZ.

PLL-=2; //Offset 2 units

RCC->CFGR|=PLL<<18; //Set PLL value 2~16 Set PLL to 9 times frequency

RCC->CFGR|=1<<16; //PLLSRC ON sets HSE as the input clock. Because the 17th bit of cfgr is also 0, the HSE input to PLLSRC is 8M

 

At this time, hse is 8MHZ. Obviously, after the 9-times multiplication above, the SYSCLK output to AHB is 72MHZ. Because AHB is set to not divide the frequency, the AHB output is also 72MHZ. Apb1 is divided before, so the output is 36MHZ. Apb2 is 72MHZ

 

Step 7:

FLASH->ACR|=0x32; //FLASH 2 delay cycles

Step 8:

     RCC->CIR = 0x00000000; //Disable all interrupts

Step 9:

     //Configure vector table                        

#ifdef  VECT_TAB_RAM

     MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else  

     MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //The flash is used here to start

#endif

Step 10:

     RCC->CR|=0x00010000; //External high-speed clock enables HSEON. Note that the external clock cannot be the system clock directly or indirectly before enabling hseon. That is to say, the SW bit in cfgr is 0 first. Because it has been set to 0 in the fifth step, there is no need to worry about it here.

     while(!(RCC->CR>>17));//Wait for external clock to be ready

Step 11: Turn on the PLL.

     RCC->CR|=0x01000000;  //PLLON

     while(!(RCC->CR>>25));//Wait for PLL to lock

Step 12:

     RCC->CFGR|=0x00000002; //PLL as system clock      

     while(temp!=0x02) //Wait for PLL to be successfully set as system clock

     {  

            temp=RCC->CFGR>>2;

            temp&=0x03;

     }

 /*The above code is a bit messy, let's combine the code to make it easier to read*/

Combined with the clock configuration process of Stm32_Clock_Init(), I summarize the clock configuration as follows:

turn off all peripheral clocks,
(1) enable HSI and turn off HSE, PLL, CSS, configure the frequency division register, and set the system clock to HSI in crgr.
(2) Turn off all interrupts.
(3) Configure the vector table.
(4) Enable HSE and wait for the setting to be completed in CR.
(5) Turn on PLL and wait for PLL to turn on in CR.
(6) Wait for PLL to become the system clock in sws bit in cfgr.


Combined with the above methods, the code I rewrote is as follows:
void Stm32_Clock_Init111(u8 PLL)
{

 unsigned char temp=0;  
 RCC->APB1RSTR = 0x00000000;//Reset endsRCC-    
 >APB2RSTR = 0x00000000; 
   
 RCC->AHBENR = 0x00000014; //Sleep mode flash and SRAM clock enable. Others are turned off.   
 RCC->APB2ENR = 0x00000000; //Peripheral clock is turned off.      
 RCC->APB1ENR = 0x00000000;   
 
 RCC->CR &= 0xFEF2FFFF; //The main function of this step is to turn on the internal HSION and turn off HSE, CSS, PLLON                  
 
 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; HSE is set to non-divided frequency. The main function of CFGR is to configure the frequency division. Before the frequency division, of course, all HSE clocks in cr should be turned off and only the HSI clock should be turned on. Of course, another important function is to set which one is currently used as the system clock, that is, the SW bit.


 PLL-=2; //Offset 2 units
 RCC->CFGR|=PLL<<18; //Set PLL value 2~16
 RCC->CFGR|=1<<16; //PLLSRC ON

 FLASH->ACR|=0x32; //FLASH 2 delay cyclesRCC-
       
 >CIR = 0x00000000; //Turn off all interrupts
 //Configure vector table      
#ifdef VECT_TAB_RAM
 MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else   
 MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //Flash startup is used here
#endif
   
 RCC->CR|=0x00010000; //External high-speed clock enable HSEON
 while(!(RCC->CR>>17));//Wait for external clock to be readyRCC-
 >CR|=0x01000000; //PLLON
 while(!(RCC->CR>>25));//Wait for PLL to lock
 RCC->CFGR|=0x00000002;//PLL as system clock  
 while(temp!=0x02) //Wait for PLL to be set as system clock successfully
 {   
  temp=RCC->CFGR>>2;
  temp&=0x03;
 }
     
}


Keywords:STM32 Reference address:Learning STM32 (3) - Power supply, clock, reset circuit

Previous article:About BOOT0 and BOOT1 of STM32
Next article:How to start stm32 boot0 boot1

Recommended ReadingLatest update time:2024-11-16 09:28

51 single chip electronic calendar (adjustable with temperature) DS1302 clock + 12864 LCD display
The 51 MCU display time (adjustable) (DS1302 clock + 12864 LCD display) can be connected according to the program. The simulation schematic diagram is as follows: The MCU source program is as follows: /********************************************/ /* Electronic calendar with temperature display */ /***************
[Microcontroller]
51 single chip electronic calendar (adjustable with temperature) DS1302 clock + 12864 LCD display
STM32 study notes: standby wake-up
1. Brief Introduction 1.1 Low power mode: After a system or power reset, the microcontroller is in the running state. When the CPU does not need to continue running, you can use a variety of low-power modes to save power, such as: waiting for an external event, the common key wake-up. The user needs to select the b
[Microcontroller]
STM32 study notes: standby wake-up
STM32-Analysis of GPIO related functions in HAL library
background: I have been studying the HAL library recently, and summarized the knowledge points of GPIO related functions of the HAL library in STM32. content: The GPIO related registers are defined in the stm32l152xb.h header file. The GPIO functions described below will call these registers. The structure definition
[Microcontroller]
Single chip electronic clock class design assembly language code and proteus simulation
  MCU assembly language source code: ORG 0000H AJMP MAIN ORG 000BH LJMP INTT0 ORG 0030H MAIN: MOV SP,#60H ; establish stack area MOV PSW,#00H MOV R0,#20H ; RAM area first address MOV R7,#5FH ; Number of RAM area units QL: MOV @R0,#00H ; RAM clear         INC R0 DJNZ R7,QL MOV IP,#02H ;IP initialization, priorit
[Microcontroller]
Single chip electronic clock class design assembly language code and proteus simulation
Solution to the problem that the STM32 I/O port cannot output high and low levels normally
The I/O port cannot output normally because the port is reused. In addition to checking whether there is a program to reuse the port in the program, you should also pay attention to the following: some ports are reused by default when the microcontroller is powered on, such as the PA13, PA14, PA15, PB3, and PB4 pins r
[Microcontroller]
Solution to the problem that the STM32 I/O port cannot output high and low levels normally
PWM on STM32
        At yesterday's sharing session in the laboratory embedded group, I explained some knowledge about PWM, external interrupts and timers. In the process of organizing knowledge points and making PPTs, I also summarized my knowledge, so I plan to write three blogs to record these three knowledge points. I will use
[Microcontroller]
PWM on STM32
Problems encountered by STM32 UART4 and UART5
       I'm writing a human-machine interface recently. Due to the layout problem of my hardware colleagues, I have to use serial port 4. At first I thought it was nothing, just changing USART1 to 4 and turning on the clock and configuring the pins.        But it turns out that my idea is stupid. After 2 days of debu
[Microcontroller]
Overview of STM32 GPIO registers
A GPIO register is generally divided into three categories: a. control register; b. data register; c. latch register A. Control register (GPIO_CRL or GPIO_CRH (CRL corresponds to the lower 8 bits, CRH corresponds to the upper 8 bits)). See page 106 of the manual for details. CNFx MODE XX00-----Input mode (generally n
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号