【I. Introduction
- When programming STM32 front-end and back-end programs, the most basic configuration should be the configuration of its clock and system timer. For the standard library, call SysTick_Init ();. If the HAL library is used, HAL_Init() should be called first; to initialize the HAL library.
- The standard library is used here.
[2] STM32 clock configuration
1 Overview
- The clock controller in RCC (Reset Clock Controller) mainly focuses on the clock tree.
- General configuration: PCLK2 (APB2 peripheral)=HCLK (SDIO peripheral clock only)=SYSCLK (system clock)=PLLCLK=72MHz, PCLK1=HCLK/2=36MHz.
- Explanation of various clocks:
Note 1: HSE (High speed external clock): High speed external clock. Provided by external crystal oscillator through OSC_IN and OSC_OUT. If it is a passive crystal oscillator, connect two pins; if it is an active crystal oscillator, connect it to OSC_IN, and the other one is left floating. Generally, a passive crystal oscillator of 8MHz is used.
Note 2: LSE (Low speed external clock): Low speed external clock. Provided by the external crystal oscillator through OSC32_IN and OSC32_OUT, generally 32.768KHz, provides the clock of the RTC.
Note 3: HSI (High speed internal clock): High speed internal clock, 8MHz, can be used as a backup. When the HSE fails, when the CSS and CSS interrupts are enabled, the HSI can provide the system running clock, but the maximum can only be 64MHz.
Note 4: LSI (Low speed internal clock): Low speed internal clock, 40KHz, provided for independent watchdog.
Note 5: PLL (phaselocked loop): phase-locked loop frequency multiplication output. Provided by HSE or HSI/2, it can be set to 2~16 times of output. Generally, the HSE path is selected, and the frequency is 9 times (72MHz).
1.PCLK2 (Peripheral Clock 2): The clock of APB2 (Advanced Peripheral Bus, Advanced Peripheral Bus), the clock provided to peripherals, such as GPIO/USART1/SPI1, etc. Generally set to a frequency division, 72MHz.
2. HCLK (High Performance Clock): The clock of AHB (Advanced High Performance Bus, advanced high-performance bus), the clock provided to the AHB bus, core memory, DMA, etc., can be obtained by dividing the frequency by the AHB prescaler.
3.PCLK(Peripheral Clock): Peripheral bus clock, which is low-rate, provided to USART2/3/4/5, SPI2/3, IIC1/2, etc.
Functions about system clock configuration exist in the library function system_stm32f10x.c.
2. Clock configuration
- For the standard library, if a clock frequency is defined, the system will initialize the clock frequency by default.
In system_stm32f10x.c:
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
#endif
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */
uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */
#endif
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#endif
As can be seen from these three pieces of code, if SYSCLK_FREQ_72MHz is defined, the SetSysClockTo72(void); function will be called. See the function description of this function below:
/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
……
In summary, the system clock can be set by defining the clock frequency, which are all functions that have been written by the standard library.
3. Clock output
Configure PA8 multiplexing as MCO pin output:
void MCO_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
[3] STM32 SysTick system timer configuration
- SysTick is the core peripheral of CM3. It is a 24-bit down-counter, and each count time is 1/SYSCLK, which is 1/72000000.
- Calculation of SysTick count time: t=reload value*1/AHB clock frequency. 1/AHB clock frequency is the time to count once. Generally, the reload value is set as 72000000/100000=720, then 10us is interrupted once; generally it is not set as 1us interrupt once, so the interrupt frequency is too high, and the program center of gravity is shifted.
- Timer configuration steps:
1. Initialization:
/**
* @brief 启动系统滴答定时器SysTick
* @param none
* @retval none
*/
void SysTick_Init( void )
{
/* SystemFrequency / 1000 1ms
* SystemFrequency / 100000 10us
* SystemFrequency / 1000000 1us
*/
if ( SysTick_Config(SystemCoreClock / 100000) )
{
/* Capture error */
while (1);
}
//关闭滴答定时器
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
2. Timing function:
/**
* @brief 10us延时程序
* @param
* @arg nTime: Delay_10us( 1 ) 为10us
* @retval none
*/
void Delay_10us( __IO u32 nTime )
{
TimingDelay = nTime;
//使能滴答定时器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while( TimingDelay != 0 );
}
3. Interrupt service function:
static __IO u32 TimingDelay = 0;
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
/**
* @brief 获取节拍程序,10us减1
* @param none
* @retval none
* @attention 在SysTick_Handler()中调用
*/
void TimingDelay_Decrement(void)
{
if ( TimingDelay != 0x00 )
{
TimingDelay --;
}
if(TimeLapseflag != 0x00)
{
TimeLapseflag --;
}
}
- Another microsecond-level timing programming:
void SysTick_Delay_Us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i<us;i++)
{
//当计数器的值减到0时,CTRL寄存器的位16会置1
while(!((SysTick->CTRL)&(1<<16)));
}
SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
In the same way, you can write ms-level timing programs.