当前位置: 首页 > news >正文

STM32完全学习——系统时钟设置

一、时钟框图的解读

首先我们知道STM32在上电初始化之后使用的是内部的HSI未经过分频直接通过SW供给给系统时钟,由于内部HSI存在较大的误差,因此我们在系统完成上电初始化,之后需要将STM32的时钟切换到外部HSE作为系统时钟,那么我们需要完成下面一些设置完成切换。首先我们需要打开外部HSE的震荡电路然后,等待外部震荡电路就绪后,在切换PLLTPRE为HSE的1分频,在设置PLLSRC为PLLXTPRE过来的时钟。然后设置PLLMUL倍频系数,然后打开PLL开关等待PLL稳定。然后设置APB1总线为2分频,最后切换系统时钟为PLL输出的时钟。

二、相关寄存器

三、编程实现

#ifndef __SYSTEM_H__
#define __SYSTEM_H__#define uint unsigned inttypedef struct rRCC
{uint CR;uint CFGR;uint CIR;uint APB2RSTR;uint APB1RSTR;uint AHBENR;uint APB2ENR;uint APB1ENR;uint BDCR;uint CSR;uint AHBRSTR;uint CFGR2;	
}RCC_TypeDef;static RCC_TypeDef *RCC = (RCC_TypeDef *)0x40021000;void set_system_clock(void);#endif
#include "system.h"uint HSERDY_FLAG = 0;     //HSE就绪标志
uint PLLRDY_FLAG = 0;     //PLL就绪标志
uint SWRDY_FLAG  = 0;     //时钟切换标志
uint false_time = 0;      //超时时间标志void set_system_clock(void)
{rFLASH_ACR = 0x00000032; //这个用来设置系统时钟于Flash访问时间的比率 根据系统时钟的不同设置的值不同RCC->CR &= (~(0x01 << 16));      //将HSEON这位清零RCC->CR |= (0x01 << 16);         //开启外部HSE振荡器电路do                               //判断外部HSE电路是否就绪{HSERDY_FLAG = ((RCC->CR) & (0x01 << 17));false_time++;}while((false_time < 0x00ffffff) && (HSERDY_FLAG == 0));false_time = 0;if (HSERDY_FLAG != 0)            //如果外部振荡器电路就绪才会执行{ RCC->CFGR &= (~((0x01 << 17) | (0x01 << 16) | (0x0f << 18)));  //设置PLL倍频系数为9倍频RCC->CFGR |= ((0x01 << 16) | (0x0 << 17) | (0x07 << 18));  //设置PLL时钟来源为PREDIV1 并且设置PLLXTPRE不对输入的时钟分频RCC->CR &= (~(0x01 << 24));       //使能PLL时钟RCC->CR |= (0x01 << 24);do {PLLRDY_FLAG = ((RCC->CR) & (0x01 << 25));false_time++;}while((false_time < 0x00ffffff) && (PLLRDY_FLAG == 0));  //等待PLL时钟就绪false_time = 0;if (((RCC->CR) & (0x01 << 25)) != 0){	RCC->CFGR &= (~((0x01 << 22) | (0x07 << 8)));  RCC->CFGR |= ((0x0 << 22) | (0x04 << 8));     //全速USB OTG配置为PLL输出2分频 APB1总线2分频 PLL输出作为系统时钟RCC->CFGR &= ~(0x03 << 0); RCC->CFGR |= (0x02);    //切换系统时钟为PLL输出时钟do{SWRDY_FLAG = ((RCC->CFGR) & (0x03 << 2));false_time++;	}while((false_time < 0x00ffffff) && ((SWRDY_FLAG) == 0));if (((RCC->CFGR) & (0x03 << 2)) != 0)  //判断时钟是否切换成功{}else{while(1);}}}else{while(1);}
}

上面的代码一个是.h文件另一个是.c文件,但是当我们运行上面的代码时我发现了一个问题,当我们将时钟切换到PLL输出作为系统时钟时,系统就不运行了。就死机了。这是为什么呢,通过翻看数据手册发现,系统时钟和内部flah有一些关系,我们来看flash的寄存器就可以发现。

我们来看bit0-2发现,当复位时默认是000,因此系统时钟必须在0到24MHz之间,这时候我们使用的是内部的HSI时钟,时钟只有8MHz,因此这个时候系统是可以正常运行的,但是当我们将时钟切换到外部HSE时,由于我们做了一系列的倍频,因此这个时候系统时钟到了72MHz,因此我们呢这里需要将这个寄存器的值也设置为010,系统就可以正常运行了。

#define FLASH_ACR  0x40022000
#define rFLASH_ACR *((uint *)FLASH_ACR)void set_system_clock(void)
{rFLASH_ACR = 0x00000032;     //这个用来设置系统时钟于Flash访问时间的比率 根据系统时钟的不同设置的值不同RCC->CR &= (~(0x01 << 16));      //将HSEON这位清零RCC->CR |= (0x01 << 16);         //开启外部HSE振荡器电路do                               //判断外部HSE电路是否就绪{HSERDY_FLAG = ((RCC->CR) & (0x01 << 17));false_time++;}while((false_time < 0x00ffffff) && (HSERDY_FLAG == 0));false_time = 0;if (HSERDY_FLAG != 0)            //如果外部振荡器电路就绪才会执行{ RCC->CFGR &= (~((0x01 << 17) | (0x01 << 16) | (0x0f << 18)));  //设置PLL倍频系数为9倍频RCC->CFGR |= ((0x01 << 16) | (0x0 << 17) | (0x07 << 18));  //设置PLL时钟来源为PREDIV1 并且设置PLLXTPRE不对输入的时钟分频RCC->CR &= (~(0x01 << 24));       //使能PLL时钟RCC->CR |= (0x01 << 24);do {PLLRDY_FLAG = ((RCC->CR) & (0x01 << 25));false_time++;}while((false_time < 0x00ffffff) && (PLLRDY_FLAG == 0));  //等待PLL时钟就绪false_time = 0;if (((RCC->CR) & (0x01 << 25)) != 0){	RCC->CFGR &= (~((0x01 << 22) | (0x07 << 8)));  RCC->CFGR |= ((0x0 << 22) | (0x04 << 8));     //全速USB OTG配置为PLL输出2分频 APB1总线2分频 PLL输出作为系统时钟RCC->CFGR &= ~(0x03 << 0);  RCC->CFGR |= (0x02); do{SWRDY_FLAG = ((RCC->CFGR) & (0x03 << 2));false_time++;	}while((false_time < 0x00ffffff) && ((SWRDY_FLAG) == 0));if (((RCC->CFGR) & (0x03 << 2)) != 0){}else{while(1);}}}else{while(1);}
}

http://www.lryc.cn/news/487836.html

相关文章:

  • Github 2024-11-16Rust开源项目日报 Top10
  • CH03_反射
  • vue2侧边导航栏路由
  • core 不可变类型 线程安全 record
  • linux之调度管理(8)-SMP cpu 的 psci启动
  • review-消息中间件MQ
  • leetcode400第N位数字
  • 前端网页开发学习(HTML+CSS+JS)有这一篇就够!
  • CSS遮罩:mask
  • Swift闭包的本质
  • 时代变迁对传统机器人等方向课程的巨大撕裂
  • 【算法设计与分析实训】第1关:求序列的最大字段和
  • 【澜舟科技-注册/登录安全分析报告】
  • 【读书笔记-《网络是怎样连接的》- 7】Chapter3_2 路由器
  • Android Activity 基础接口知识和常见问题
  • 利用python 检测当前目录下的所有PDF 并转化为png 格式
  • 解决 Spring Boot 中 `Ambiguous mapping. Cannot map ‘xxxController‘ method` 错误
  • C++ 函数返回值优化
  • c++源码阅读__ThreadPool__正文阅读
  • 关于ES的查询
  • 数据结构初识
  • 保存数据到Oracle时报错ORA-17004: 列类型无效: 1111
  • Excel——宏教程(1)
  • 论文浅尝 | MindMap:知识图谱提示激发大型语言模型中的思维图(ACL2024)
  • 第6章:TDengine 标签索引和删除数据
  • 【微软:多模态基础模型】(5)多模态大模型:通过LLM训练
  • 海外带云仓多语言商城源码,多语言多商家云仓一键代发商城
  • android:taskAffinity 对Activity退出时跳转的影响
  • Apache Dolphinscheduler数据质量源码分析
  • solana链上智能合约开发案例一则