专题三stm32时钟树及相关库函数
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Startup_stm32f10x_ld.s
Startup_stm32f10x_md.s
Startup_stm32f10x_hd.s
上面,有后缀ld,md,hd,这三个后缀是什么意思呢?原来是这样的:
ld Low-density小容量16-32K
md Medium-density中容量64-128K
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,等等,具体可以在stm32f10x_rcc.c文件中查看函数说明。
如果要进行时钟设置,就是对上面的寄存器进行操作。有两种方法,一种是直接进行寄存器的赋值,还有一种方法是调用ST公司提供的库函数,用户无需面对寄存器。
以与GPIO外设有关的寄存器为例,APB2ENR,它将使能GPIO的时钟。在程序中,如果要使能GPIO时钟,比如使能GPIOA,已知APB2ENR的bit2位是使能GPIOA,那么寄存器直接操作的方法是:
我们看这个函数的定义:
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
红色第3行:SetSysClock();设置系统时钟到72MHz.也就是SYSCLK是72MHz。
第3种启动方式是STM32内嵌的SRAM启动,该模式用于调试。
上述三种模式,各有作用。如果要进行程序下载,就必须将启动模式调整到第二种方式,程序下载完毕后,再回复到第一种方式,就可以正常工作了。
2.2 STM32的启动文件
启动文件:建立工程文件时,keil MDK会提示“复制启动文件STM32F10x.s到项目文件夹下”。但是MDK提示的这个启动文件只定义了3个串口,4个定时器,具体到某个型号,每种STM32芯片都不一样。比如有的芯片器件是有5个串口,6个定时器的,如果用MDK提供的启动文件,就有2个串口,2个定时器找不到定义导致不能使用。在3.5版本的固件库下,有加了后缀的启动文件:
4.低速内部时钟LSI(40kHz)。
从图1还可看到,芯片内部系统时钟SYSCLK的来源有3个。
1.高速外部时钟HSE(4-16MHz);
2.高速内部时钟HSI(8MHz);
3.HSE或HSI通过锁相环2-16倍频后的锁相环时钟PLLCLK。
上述的系统时钟SYSCLK经AHB预分频器后得到AHB总线时钟HCLK,继而得到APB1和APB2总线时钟。要注意的是:APB1挂接的外设有:DAC、UART2-5,TIM2-7、USB、I2C1-2等;APB2挂接的外设有:ADC1-3,GPIOA-G,TIM1,TIM8等。每次要使用STM32的相关外设,都要先使能对应的时钟。
APB2ENR|=1<<2;//或运算,1有效。
第二种方法就是调用库函数。
四、介绍两种库函数
4.1外设时钟使能函数
与rcc有关寄存器设置的库函数都在stm32f10x_rcc.c以及stm32f10x_rcc.h文档中。上面说要使能GPIO时钟,因为GPIO是APB2的外设,因此就是使能APB2相应外设时钟。库函数是:
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
2)CFGR:时钟配置寄存器,选择SYSCLK时钟源,以及各总线时钟的分频系数,以及PLL的倍频系数
3)CIR:时钟中断寄存器,进行时钟中断的使能和清除。
4)APB2RSTR:APB2外设复位寄存器,进行APB2外设的复位,与APB2连接的外设有USART1,SPI1,TIM1,ADC2,ADC1,等等。
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}
4.2与SYSCLK时钟设置有关的函数void SystemInit(void)
在3.5版本的库里,上面第节介绍的路径下,有个system_stm32f10x.c文件,在这个文件中,定义了一个函数void SystemInit(void)。这个函数将stm32芯片的时钟源设置成了PLL倍频模式,SYSCLK直接被设置为了72MHz。
typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
5)APB1RSTR:APB1外设复位寄存器,进行APB1外设的复位,有DAC,PWR,CAN2,I2C等。
6)AHBENR:AHB外设使能寄存器。包括以太网MAC,全速USB OTG时钟使能,SRAM时钟使能,DMA2,DMA1时钟使能等。
7)APB2ENR:APB2外设时钟使能寄存器,APB2连接外设的使能,有USART1,SPI1,TIM1,ADC2,ADC1,IOPE(GPIOE),IOPD(GPIOD),IOPC(GPIOC),IOPB(GPIOB),IOPA(GPIOA)等。
BOOT1
BOOT0
X
0
用户闪存存储器
将用户闪存存储器选为系统启动区域
0
1
系统存储器
将系统存储器选为系统启动区域
1
1
片上SRAM
将片上SRAM选为系统启动区域
第1种启动方式是最常用的用户FLASH启动,正常工作就在这种模式下,STM32的FLASH可以擦除10万次。
第2种方式是系统存储器启动方式,即我们常说的串口下载方式(ISP)。STM32中自带的BootLoader就是在这种启动方式中,如果出现程序硬件错误的话,可以切换到该模式下重新烧写Flash即可恢复正常。
hd High-density大容量256-512K
xl超大容量512-1024K
vl value line devices超值型
cl Connectivity line devices互联型
小容量:flash<=32K
中容量:64K<=flash <=128K
大容量:256K<=flash
根据你使用的芯片型号,就可以确定要使用哪种启动文件了。比如,我们使用STM32F103RB,这款芯片是128K的容量,那么就应该选启动文件Startup_stm32f10x_md.s。
三
从前面的图1可以看到,要设置STM32芯片的时钟,有以下几个方面要考虑:
1.芯片的时钟源选择HSE,HIS还是其他?
2.SYSCLK系统时钟应该选择哪个?
3.各总线的分频系数?
4.PLL锁相环的倍频系数?
5.各个外设对应的时钟是开启呢,还是禁止?
上面5个问题,STM32统一用RCC来解决。我们首先来看下与RCC相关的寄存器有哪些。
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
输入参数2:NewState,外设时钟的新状态,可以是DISABLE,ENABLE两种。
返回值:无
调用示范:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
函数的具体定义引用如下:
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
启动文件主要做了3个工作:
1.定义和初始化堆栈;
2.定义复位向量并初始化;
3.定义中断向量表及其相应的异常处理程序。
4.最后,开始main()函数。
注意,在3.5版固件库中,升级后的启动文件还调用了system_stm32f10x.c文件中的SystemInit()函数,配置系统时钟到PLL倍频下的72MHz。因此,如果使用新版的启动文件,main()函数就无需再调用SystemInit()函数了。而如果工程文件中包含的是旧版的STM32F10x.s文件,该文件是没有系统时钟配置语句的,因此,用户进入main()函数需要自己调用SystemInit()函数。
二、
2.1 STM32的启动模式
STM32处理器支持3种系统启动模式,且对应的存储介质均是芯片内置的。在每个STM32的芯片上都有两个引脚BOOT0和BOOT1,这两个引脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。
表1.STM32xx系列处理器的启动模式
启动模式的引脚
启动模式
功能说明
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
红色第1行:RCC->CR |= (uint32_t)0x00000001;设置时钟和复位寄存器,选择内部8MHz高速RC振荡器作为时钟源。
8)APB1ENR:APB1外设时钟使能寄存器,APB1连接的外设有DAC,CAN2,CAN1,I2C2,I2C1,UART5,UART4,USART3,USART2,SPI3,SPI2,TIM7-2等。
9)初始阶段我们比较关注的有CR,CFGR,
10)BDCR:备份域控制寄存器
11)CSR:控制/状态寄存器,对看门狗、软件复位等的状态进行标识。
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
函数名:RCC_APB2PeriphClockCmd()
功能描述:使能或禁止高速APB2外设时钟。
输入参数1:RCC_APB2Periph,定义了APB2外设在RCC_APB2ENR中的相应位地址。这个参数可以是下列值:
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
} RCC_TypeDef;
上面这个结构体类型的定义有这么多寄存器,每个寄存器简要说明如下:
1)CR:时钟控制寄存器,选择stm32芯片时钟源,在HSE,HSI,PLL之间进行选择。
专题三STM32时钟及相关库函数
一、
STM32 MCU系统时钟树由系统时钟源、系统时钟SYSCLK和设备时钟等部分组成。
图1 STM32芯片时钟树
从图1可看到,芯片时钟源有4个:
1.高速外部时钟HSE(4-16MHz);
2.高速内部时钟HSI(8MHz);
3.低速外部时钟LSE(32.768kHz);
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /*ຫໍສະໝຸດ BaiduSTM32F10X_CL */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
Startup_stm32f10x_md.s
Startup_stm32f10x_hd.s
上面,有后缀ld,md,hd,这三个后缀是什么意思呢?原来是这样的:
ld Low-density小容量16-32K
md Medium-density中容量64-128K
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,等等,具体可以在stm32f10x_rcc.c文件中查看函数说明。
如果要进行时钟设置,就是对上面的寄存器进行操作。有两种方法,一种是直接进行寄存器的赋值,还有一种方法是调用ST公司提供的库函数,用户无需面对寄存器。
以与GPIO外设有关的寄存器为例,APB2ENR,它将使能GPIO的时钟。在程序中,如果要使能GPIO时钟,比如使能GPIOA,已知APB2ENR的bit2位是使能GPIOA,那么寄存器直接操作的方法是:
我们看这个函数的定义:
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
红色第3行:SetSysClock();设置系统时钟到72MHz.也就是SYSCLK是72MHz。
第3种启动方式是STM32内嵌的SRAM启动,该模式用于调试。
上述三种模式,各有作用。如果要进行程序下载,就必须将启动模式调整到第二种方式,程序下载完毕后,再回复到第一种方式,就可以正常工作了。
2.2 STM32的启动文件
启动文件:建立工程文件时,keil MDK会提示“复制启动文件STM32F10x.s到项目文件夹下”。但是MDK提示的这个启动文件只定义了3个串口,4个定时器,具体到某个型号,每种STM32芯片都不一样。比如有的芯片器件是有5个串口,6个定时器的,如果用MDK提供的启动文件,就有2个串口,2个定时器找不到定义导致不能使用。在3.5版本的固件库下,有加了后缀的启动文件:
4.低速内部时钟LSI(40kHz)。
从图1还可看到,芯片内部系统时钟SYSCLK的来源有3个。
1.高速外部时钟HSE(4-16MHz);
2.高速内部时钟HSI(8MHz);
3.HSE或HSI通过锁相环2-16倍频后的锁相环时钟PLLCLK。
上述的系统时钟SYSCLK经AHB预分频器后得到AHB总线时钟HCLK,继而得到APB1和APB2总线时钟。要注意的是:APB1挂接的外设有:DAC、UART2-5,TIM2-7、USB、I2C1-2等;APB2挂接的外设有:ADC1-3,GPIOA-G,TIM1,TIM8等。每次要使用STM32的相关外设,都要先使能对应的时钟。
APB2ENR|=1<<2;//或运算,1有效。
第二种方法就是调用库函数。
四、介绍两种库函数
4.1外设时钟使能函数
与rcc有关寄存器设置的库函数都在stm32f10x_rcc.c以及stm32f10x_rcc.h文档中。上面说要使能GPIO时钟,因为GPIO是APB2的外设,因此就是使能APB2相应外设时钟。库函数是:
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
2)CFGR:时钟配置寄存器,选择SYSCLK时钟源,以及各总线时钟的分频系数,以及PLL的倍频系数
3)CIR:时钟中断寄存器,进行时钟中断的使能和清除。
4)APB2RSTR:APB2外设复位寄存器,进行APB2外设的复位,与APB2连接的外设有USART1,SPI1,TIM1,ADC2,ADC1,等等。
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}
4.2与SYSCLK时钟设置有关的函数void SystemInit(void)
在3.5版本的库里,上面第节介绍的路径下,有个system_stm32f10x.c文件,在这个文件中,定义了一个函数void SystemInit(void)。这个函数将stm32芯片的时钟源设置成了PLL倍频模式,SYSCLK直接被设置为了72MHz。
typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
5)APB1RSTR:APB1外设复位寄存器,进行APB1外设的复位,有DAC,PWR,CAN2,I2C等。
6)AHBENR:AHB外设使能寄存器。包括以太网MAC,全速USB OTG时钟使能,SRAM时钟使能,DMA2,DMA1时钟使能等。
7)APB2ENR:APB2外设时钟使能寄存器,APB2连接外设的使能,有USART1,SPI1,TIM1,ADC2,ADC1,IOPE(GPIOE),IOPD(GPIOD),IOPC(GPIOC),IOPB(GPIOB),IOPA(GPIOA)等。
BOOT1
BOOT0
X
0
用户闪存存储器
将用户闪存存储器选为系统启动区域
0
1
系统存储器
将系统存储器选为系统启动区域
1
1
片上SRAM
将片上SRAM选为系统启动区域
第1种启动方式是最常用的用户FLASH启动,正常工作就在这种模式下,STM32的FLASH可以擦除10万次。
第2种方式是系统存储器启动方式,即我们常说的串口下载方式(ISP)。STM32中自带的BootLoader就是在这种启动方式中,如果出现程序硬件错误的话,可以切换到该模式下重新烧写Flash即可恢复正常。
hd High-density大容量256-512K
xl超大容量512-1024K
vl value line devices超值型
cl Connectivity line devices互联型
小容量:flash<=32K
中容量:64K<=flash <=128K
大容量:256K<=flash
根据你使用的芯片型号,就可以确定要使用哪种启动文件了。比如,我们使用STM32F103RB,这款芯片是128K的容量,那么就应该选启动文件Startup_stm32f10x_md.s。
三
从前面的图1可以看到,要设置STM32芯片的时钟,有以下几个方面要考虑:
1.芯片的时钟源选择HSE,HIS还是其他?
2.SYSCLK系统时钟应该选择哪个?
3.各总线的分频系数?
4.PLL锁相环的倍频系数?
5.各个外设对应的时钟是开启呢,还是禁止?
上面5个问题,STM32统一用RCC来解决。我们首先来看下与RCC相关的寄存器有哪些。
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
输入参数2:NewState,外设时钟的新状态,可以是DISABLE,ENABLE两种。
返回值:无
调用示范:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
函数的具体定义引用如下:
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
启动文件主要做了3个工作:
1.定义和初始化堆栈;
2.定义复位向量并初始化;
3.定义中断向量表及其相应的异常处理程序。
4.最后,开始main()函数。
注意,在3.5版固件库中,升级后的启动文件还调用了system_stm32f10x.c文件中的SystemInit()函数,配置系统时钟到PLL倍频下的72MHz。因此,如果使用新版的启动文件,main()函数就无需再调用SystemInit()函数了。而如果工程文件中包含的是旧版的STM32F10x.s文件,该文件是没有系统时钟配置语句的,因此,用户进入main()函数需要自己调用SystemInit()函数。
二、
2.1 STM32的启动模式
STM32处理器支持3种系统启动模式,且对应的存储介质均是芯片内置的。在每个STM32的芯片上都有两个引脚BOOT0和BOOT1,这两个引脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。
表1.STM32xx系列处理器的启动模式
启动模式的引脚
启动模式
功能说明
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
红色第1行:RCC->CR |= (uint32_t)0x00000001;设置时钟和复位寄存器,选择内部8MHz高速RC振荡器作为时钟源。
8)APB1ENR:APB1外设时钟使能寄存器,APB1连接的外设有DAC,CAN2,CAN1,I2C2,I2C1,UART5,UART4,USART3,USART2,SPI3,SPI2,TIM7-2等。
9)初始阶段我们比较关注的有CR,CFGR,
10)BDCR:备份域控制寄存器
11)CSR:控制/状态寄存器,对看门狗、软件复位等的状态进行标识。
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
函数名:RCC_APB2PeriphClockCmd()
功能描述:使能或禁止高速APB2外设时钟。
输入参数1:RCC_APB2Periph,定义了APB2外设在RCC_APB2ENR中的相应位地址。这个参数可以是下列值:
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
} RCC_TypeDef;
上面这个结构体类型的定义有这么多寄存器,每个寄存器简要说明如下:
1)CR:时钟控制寄存器,选择stm32芯片时钟源,在HSE,HSI,PLL之间进行选择。
专题三STM32时钟及相关库函数
一、
STM32 MCU系统时钟树由系统时钟源、系统时钟SYSCLK和设备时钟等部分组成。
图1 STM32芯片时钟树
从图1可看到,芯片时钟源有4个:
1.高速外部时钟HSE(4-16MHz);
2.高速内部时钟HSI(8MHz);
3.低速外部时钟LSE(32.768kHz);
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /*ຫໍສະໝຸດ BaiduSTM32F10X_CL */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */