STM32时钟配置与SysTick配置_基于STM32F103
程序员文章站
2022-03-13 17:31:54
...
【一】前言
- STM32前后台程序编程时,最基本的配置应当是对其时钟和系统定时器的配置,对标准库而言,调用SysTick_Init ();。如果采用HAL库,首先还应该调用HAL_Init();初始化HAL库。
- 此处采用标准库。
【二】STM32时钟配置
1、概述
- RCC(Reset Clock Controller)中时钟控制器,主要关注时钟树。
- 一般配置:PCLK2(APB2外设)=HCLK(SDIO外设时钟只能)=SYSCLK(系统时钟)=PLLCLK=72MHz,PCLK1=HCLK/2=36MHz。
- 各类时钟解释:
注1:HSE(High speed external clock):高速外部时钟。由外部晶振通过OSC_IN和OSC_OUT提供。如果是无源晶振,接两根引脚;如果是有源晶振,接OSC_IN,另一根悬空。一般采用8MHz的无源晶振。
注2:LSE(Low speed external clock):低速外部时钟。由外部晶振通过OSC32_IN和OSC32_OUT提供,一般为32.768KHz,提供RTC的时钟。
注3:HSI(High speed internal clock):高速内部时钟,8MHz,可备用,当HSE故障时,开启CSS和CSS中断的情况下,HSI可提供系统运行时钟,但最高只能是64MHz。
注4:LSI(Low speed internal clock):低速内部时钟,40KHz,提供给独立看门狗。
注5:PLL(phaselocked loop):锁相环倍频输出。由HSE或HSI/2提供,可设置2~16倍输出,一般选用HSE路径,9倍频(72MHz)。
1.PCLK2(Peripheral Clock 2):APB2(Advanced Peripheral Bus,高级外围总线)的时钟,提供给外设的时钟,如GPIO/USART1/SPI1等。一般设置为一分频,72MHz。
2.HCLK(High Performance Clock):AHB(Advanced High Performance Bus,高级高性能总线)的时钟,提供给AHB总线、核心存储器、DMA等的时钟,可通过AHB预分频器分频得到。
3.PCLK(Peripheral Clock):外设总线时钟,属于低速率的,提供给USART2/3/4/5、SPI2/3、IIC1/2等。
关于系统时钟配置的函数存在于库函数system_stm32f10x.c中。
2、时钟配置
- 对标准库来说,如果定义了时钟频率,则系统会默认初始化该时钟频率。
在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
这三段代码可以看出,定义了SYSCLK_FREQ_72MHz,则会调用SetSysClockTo72(void);函数。以下看该函数的功能描述:
/**
* @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
*/
……
综上,可以通过定义时钟频率来设置系统的时钟,都是标准库已经写好的函数。
3、时钟输出
配置PA8复用为MCO引脚输出:
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);
}
【三】STM32 SysTick系统定时器配置
- SysTick是CM3的内核外设,是一个24位的向下递减计数器,每次计数时间是1/SYSCLK,即1/72000000。
- SysTick计数时间的计算:t=重装载值*1/AHB时钟频率。1/AHB时钟频率即是计数一次的时间。一般把重装载值定为72000000/100000=720,则10us中断一次;一般不设置为1us中断一次,这样中断频率太高,偏移了程序重心。
- 定时器配置步骤:
1.初始化:
/**
* @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.定时函数:
/**
* @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.中断服务函数:
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 --;
}
}
- 另一种微秒级定时编程:
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;
}
同理可以写出ms级的定时程序。
下一篇: 通过ESP8266上传温度到腾讯云