STM32笔记(四)---配置系统时钟实验

发布者:码字奇思最新更新时间:2022-05-26 来源: eefocus关键字:STM32  配置  系统时钟 手机看文章 扫描二维码
随时随地手机看文章

配置系统时钟实验

1 使用 HSE

一般情况下,我们都是使用 HSE,然后 HSE 经过 PLL 倍频之后作为系统时钟。


通常的配置是: HSE=8M, PLL 的倍频因子为: 9,系统时钟就设置成:SYSCLK = 8M * 9 = 72M。使用 HSE,系统时钟 SYSCLK 最高是128M(16倍频)。


当程序来到 main 函数之前,启动文件: statup_stm32f10x_hd.s 已经调用 SystemInit()函数把系统时钟初始化成 72MHZ, SystemInit()在库文件: system_stm32f10x.c 中定义。如果我们想把系统时钟设置低一点或者超频的话,可以修改底层的库文件,但是为了维持库的完整性,我们可以根据时钟树的流程自行写一个。


2 使用HSI

当 HSE 故障的时候, 如果 PLL 的时钟来源是 HSE, 那么当 HSE 故障的时候,不仅HSE 不能使用,连 PLL 也会被关闭,这个时候系统会自动切换 HSI 作为系统时钟,此时SYSCLK=HSI=8M,如果没有开启 CSS 和 CSS 中断的话,那么整个系统就只能在低速率运行,这是系统跟瘫痪没什么两样。


如果开启了 CSS 功能的话,那么可以当 HSE 故障时,在CSS 中断里面采取补救措施,使用 HSI,并把系统时钟设置为更高的频率,最高是 64M,64M 的频率足够一般的外设使用,如: ADC 、 SPI、 I2C 等。但是这里就又有一个问题了,原来 SYSCLK=72M,现在因为故障改成 64M,那么那些外设的时钟肯定被改变了,那么外设工作就会被打乱,那我们是不是在设置 HSI 时钟的时候,也重新调整外设总线的分频因子,即 AHB, APB2 和 APB1 的分频因子,使外设的时钟达到跟 HSE 没有故障之前一样。但是这个也不是最保障的办法,毕竟不能一直使用 HSI,所以当 HSE 故障时还是要采取报警措施。


编程要点对应着时钟树图中的序号:1、开启 HSE/HSI , 并等待 HSE/HSI 稳定2、设置 AHB、 APB2、 APB1 的预分频因子3、设置 PLL 的时钟来源,和 PLL 的倍频因子,设置各种频率主要就是在这里设置4、开启 PLL,并等待 PLL 稳定5、把 PLLCK 切换为系统时钟 SYSCLK6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟


3 HSE库函数版配置

void HSE_SetSysClock(uint32_t pllmul)

{

__IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;

// 把 RCC 外设初始化成复位状态

RCC_DeInit();

//使能 HSE,开启外部晶振--8M

RCC_HSEConfig(RCC_HSE_ON);

// 等待 HSE 启动稳定

HSEStartUpStatus = RCC_WaitForHSEStartUp();

// 只有 HSE 稳定之后则继续往下执行

if (HSEStartUpStatus == SUCCESS) {

//-----------------------------------------------------------------//

// 这两句是操作 FLASH 闪存用到的,如果不操作 FLASH,这两个注释掉也没影响

// 使能 FLASH 预存取缓冲区

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

// SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2

// 设置成 2 的时候, SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,

// 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了

// 0: 0 < SYSCLK <= 24M

// 1: 24< SYSCLK <= 48M

// 2: 48< SYSCLK <= 72M

FLASH_SetLatency(FLASH_Latency_2);

//-----------------------------------------------------------------//

// AHB 预分频因子设置为 1 分频, HCLK = SYSCLK

RCC_HCLKConfig(RCC_SYSCLK_Div1);

// APB2 预分频因子设置为 1 分频, PCLK2 = HCLK

RCC_PCLK2Config(RCC_HCLK_Div1);

// APB1 预分频因子设置为 2 分频, PCLK1 = HCLK/2

RCC_PCLK1Config(RCC_HCLK_Div2);

//-----------------设置各种频率主要就是在这里设置-------------------//

// 设置 PLL 时钟来源为 HSE,设置 PLL 倍频因子

// PLLCLK = 8MHz * pllmul

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);

//-------------------------------------------------------------//

// 开启 PLL

RCC_PLLCmd(ENABLE);

// 等待 PLL 稳定

while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {

    }

// 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

// 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟

while (RCC_GetSYSCLKSource() != 0x08) {

    }

    else 

    {

// 如果 HSE 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理

// 当 HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,

// HSI 是内部的高速时钟, 8MHZ

while (1) {

}

}

}


4 HSI库函数版配置

void HSI_SetSysClock(uint32_t pllmul)

{

__IO uint32_t HSIStartUpStatus = 0;

// 把 RCC 外设初始化成复位状态

RCC_DeInit();

//使能 HSI

RCC_HSICmd(ENABLE);

// 等待 HSI 就绪

HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;

// 只有 HSI 就绪之后则继续往下执行

if (HSIStartUpStatus == RCC_CR_HSIRDY) {

//-------------------------------------------------------------//

// 这两句是操作 FLASH 闪存用到的,如果不操作 FLASH,这两个注释掉也没影响

// 使能 FLASH 预存取缓冲区

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

// SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2

// 设置成 2 的时候, SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,

// 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了

// 0: 0 < SYSCLK <= 24M

// 1: 24< SYSCLK <= 48M

// 2: 48< SYSCLK <= 72M

FLASH_SetLatency(FLASH_Latency_2);

//------------------------------------------------------------//

// AHB 预分频因子设置为 1 分频, HCLK = SYSCLK

RCC_HCLKConfig(RCC_SYSCLK_Div1);

// APB2 预分频因子设置为 1 分频, PCLK2 = HCLK

RCC_PCLK2Config(RCC_HCLK_Div1);

// APB1 预分频因子设置为 1 分频, PCLK1 = HCLK/2

RCC_PCLK1Config(RCC_HCLK_Div2);

//-----------设置各种频率主要就是在这里设置-------------------//

// 设置 PLL 时钟来源为 HSE,设置 PLL 倍频因子

// PLLCLK = 4MHz * pllmul

RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);

//-- -----------------------------------------------------//

// 开启 PLL

RCC_PLLCmd(ENABLE);

// 等待 PLL 稳定

while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {

}

// 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

// 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟

while (RCC_GetSYSCLKSource() != 0x08) {

}

    else 

    {

// 如果 HSI 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理

// 当 HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,

// HSI 是内部的高速时钟, 8MHZ

while (1) {

}

}

}


5 MCO 输出

STM32F103 系列中, PA8 可以复用为 MCO 引脚,对外提供时钟输出,我们也可以用示波器监控该引脚的输出来判断我们的系统时钟是否设置正确。


MCO GPIO 初始化函数:


/*

* 初始化 MCO 引脚 PA8

* 在 F103 系列中 MCO 引脚只有一个,即 PA8,在 F4 系列中, MCO 引脚有两个

*/

void MCO_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

// 开启 GPIOA 的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

// 选择 GPIO8 引脚

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

//设置为复用功能推挽输出

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

//设置 IO 的翻转速率为 50M

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

// 初始化 GPIOA8

GPIO_Init(GPIOA, &GPIO_InitStructure);

}


MCO 输出时钟选择:


// 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,

// 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确

// MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK

//RCC_MCOConfig(RCC_MCO_HSE);

//RCC_MCOConfig(RCC_MCO_HSI);

//RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);

RCC_MCOConfig(RCC_MCO_SYSCLK);


6 主函数

int main(void)

{

// 程序来到 main 函数之前,启动文件: statup_stm32f10x_hd.s 已经调用

// SystemInit()函数把系统时钟初始化成 72MHZ

// SystemInit()在 system_stm32f10x.c 中定义

// 如果用户想修改系统时钟,可自行编写程序修改

// 重新设置系统时钟,这时候可以选择使用 HSE 还是 HSI

// 使用 HSE 时, SYSCLK = 8M * RCC_PLLMul_x, x:[2,3,...16],最高是 128M

HSE_SetSysClock(RCC_PLLMul_9);

// 使用 HSI 时, SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16],最高是 64MH

//HSI_SetSysClock(RCC_PLLMul_16);

// MCO 引脚初始化

MCO_GPIO_Config();

// 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,

// 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确

// MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK

//RCC_MCOConfig(RCC_MCO_HSE);

//RCC_MCOConfig(RCC_MCO_HSI);

//RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);

RCC_MCOConfig(RCC_MCO_SYSCLK);

// LED 端口初始化

LED_GPIO_Config();

while (1) 

    {

LED1( ON ); // 亮

Delay(0x0FFFFF);

LED1( OFF ); // 灭

Delay(0x0FFFFF);

}

}


在主函数中,可以调用 HSE_SetSysClock()或者 HSI_SetSysClock()这两个函数把系统时钟设置成各种常用的时钟,然后通过 MCO 引脚监控,或者通过 LED 闪烁的快慢体验不同的系统时钟对同一个软件延时函数的影响。

关键字:STM32  配置  系统时钟 引用地址:STM32笔记(四)---配置系统时钟实验

上一篇:STM32笔记(五)---中断应用
下一篇:STM32笔记(三)---寄存器映射--BSRR分析

推荐阅读最新更新时间:2024-11-11 09:21

ATmega48 时钟系统及其分布
Figure12为ATmega48 的主要时钟系统及其分布。这些时钟并不需要同时工作。为了降低功耗,可以通过使用不同的睡眠模式来禁止无需工作的模块的时钟,详见 P32” 电源管理及休眠模式 ” 。下面为时钟系统的详细描述。 CPU 时钟- clkCPU CPU时钟与操作AVR内核的子系统相连,如通用寄存器文件、状态寄存器及保存堆栈指针的数据存储器。终止CPU 时钟将使内核停止工作和计算。 I/O 时钟- clkI/O I/O时钟用于主要的I/O 模块,如定时器/ 计数器、SPI 和USART。I/O 时钟还用于外部中断模块。要注意的是有些外部中断由异步逻辑检测,因此即使I/O 时钟停止了这些中断仍然可以得到监控。此外, USI
[单片机]
ATmega48 <font color='red'>时钟</font><font color='red'>系统</font>及其分布
使用STM32实现云连接应用的资料概述
网络的形成,无论是现在已趋于成熟的互联网,还是蕴含着巨大潜力蓬勃发展的物联网,都是来自于一个个原本孤立的节点,因为某种互动关系或需求而产生连接。未来可期的物联网,基于网络协议技术以及云端强大的计算和存储能力,正在不断“挖掘”众多智能设备的“潜力”。这个过程中,云连接成为组成网络最必要的应用。 每个垂直行业的物联网应用都有各自不同的特点,但他们都有着共通的基本需求:连接、处理(包括数据的感知,命令的执行)、安全、功耗等。 连云刚需下的STM32生态 为了满足客户的连云需求,一方面,ST设计开发出在功耗和安全方面更加适用于IoT应用的STM32产品线,这是在芯片本身方面的努力;另一方面,进一步完善STM32的生态系统,与各个连
[单片机]
STM32笔记之九:打断它来为我办事,EXIT (外部I/O中断)应用
a) 目的:跟串口输入类似,不使用中断进行的IO输入效率也很低,而且可以通过EXTI插入按钮事件,本节联系EXTI中断。 b) 初始化函数定义: void EXTI_Configuration(void); //定义IO中断初始化函数 c) 初始化函数调用: EXTI_Configuration();//IO中断初始化函数调用简单应用: d) 初始化函数: void EXTI_Configuration(void) { EXTI_InitTypeDef EXTI_InitStructure; //EXTI初始化结构定义 EXTI_Cle
[单片机]
库卡机器人EL6752 DeviceNet板卡配置福尼斯(Fronius)焊机的方法教程
1. 已经配置 EL6752 模块 2. 展开“总线结构 ”→“KUKA Exnsion Bus (STS-X44)”→“EK1100 EtherCAT Coupler(2A E-Bus)”→“EL6752 DeviceNet Master”→“DeviceNet IO”,双击“Generic DeviceNet Device”,弹出 DeviceNet 设备设置界面 3. 设置参数③点“继续workvisual 将自动分析将要设备说明文件,随后点击完成,设备说明文件导入workvisual 4. 打开输入输出信号配置画面
[机器人]
STM32 软件模拟SPI时序驱动NRF24L01
其实stm32本身的硬件SPI也很好用,但是还是想用软件来模拟一下PSI的时序。 SPI 是一种高速的,全双工,同步串行的通信总线。SPI通信方式相当于是一个环形结构,由CSN、MISO、MOSI、SCLK四线组成,主要是在SCLK时钟线的驱动下,进行数据转换。 接下来直接上程序配置: 使用32模拟SPI时序的IO口配置,应该注意的是MISO应该选择模拟输入方式GPIO_Mode_IN_FLOATING。 以下是我的初始化部分: /*用于软件模拟SPI IO口宏定义区*/#define SPI_CS_PORT GPIOB#define SPI_CS_PIN GPIO_Pin_11#define SPI_CS_LOW
[单片机]
<font color='red'>STM32</font> 软件模拟SPI时序驱动NRF24L01
GPIO资源总结
STM32Fx系列 GPIO基本结构 保护二极管:IO引脚上下两边两个二极管用于防止引脚外部过高、过低的电压输入。当引脚电压高于VDD时,上方的二极管导通;当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁。但是尽管如此,还是不能直接外接大功率器件,须加大功率及隔离电路驱动,防止烧坏芯片或者外接器件无法正常工作。 P-MOS管和N-MOS管:由P-MOS管和N-MOS管组成的单元电路使得GPIO具有“推挽输出”和“开漏输出”的模式。这里的电路会在下面很详细地分析到。 TTL肖特基触发器:信号经过触发器后,模拟信号转化为0和1的数字信号。但是,当GPIO引脚作为ADC采集电压的输入通道时,用其“
[单片机]
GPIO资源总结
STM32的printf使用
#include //加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1- SR&0X40)==
[单片机]
关于STM32 ADC时采用DMA的一点疑问
手册上有这样的话:只有ADC1能够产生DMA请求,似乎是只有ADC通道1能采用DMA方式传输数据。 但是万利的开发板上的ADC例子,用的是ADC通道10,还用了DMA 方式传数据。 所以我猜测 “只有ADC1能够产生DMA请求”中提到的ADC1 并不是指ADC 通道1, 而是软件可配置的 ADC 通道的分类形式,可分为ADC1和ADC2. 我们可将 通道10(或其他)配置成ADC1 “模式”。通过函数 /* ADC1 regular channel10 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_5
[单片机]

推荐帖子

请问TPS5430输出的电压为什么随着输入电压增加而变大
这是电路,输入12V以下稳定输出3.3V,输入13V,电源输出3.7V,按理应该恒定的啊。请问TPS5430输出的电压为什么随着输入电压增加而变大电路上看不出什么问题的。一般与所用具体器件的有关。空载测的还是带载测的?与使能脚那个上拉电阻有关,把电阻取了就正常,但手册里说5脚悬空或拉高,不知道问题在哪儿,难道大于12V的电压加在5脚对芯片有影响?祝楼主节日快乐,工作顺利。看起来5脚只能悬空楼主的C72,R101的值怎么来的 “难道大于12V的电压加在5脚对芯片有影响”当
存在即合理 模拟与混合信号
Verilog与CPLD,FPGA的设计及应用教程
内容如题.Verilog与CPLD,FPGA的设计及应用教程谢谢分享!正在学这个方面的知识!Re:Verilog与CPLD,FPGA的设计及应用教程顶看看谢谢楼主Re:Verilog与CPLD,FPGA的设计及应用教程感谢楼主啊,谢谢!!!啊!!!哈哈哈!!!我先看看啊!!!
kejuyuan FPGA/CPLD
被某人成为世界难题(干扰和信号),坛里的高手来看看
公司历经三年,耗资3000万始终没有解决问题。我们系统中GPRSwifi等大功率大电流的模块都是实时工作在他们工作的时候系统中模拟电路始终受到大功率模块的辐射干扰和传导干扰导致系统无**常工作。现在我们系统重新架构如上图所示。所有模块的地都通过磁珠一点接入到电源进线。磁珠的额定电流都是超过2A。我想问一下各位高手这么的系统架构合不合理。有没有更好的电源系统架构和走线方式。特别是地的处理方式。。。。。。。。被某人成为世界难题(干扰和信号),坛里的高手来看看磁珠是用来吸
laojiededepan 模拟电子
总结给要参加电子设计竞赛的同学们
本帖最后由paulhyde于2014-9-1509:33编辑总结给要参加电子设计竞赛的同学们电子设计竞赛的近几年成为企业录用大学生的重点考察点从而带动成为大学生的热点,在参赛的同学中有很多是大二学生或者是第一次参赛的同学,或许很迷茫、不知道从哪方面入手。这里,我将之前学长给我们的建议以及一点个人拙见整理了一下分享给你们。1、不要追求高精尖,要通,简单而言“不怕千招会,只怕一招熟”。电赛时间有限,与其花时间去弄自己没接触过的东西,不如把自己已经学到的东西弄透。
asasd1 电子竞赛
关于arm9的cache清空问题
arm手册中只有一句汇编MRCp15,0,Rd,c7,c7,0我的程序是用C++写的,我用了_asm{MRCp15,0,Rd,c7,c7,0}后便宜提示p15没定义,我想在我的应用程序里清空cache,具体怎么做啊关于arm9的cache清空问题我没有在应用程序中嵌入过汇编。我冒昧的推测,这样做不行,因为如果可以再应用程序嵌入式汇编操作硬件,那我直接写个应用程序,不写驱动了。如果你想在应用程序清空cache就写个驱动,在驱动中嵌入汇编我觉得这个方法比较好有谁在EVC或者VS200
blackbeer ARM技术
振动台功率放大板维修
振动台的功率放大器是桥式放大输出,一般是管子的十安培保险烧坏,IRFP260N功放管烧坏。 功放板一般是断电用万用表测量,把坏的电子元件换了,通电后量管子G极串联小电阻上电压可以检查管子的好坏。 振动台功率放大板维修测量功放板时没有加上200V的直流电压,相对电路板上电压是15V,安全性能好,这时用示波器看方波的波形都是没有关系的。 功放管输入端串联一个5欧姆的小电阻,功放输出电路接通后,量5欧电阻上的直流电压,就可以知道功放管的驱动电流,正常5欧电阻上电压是0.6到
振动试验仪器 电源技术
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved