STM32-System Clock

Publisher:平安宁静Latest update time:2017-10-26 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1. STM32 clock system

In STM32, there are 5 clock sources, namely HSI, HSE, LSI, LSE, PLL

(1) HSI is a high-speed internal clock, RC oscillator, with a frequency of 8MHz;

(2) HSE is a high-speed external clock that can be connected to a quartz/ceramic resonator or an external clock source. The frequency range is 4MHz – 16MHz.

(3) LSI is a low-speed internal clock, RC oscillator, with a frequency of 40KHz;

(4) LSE is a low-speed external clock connected to a quartz crystal with a frequency of 32.768KHz;

(5) PLL is a phase-locked loop frequency multiplication output. Strictly speaking, it is not an independent clock source. The input of PLL can be connected to HSI/2, HSE or HSE/2. The frequency multiplication can be selected from 2 to 16 times, but the maximum output frequency cannot exceed 72MHz.

The 40kHz LSI is used by the independent watchdog IWDG, and 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 STM32 has a full-speed USB module, and its serial interface engine requires a 48MHz clock source. This clock source can only be obtained from the PLL, which can be divided by 1.5 or 1. That is, when the USB module is used, the PLL must be enabled and the clock must be configured to 48MHz or 72MHz.

In addition, the STM32 can also select a clock signal to output to the MCO pin (PA.8), which can be selected as the 2-division output of the PLL, 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 be divided by 1, 2, 4, 8, 16, 64, 128, 256, or 512. The clock output by the divider is sent to five modules:

(1) HCLK clock sent to AHB bus, core, memory and DMA;

(2) The system timer clock is sent to Cortex after being divided by 8;

(3) The idle running clock FCLK sent directly to Cortex;

(4) Sent to the APB1 divider. The APB1 divider can select 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 multiplier. The frequency multiplier can select 1 or 2 frequency multiplication, and the clock output is used by timers 2, 3, and 4.

(5) Sent to the APB2 divider. The APB2 divider can select 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) for 1x frequency. The frequency multiplier can select 1 or 2 times, and the clock output is used by Timer 1. In addition, the APB2 divider has another output for the ADC divider, which is sent to the ADC module after division. The ADC divider can be selected to be 2, 4, 6, or 8 frequency divisions.

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 working clock of the USB module should be provided by APB1.

The devices connected to APB2 (high-speed peripherals) are: UART1, SPI1, Timer1, ADC1, ADC2, GPIOx (PA~PE), and the second function IO port.


2. Initialization of STM32 clock

Since the development board has an external 8MHz crystal oscillator, the HSE clock will be used. In the MDK compilation platform, the program's clock setting parameter process is as follows:

(1) Reset the RCC register to the default value: RCC_DeInit;

(2) Turn on the external high-speed clock crystal oscillator HSE: RCC_HSEConfig(RCC_HSE_ON);

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

(4) Set AHB clock (HCLK): RCC_HCLKConfig;

(5) Set high-speed AHB clock (APB2): RCC_PCLK2Config;

(6) Set the low-speed AHB clock (APB1): RCC_PCLK1Config;

(7) Set PLL: RCC_PLLConfig;

(8) Enable PLL: RCC_PLLCmd(ENABLE);

(9) Wait for PLL to work: while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

(10) Set the system clock: RCC_SYSCLKConfig;

(11) Determine whether PLL is the system clock: while(RCC_GetSYSCLKSource() != 0x08);

(12) Turn on the peripheral clock to be used: RCC_APB2PerphClockCmd()….

For detailed usage of some functions, please refer to "STM32 Firmware Library User Manual V10"

3. SysTick Timer

In NVIC, there is a SysTick timer bundled, which is a 24-bit countdown timer. When it counts to 0, it will automatically reload the timing initial value from the RELOAD register and continue counting. At the same time, the internal COUNTFLAG flag will be set to trigger an interrupt (if the interrupt is enabled). As long as its enable bit in the SysTick control and status register is not cleared, it will not stop. Cortex-M3 allows two clock sources to be selected for SysTick. The first is the core's "free running clock" FCLK. "Free" means that it does not come from the system clock HCLK, so when the system clock stops, FCLK can continue to run. The second is an external reference clock, but when using an external clock, because it is sampled internally by FCLK, its period must be at least twice that of FCLK (sampling theorem).

The following is an introduction to SysTick in STM32, which belongs to the NVIC control part and has a total of 4 registers:

STK_CSR, 0xE000E010: Control register

STK_LOAD, 0xE000E014: Reload register

STK_VAL, 0xE000E018: Current value register

STK_CALRB, 0xE000E01C: Calibration value register

 

First look at the STK_CSR control register, there are 4 bits with meaning:

Bit 0: ENABLE, SysTick enable bit (0: turn off SysTick function, 1: turn on SysTick function);

Bit 1: TICKINT, SysTick interrupt enable bit (0: disable SysTick interrupt, 1: enable SysTick interrupt);

Bit 2: CLKSOURCE, SysTick clock selection (0: use HCLK/8 as the clock source, 1: use HCLK);

The third is: COUNTFLAG, SysTick count comparison flag. If SysTick has counted to 0 after the last read of this register, this bit is 1. If this bit is read, it is automatically cleared.

STK_LOAD reload register:

Systick is a decrementing timer. When the timer decrements to 0, the value in the reload register will be reloaded and continue to decrement. STK_LOAD reload register is a 24-bit register with a maximum count of 0xFFFFFF.

STK_VAL current value register:

This is also a 24-bit register. When read, it returns the current countdown value. Writing it clears it to zero and also clears the COUNTFLAG flag in the SysTick control and status register.

STK_CALRB calibration value register:

It contains a TENMS field, but the specific information is unknown. It is not used for the time being.

In the MDK development environment, we do not have to operate every register. We can perform related operations by calling functions in the ST function library. The steps are as follows:

(1) Call SysTick_CounterCmd() to disable the SysTick counter

(2) Call SysTick_ITConfig() to disable SysTick interrupt

(3) Call SysTick_CLKSourceConfig() to set the SysTick clock source

(4) Call SysTick_SetReload() to set the SysTick reload value

(5) Call NVIC_SystemHandlerPriorityConfig() to set the SysTick timer interrupt priority

(6) Call SysTick_ITConfig() to enable SysTick interrupt

(7) Write the interrupt service function under SysTickHandler() in stm32f10x_it.c.

(8) Call SysTick_CounterCmd() to start the SysTick counter when needed

 

4. Engineering Implementation

According to the above description, we are going to do a small experiment using the LED lights on the development board. We will slightly improve the first marquee experiment and light up the LED lights sequentially with a precise delay of 1s. The timer used is SysTick.

The design idea is to configure the various parameters of the system first, then set the SysTick timer to enter an interrupt every 1ms, then define a global variable as a parameter for the timing length, and then assign the parameters obtained from the delay function to this global variable. Every time an interrupt is entered, the global variable is reduced once until it is reduced to 0, and then the delay function is exited.

1. Configure the system clock

void RCC_cfg()

{

       //Define error status variable

       ErrorStatus HSEStartUpStatus;

      

       //Reset the RCC register to the default value

       RCC_DeInit();

 

       // Turn on the external high-speed clock crystal

       RCC_HSEConfig(RCC_HSE_ON);

 

       //Wait for the external high-speed clock crystal to work

       HSEStartUpStatus = RCC_WaitForHSEStartUp();

       if(HSEStartUpStatus == SUCCESS)

       {

              //Set AHB clock (HCLK) as system clock

              RCC_HCLKConfig(RCC_SYSCLK_Div1);

 

              //Set the high-speed AHB clock (APB2) to HCLK clock

              RCC_PCLK2Config(RCC_HCLK_Div1);

 

              //Set the low-speed AHB clock (APB1) to 2 times the frequency of HCLK

              RCC_PCLK1Config(RCC_HCLK_Div2);

             

              //Set FLASH code delay

              FLASH_SetLatency(FLASH_Latency_2);

 

              // Enable prefetch cache

              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

              //Set the PLL clock to 9 times the HSE frequency 8MHz * 9 = 72MHz

              RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

 

              // Enable PLL

              RCC_PLLCmd(ENABLE);

 

              //Wait for PLL to be ready

              while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

 

              //Set PLL as system clock source

              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

              //Judge whether PLL is the system clock

              while(RCC_GetSYSCLKSource() != 0x08);

       }

 

       //Turn on PB and PD to light up the LED

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD, ENABLE);

}

    The NVIC function is used, so stm32f10xR.lib needs to be added to the project.

2. Configure the SysTick timer

void SysTick_cfg()

{

       //Set the disabled SysTick timer

       SysTick_CounterCmd(SysTick_Counter_Disable);

 

       //Set to disable SysTick interrupt

       SysTick_ITConfig(DISABLE);

 

       //Set the SysTick clock source to AHB clock

       SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

 

       //Set the reload value. Since SysTick is the AHB clock, which is 72MHz, the reload value is set to 72000, which means it will be reloaded every 1ms.

       SysTick_SetReload(72000);

 

       //Set the SysTick timer interrupt priority

       NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 1, 0);

 

       //Set to enable SysTick interrupt

       SysTick_ITConfig(ENABLE);

}

 

3. Write a delay function

void Delay(u32 nTime)

{

       TimingDelay = nTime;

 

       // Enable SysTick timer

       SysTick_CounterCmd(SysTick_Counter_Enable);

 

       //Loop waiting for the timer to expire

       while(TimingDelay != 0);

 

       //Disable SysTick timer

       SysTick_CounterCmd(SysTick_Counter_Disable);

 

       // Clear the SysTick timer

       SysTick_CounterCmd(SysTick_Counter_Clear);

}

 

4. Set the general IO port

void GPIO_cfg()

{

       GPIO_InitTypeDef GPIO_InitStructure; //Define GPIO macro operation structure

 

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                               

       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Configure port B5 as general push-pull output

       GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz; //Port line flip speed is 50MHz

       GPIO_Init(GPIOB, &GPIO_InitStructure); // Place GPIOB port

      

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_3; //Configure D3 and D6 ports as push-pull output

       GPIO_Init(GPIOD, &GPIO_InitStructure); // Place GPIOD port

}

5. Interrupt service function

void SysTickHandler(void)

{

       TimingDelay--;

}

The global variable TimingDelay needs to be declared in stm32f10x_it.c when used, otherwise it cannot be used. The declaration statement is:

extern vu32 TimingDelay;

The global variable TimingDelay is always checked in the delay program, and the delay function is exited only when it is reduced to 0.

6. Main program

#include "stm32f10x_lib.h"

 

vu32 TimingDelay;

void RCC_cfg();

void SysTick_cfg();

void Delay(u32 nTime);

void GPIO_cfg();

 

int main()

{

       RCC_cfg(); //Configure RCC clock

       SysTick_cfg(); //Configure SysTick timer

       GPIO_cfg(); // General IO port configuration

 

       while(1)

       {

              GPIO_ResetBits(GPIOB, GPIO_Pin_5);

              GPIO_ResetBits(GPIOD, GPIO_Pin_6);

              GPIO_SetBits(GPIOD, GPIO_Pin_3);

             

              Delay(1000); //Delay 1s

             

              GPIO_ResetBits(GPIOB, GPIO_Pin_5);

              GPIO_ResetBits(GPIOD, GPIO_Pin_3);

              GPIO_SetBits(GPIOD, GPIO_Pin_6);

             

              Delay(1000);

                           

              GPIO_SetBits(GPIOB, GPIO_Pin_5);                            

              GPIO_ResetBits(GPIOD, GPIO_Pin_6);                     

              GPIO_ResetBits(GPIOD, GPIO_Pin_3);                  

 

              Delay(1000);                                    

       }

             

}

    Any 32-bit integer can be filled in the parameter of the delay function Delay, and the delay unit is ms.


Keywords:STM32 Reference address:STM32-System Clock

Previous article:STM32 - PWM generation
Next article:STM32-Interrupt Application

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号