微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32F051应用笔记-系统时间选择及PLL倍频设

STM32F051应用笔记-系统时间选择及PLL倍频设

时间:11-21 来源:互联网 点击:
对于广大初次接触STM32的读者朋友(甚至是初次接触ARM器件的读者朋友)来说,在熟悉了开发环境的使用之后,往往“栽倒”在同一个问题上。这问题有个关键字叫:时钟树。

众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如51,AVR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固定的,用户无法将此时钟速率更改,除非更换晶振。
而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,而不同的外设也对应有不同的时钟,使用任何一个外设都必须打开相应的时钟。这样的好处就是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果。

1、启动代码分析—SystemInit (void)系统时钟初始化

SystemInit (void)是系统初始化函数,很多新手不知其在何处调用,小肖马上为你解惑。

startup_stm32f0xx.s文件中汇编代码为STM32启动代码。

启动代码步骤一般为:

1)堆和栈的初始化;

2)向量表定义;

3)地址重映射及中断向量表的转移;

4)设置系统时钟频率;

5)中断寄存器的初始化;

6)进入主程序。

废话太多,估计也看烦了。现在挑重点讲,重点在第4个步骤。(第5、6一般编程时在用户代码中执行)。

Reset_Handler

PROC;标记一个函数的开始,也就是复位入口。

IMPORT

__main ; 通知编译器要使用的标号在其他文件

IMPORT

SystemInit; 同上

关键在这里了,

LDR

R0, =SystemInit;

这里的“=”表示LDR目前是伪指令不是标准指令。这里是把SystemInit的地址给RO。也就是说SystemInit (void)在这里被调用编译。所以用户编在写程序时无需编写PLL配置程序。

BX

R0;BX是ARM指令集和THUMB指令集之间程序的跳转。

其他省略。详情如下图所示:

SystemInit初始化RCC之后调用SetSysClock(void)系统时钟设置函数

代码如下:

void SystemInit (void)

{

RCC->CR |= (uint32_t)0x00000001;

RCC->CFGR &= (uint32_t)0xF8FFB80C;

RCC->CR &= (uint32_t)0xFEF6FFFF;

RCC->CR &= (uint32_t)0xFFFBFFFF;

RCC->CFGR &= (uint32_t)0xFFC0FFFF;

RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;

RCC->CFGR3 &= (uint32_t)0xFFFFFEAC;

RCC->CR2 &= (uint32_t)0xFFFFFFFE;

RCC->CIR = 0x00000000;

SetSysClock();

}

2、SetSysClock()设置系统时钟

由于之前选择定义了PLL_SOURCE_HSE,执行条件编译。

RCC->CR |= ((uint32_t)RCC_CR_HSEON);//使能HSE,如下图所示:

等待HSE设置完毕,代码如下。

do

{

HSEStatus = RCC->CR & RCC_CR_HSERDY;

StartUpCounter++;

} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)

{

HSEStatus = (uint32_t)0x01;

}

else

{

HSEStatus = (uint32_t)0x00;

}

设置完成,HSEStatus赋值1,代码如下:

if ((RCC->CR & RCC_CR_HSERDY) != RESET)

{

HSEStatus = (uint32_t)0x01;

}

else

{

HSEStatus = (uint32_t)0x00;

}

HSEStatus HSE==1表示HSE状态正常,启用缓冲区和设置FLASH延迟、HCLK\PCLK。PLL倍频如下图红线所示,修改RCC_CFGR_PLLMULL实现倍频(默认6倍频)。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top