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 int
	
typedef 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);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/920222.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu无密码用SCP复制文件到windows

默认情况下,ubuntu使用scp复制文件到windows需要输入密码: scp *.bin dev001@172.16.251.147:~/Desktop/. 为了解决每次复制文件都要输入密码这个问题,需要按如下操作: 1.创建ssh密钥 ssh-keygen -t ed25519 -C "xxx_xxx_xxx@hotmail.com" 2.使用scp复制公钥到w…

vulfocus在线靶场:CVE-2018-7600 速通手册

目录 一、启动环境&#xff0c;访问页面&#xff0c;语言选择中文&#xff0c;打开phpmyadmin 二、phpmyadmin中打开小房子 三、选择显示php信息 四、ctrlF&#xff0c;搜索flag&#xff0c;复制粘贴到任务中&#xff0c;通关 一、启动环境&#xff0c;访问页面&#xff0c;…

vue3 element el-table实现表格动态增加/删除/编辑表格行,带有校验规则

需求描述 在项目中遇到需要实现表格动态的新增、编辑、删除表格行的需求&#xff0c;同时带有校验规则 代码解决 点击新增的时候&#xff0c;给新增row默认属性&#xff0c;给相应的默认值&#xff0c;包括给一个isEditor: true&#xff0c;用来区分是否需要编辑。同时当有编…

python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具

python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具 文章目录 python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具项目背景技术栈用户界面核心功能实现结果展示完整代码总结 在现代软件开发中&#xff0c;测试接口的有效性与响应情况变得尤为重要。本文将指导…

MySQL社区版的启动与连接

1.启动&#xff1a; 注意&#xff1a;MySQL是默认开机自启的 方式一&#xff1a; 1.WinR 的命令行中直接输入services.msc 2.在服务中找到数据库名称&#xff0c;然后鼠标右键点击启动 方式二&#xff1a; 1.在开始选项中搜索“cmd”命令提示符&#xff0c;使用管理员身份运行 …

《Python浪漫的烟花表白特效》

一、背景介绍 烟花象征着浪漫与激情&#xff0c;将它与表白结合在一起&#xff0c;会创造出别具一格的惊喜效果。使用Python的turtle模块&#xff0c;我们可以轻松绘制出动态的烟花特效&#xff0c;再配合文字表白&#xff0c;打造一段专属的浪漫体验。 接下来&#xff0c;让…

【Linux学习】【Ubuntu入门】1-8 ubuntu下压缩与解压缩

1.Linux系统下常用的压缩格式 常用的压缩扩展名&#xff1a;.tar、.tar.bz2、.tar.gz 2.Windows下7ZIP软件安装 Linux系统下很多文件是.bz2&#xff0c;.gz结尾的压缩文件。 3.Linux系统下gzip压缩工具 gzip工具负责压缩和解压缩.gz格式的压缩包。 gzip对单个文件进行…

Ubuntu问题 -- 允许ssh使用root用户登陆

目的 新重装的系统, 普通用户可以使用ssh登陆服务器, 但是root不能使用ssh登陆 方法 vim 编辑ssh配置文件 sudo vim /etc/ssh/sshd_config找到 PermitRootLogin 这一行, 把后面值改成 yes 重启ssh sudo service sshd restart然后使用root账号登陆即可

最新智能AI问答运营系统(SparkAi)一站式AIGC系统,GPT-4.0/GPT-4o多模态模型+联网搜索提问+AI绘画+管理后台,用户会员套餐

目录 一、文章前言 系统介绍文档 二、功能模块介绍 系统快速体验 三、系统功能模块 3.1 AI全模型支持/插件系统 AI大模型 多模态模型文档分析 多模态识图理解能力 联网搜索回复 3.2 AI智能体应用 3.2.1 AI智能体/GPTs商店 3.2.2 AI智能体/GPTs工作台 3.2.3 自定义…

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的&#xff0c;要进一步提高redis的并发能力可以搭建主从集群&#xff0c;实现读写分离&#xff0c;一主多从&#xff0c;主节点写数据&#xff0c;从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

Logback实战指南:基础知识、实战应用及最佳实践全攻略

背景 在Java系统实现过程中&#xff0c;我们不可避免地会借助大量开源功能组件。然而&#xff0c;这些组件往往功能丰富且体系庞大&#xff0c;官方文档常常详尽至数百页。而在实际项目中&#xff0c;我们可能仅需使用其中的一小部分功能&#xff0c;这就造成了一个挑战&#…

如何编译 Cesium 源码

如何编译 Cesium 源码 Cesium 是一个开源的 JavaScript 库&#xff0c;用于构建 3D 地球和地图应用程序。它提供了一套强大的 API 和工具&#xff0c;使开发者能够创建丰富的地理空间应用。本文将指导您如何从 GitHub 下载 Cesium 源码&#xff0c;并在本地进行编译。 TilesB…

短视频矩阵系统是什么?有什么功能?

短视频矩阵系统是什么&#xff1f;短视频矩阵系统是一个为视频创作者和运营者提供全面服务的综合平台&#xff0c;它涵盖了多账号管理、人工智能驱动的剪辑制作、定时自动发布功能、智能评论回复、跨平台流量引导及营销成果分析等多项功能。该系统利用先进的技术手段优化、管理…

鸿蒙实战:页面跳转传参

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙项目2.2 编写首页代码2.3 新建第二个页面 3. 测试效果4. 实战总结 1. 实战概述 本次实战&#xff0c;学习如何在HarmonyOS应用中实现页面间参数传递。首先创建项目&#xff0c;编写首页代码&#xff0c;实现按钮跳转至第二个页面并…

windows 和 linux检查操作系统基本信息

windows检查操作系统基本信息 systeminfolinux检查操作系统基本信息 获取系统位数 getconf LONG_BIT查询操作系统release信息 lsb_release -a查询系统信息 cat /etc/issue查询系统名称 uname -a

【WPF】Prism学习(九)

Prism Dependency Injection 1.Container Locator 1.1. Container Locator的引入&#xff1a; Container Locator是在Prism 8.0版本中新引入的一个特性。它的目的是为了帮助Prism框架摆脱对CommonServiceLocator的依赖&#xff0c;并解决一些必须回退到ServiceLocator模式的内…

webgl threejs 云渲染(服务器渲染、后端渲染)解决方案

云渲染和流式传输共享三维模型场景 1、本地无需高端GPU设备即可提供三维项目渲染 云渲染和云流化媒体都可以让3D模型共享变得简单便捷。配备强大GPU的远程服务器早就可以处理密集的处理工作&#xff0c;而专有应用程序&#xff0c;用户也可以从任何个人设备查看全保真模型并与…

Linux的指令(三)

1.grep指令 功能&#xff1a; 在文件中搜索字符串&#xff0c;将找到的行打印出来 -i&#xff1a;忽略大小写的不同&#xff0c;所以大小写视为一样 -n&#xff1a;顺便输出行号 -v:反向选择&#xff0c;就是显示出没有你输入要搜索内容的内容 代码示例&#xff1a; roo…

Linux驱动开发(7):使用设备树实现RGB 灯驱动

通过上一小节的学习&#xff0c;我们已经能够编写简单的设备树节点&#xff0c;并且使用常用的of函数从设备树中获取我们想要的节点资源。 这一小节我们带领大家使用设备树编写一个简单的RGB灯驱动程序&#xff0c;加深对设备树的理解。 1. 实验说明 本节实验使用到 EBF6ULL-…

无人机的激光雷达避障系统阐述!

一、材料 激光二极管基底材料&#xff1a;激光二极管是激光雷达的核心组件之一&#xff0c;其基底材料通常采用硅或砷化镓。硅材料成本低、易于加工&#xff0c;但发光效率相对较低&#xff1b;而砷化镓材料发光效率高&#xff0c;但成本较高。 光学镜片材料&#xff1a;激光…