配置系统时钟实验
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笔记(三)---寄存器映射--BSRR分析
推荐阅读最新更新时间:2024-11-11 09:21
推荐帖子
- 请问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到
- 振动试验仪器 电源技术
设计资源 培训 开发板 精华推荐
- EVLSTNRG-170W,基于 STNRG388A 170-W SMPS 的评估板,具有数控 PFC 和谐振 LLC 级
- NCV3163 电压反相开关稳压器的典型应用
- 使用 Diodes Incorporated 的 PT8A 3514D 的参考设计
- 使用 ROHM Semiconductor 的 BD48K28G-TL 的参考设计
- NCL2801LED1GEVB:高精度 200W 功率因数控制器
- 加热用希尔伯特曲线铝基板
- 用于并联稳压器的 TL431 可编程精密基准的典型应用
- NXH3670ADK开发套件
- SPX431L 精密可调并联稳压器典型应用电路
- AM6TW-4807SH35Z 7.2V 6瓦双输出DC/DC转换器的典型应用