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.
Previous article:STM32 - PWM generation
Next article:STM32-Interrupt Application
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Industry first! Xiaopeng announces P7 car chip crowdfunding is completed: upgraded to Snapdragon 8295, fluency doubled
- P22-009_Butterfly E3106 Cord Board Solution
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Anlu SparkRoad Development Board Review (7) MCU Soft Core IP Trial
- A DSP debugging and direct code generation method based on Matlab
- [Technical Tips] Power Supply PCB Design Skills and Case Analysis
- FPGA_100 Days Journey_VGA Design.pdf
- MakeCode graphical programming supports USB HID function
- EEWORLD University-How to improve the performance and reliability of motor drive and inverter applications? Introducing two simple and efficient methods
- The latest weekly evaluation intelligence, EE Evaluation Intelligence Bureau reports for you
- Pure hardware AC constant resistance load and INA related issues
- [FS-IR02 + D1CS-D54] - 1: Assembly (unique line color + unique labeling)
- [TI recommended course] #TI mid-power audio amplifier development software PurePath Console 3 detailed explanation#