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

【STM32】时钟设置函数(寄存器版)

一、STM32时钟设置函数移植

1.时钟模块回顾

一个疑问

前面代码并没有设置时钟为什么可以直接使用。

2.时钟树

3.时钟树分析

1.内部晶振(HSI)

内部晶振不稳定,当我们上电后,会自动产生振动,自动产生时钟,但是晶振不稳定。

不经过PPLMUL,默认使用8MHZ。所以如果我们想要72MHZ,则需要使用外部晶振

  2.外部晶振(HSE)

当接上外部晶振,当接通电源之后,不用软件操作,会自动产生振动。可以进行分频等操作。

从外部接上外部晶振的时候,我们需要等待一段时间,让其稳定后,才开始工作。(所以要进行判断)

3.PLLMUL

当上电后,经过他时,要等待一段时间,让其稳定后,才可以开始工作。(所以我们有一个寄存器专门用来判断其是否准备好开始工作,当我们去读取到其准备好了才可以进行下一步)

二、代码移植

#ifndef __CLOCK_H__
#define __CLOCK_H__#include "gpio.h"// 寄存器宏定义
// RCC寄存器基地址为0x40021000
#define RCC_BASE	0x40021000			// RCC部分寄存器的基地址
#define RCC_CR		(RCC_BASE + 0x00)	// RCC_CR的地址
#define RCC_CFGR	(RCC_BASE + 0x04)#define FLASH_ACR	0x40022000// 用C语言来访问寄存器的宏定义
#define rRCC_CR		(*((volatile unsigned int *)RCC_CR))
#define rRCC_CFGR	(*((volatile unsigned int *)RCC_CFGR))
#define rFLASH_ACR	(*((volatile unsigned int *)FLASH_ACR))// 函数作用:时钟源切换到HSE并且使能PLL,将主频设置为72MHz
void Set_SysClockTo72M(void);#endif

1.复位RCC_CR寄存器

#define rRCC_APB2ENR     (*((unsigned int *)RCC_APB2ENR))

RCC->CR就相当于rRCC_APB2ENR

	//复位RCC_CR寄存器rRCC_CR=0x00000083;

2.开启外部时钟(就是开启外部晶振)

&:将某一些位置0

|:将某一些位置1

	//开启外部时钟(外部晶振)//第一步:先置0【将bit16清零】rRCC_CR &= ~(1<<16);//关闭HSEON//第二步:在置1rRCC_CR |= (1<<16);//打开HSEON,让HSE开始工作

3.检测外部时钟开启是否成功(HSEREDY)

do while十分适合检测是否超时!!!!!!!

	do{//检测HSEREAY(bit17)是否为1,1表示准备好Rcc_CR_HSE_Ready=rRCC_CR&(1<<17);//取出bit17faultTime++;}while((faultTime<0x0fffffff) && (Rcc_CR_HSE_Ready==0))//跳出do-while 1)要么超时2)要么准好了

4.当准备好进入下一步

5.Flash的设置

		rFLASH_ACR |= 0x10;rFLASH_ACR &= (~0x03);rFLASH_ACR |= (0x02);

6.对其进行预分频

		//HPRE【AHB】:对应bit4-bit7:不分频(000)//PPRE1【APB1】:对应bit8-bit10:进行二分频(100)//PPRE2【APB2】:对应bit11-bit13:不分频(000)//AHB和APB2未分频,APB1被2分频//所以最终:AHB和APB2都是72MHZ,APB1是36MHZ//第一步:先置0rRCC_CFGR=(~((0x0f<<4) | (0x07<<8) | (0x07<<11)));//等价于:rRCC_CFGR=(~(0x3ff<<4));//第二步:置1rRCC_CFGR=(((0x0<<4) | (0x04<<8) | (0x0<<11)));

7.设置SHE为输入时钟,同时HSE不分频

		//设置为输入时钟:bit16//设置为不分频:bit17//第一步:先置0rRCC_CFGR &=(~((1<<16) | (1<<17)));//第二步:置1rRCC_CFGR |= ((1<<18) | (0<<17));

8.设置PLL倍频系数

因为我们在开发板上接上的外部晶振就是8MHZ,如果我们想要在内部使用72MHZ,则需要在内部进行分频率(9倍)

		//9分频:0111:0x07rRCC_CFGR &=(~(0x0f<<18));//清零bit18-bit21rRCC_CFGR |= (0x07<<18);//设置为9倍频

9.打开使能

		//七、打开PLL开关rRCC_CR |= (1<<24);

10.等待开启PLL开启成功

		//八、等待开启PLL开启成功do{Rcc_CR_PLL_Ready=rRcc_CR & (1<<25);//检测第25位是否为1faultTime++;}while((faultTime<0x0fffffff) && (Rcc_CR_PLL_Ready==0))

11.将PLL作为SYSCLK的时钟来源

			//到这里说明PLL已经稳定,可以用了,下面可以切换成外部时钟了rRCC_CFGR &=(~(0x03)<<0);rRCC_CFGR |=(0x10<<0);

12. 判断切换成PLL是否成功

		do{RCC_CF_SWS_PLL=rRCC_CFGR & (0x03<<2);//读出bit2-bit3faultTime++;//0x02<<2:表示此时转换成PLL}while((faultTime<0x0fffffff) && (Rcc_CR_PLL_Ready!=(0x02<<2)))

13.此时PLL转换成功

14.完整代码

#include "clock.h"void Set_SysClockTo72M(void){//检测外部晶振是否准备好unsigned int Rcc_CR_HSE_Ready=0;//等待开启PLL开启成功unsigned int Rcc_CR_PLL_Ready=0;//判断切换成PLL是否成功unsigned int RCC_CF_SWS_PLL=0;unsigned int faultTime=0;//判断等待是否超时//一、复位RCC_CR寄存器rRCC_CR = 0x00000083;//二、开启外部时钟(外部晶振)//第一步:先置0【将bit16清零】rRCC_CR &= ~(1<<16);//关闭HSEON//第二步:在置1rRCC_CR |= (1<<16);//打开HSEON,让HSE开始工作//三、检测外部时钟开启是否成功do{//检测HSEREAY(bit17)是否为1,1表示准备好Rcc_CR_HSE_Ready=rRCC_CR&(1<<17);//取出bit17faultTime++;}while((faultTime<0x0fffffff) && (Rcc_CR_HSE_Ready==0));//跳出do-while 1)要么超时2)要么准好了//判断是超时还是准备好//注意点:不能直接使用“Rcc_CR_HSE_Ready”因为rRCC_CR是需要读一次寄存器//但是读出的结果可能还未改变,所以一定不能直接使用if((rRCC_CR&(1<<17))!=0)//rRCC_CR&(1<<17)==1{//这里HSE就ready,下面再去配置PLL并且等待他ready//四、对其进行预分频//HPRE【AHB】:对应bit4-bit7:不分频(000)//PPRE1【APB1】:对应bit8-bit10:进行二分频(100)//PPRE2【APB2】:对应bit11-bit13:不分频(000)//AHB和APB2未分频,APB1被2分频//所以最终:AHB和APB2都是72MHZ,APB1是36MHZ//第一步:先置0rRCC_CFGR=(~((0x0f<<4) | (0x07<<8) | (0x07<<11)));//等价于:rRCC_CFGR=(~(0x3ff<<4));//第二步:置1rRCC_CFGR=(((0x0<<4) | (0x04<<8) | (0x0<<11)));//五、设置SHE为输入时钟,同时HSE不分频//选择HSE作为PLL输入并且HSE不分频//设置为输入时钟:bit16//设置为不分频:bit17//第一步:先置0rRCC_CFGR &=(~((1<<16) | (1<<17)));//第二步:置1,bit16rRCC_CFGR |= ((1<<18) | (0<<17));//六、设置PLL倍频系数//9分频:0111:0x07rRCC_CFGR &=(~(0x0f<<18));//清零bit18-bit21rRCC_CFGR |= (0x07<<18);//设置为9倍频//七、打开PLL开关rRCC_CR |= (1<<24);//八、等待开启PLL开启成功do{Rcc_CR_PLL_Ready=rRCC_CR & (1<<25);//检测第25位是否为1faultTime++;}while((faultTime<0x0fffffff) && (Rcc_CR_PLL_Ready==0));if((rRCC_CR & (1<<25)) == (1<<25)){//到这里说明PLL已经稳定,可以用了,下面可以切换成外部时钟了//九、切换成PLLrRCC_CFGR &=(~(0x03)<<0);rRCC_CFGR |=(0x10<<0);//十、判断切换成PLL是否成功do{RCC_CF_SWS_PLL=rRCC_CFGR & (0x03<<2);//读出bit2-bit3faultTime++;//0x02<<2:表示此时转换成PLL}while((faultTime<0x0fffffff) && (Rcc_CR_PLL_Ready!=(0x02<<2)));//十一、此时PLL转换成功if((rRCC_CFGR & (0x03<<2))==(0x02<<2)){//到这里我们的时钟整个就设置好了,可以结束了}else{//到这里说明PLL输出作为PLL失败while(1);}}else{//到这里说明PLL启动时出错了,PLL不能稳定工作while(1);}}else{//超时,或者未准备好,此时HSE不可以使用while(1);}}

三、问题解决

1.我们想要让led快速闪3下,然后换成72MHZ的频率接着闪

void delay(){unsigned int i=0,j=0;for(i=0;i<1000;i++){for(j=0;j<2000;j++){}}
}void led_init(){rRCC_APB2ENR = 0x00000008;rGPIOB_CRH = 0x33333333;rGPIOB_ODR = 0x0000ff00;//全灭}
void led_flash(void){unsigned int i=0;for(i=0;i<3;i++){rGPIOB_ODR = 0x00000000;//全亮delay();rGPIOB_ODR = 0x0000ff00;//全灭delay();} 
}
void main(void){led_init();led_flash();Set_SysClockTo72M();led_flash();
}

但是实际上并无法实现,只能在闪烁完3次后就熄灭。

2.问题解决

led初始化时,默认是全亮的

1.degger方法

把点亮led灯的函数加到clock中去,看看代码运行到哪里不会亮

2.判断超时变量的初始化

因为我们多次使用到超时变量,则每一个进入do-while循环之前要重新置0

3.出错点

相关文章:

【STM32】时钟设置函数(寄存器版)

一、STM32时钟设置函数移植 1.时钟模块回顾 一个疑问 前面代码并没有设置时钟为什么可以直接使用。 2.时钟树 3.时钟树分析 1.内部晶振&#xff08;HSI&#xff09; 内部晶振不稳定&#xff0c;当我们上电后&#xff0c;会自动产生振动&#xff0c;自动产生时钟&#xff0c;…...

【DDD】贫血模型和充血模型

基于业务开发的项目大多是MVC架构的。成为Web项目的标准开发模式&#xff0c;但它却是违反面向对象编程风格的&#xff0c;是面向过程的。之后基于领域驱动设计开发模式被人提倡。 DDD&#xff08;Domain-driven design&#xff09;领域驱动设计是一种通过将实现连接到持续进化…...

【JS学习】字符串的substring方法

1. 介绍 substring 是JavaScript字符串对象的一个方法&#xff0c;用于从一个字符串中提取子字符串&#xff0c;并返回提取的部分。 可以使用 substring 方法来截取字符串的一部分&#xff0c;指定起始索引和结束索引&#xff08;或只指定起始索引&#xff09;。 这个方法不…...

vue部署,chunk文件有部分404,解决方案

排查方案&#xff1a; 1&#xff0c;检查项目配置&#xff0c;再vue.config.js里面配置 publicPath: "./",2&#xff0c;打包后检查报错文件是否存在打包目录 3&#xff0c;如果1,2都有 找到部署后404的文件&#xff0c;查看是否为空文件 style里面全注释也会打包文…...

《红蓝攻防对抗实战》六.常规反弹之利用NC在windows系统执行反弹shell

目录 一.利用NC工具在windows系统执行反弹shell 1. Windows正向连接shell 2.Windows反向连接shell 前文推荐&#xff1a; 《红蓝攻防对抗实战》一. 隧道穿透技术详解《红蓝攻防对抗实战》二.内网探测协议出网之TCP/UDP协议探测出网《红蓝攻防对抗实战》三.内网探测协议出网…...

python如何创建自己的对冲交易算法

在这篇文章中&#xff0c;我解释了如何创建一个人工智能来每天为我进行自动交易。 随着机器学习的现代进步和在线数据的轻松访问&#xff0c;参与量化交易变得前所未有的容易。为了让事情变得更好&#xff0c;AWS 等云工具可以轻松地将交易想法转化为真正的、功能齐全的交易机器…...

Ubuntu22.04安装,SSH无法连接

Ubuntu初始化安装后&#xff0c;系统默认不允许root通过ssh连接&#xff0c;因此需要完成三个设置 1.修改ssh配置文件 vim /etc/ssh/sshd_config 将PermitRootLogin注释打开&#xff0c;并将值改为yes 保存修改并退出 :wq 2.重启ssh服务 sudo service ssh restart 3.重新打…...

解决dirsearch扫描工具pkg_resources模块警告问题

一、pkg_resources模块问题 ┌──(kali㉿kali)-[~/桌面/XXX/dirsearch-master] └─$ python dirsearch.py -h /home/kali/XX/XXXX/dirsearch-master/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io…...

JAVA-编程基础-11-04-java IO 字符流

Lison <dreamlison163.com>, v1.0.0, 2023.05.07 JAVA-编程基础-11-04-java IO 字符流 文章目录 JAVA-编程基础-11-04-java IO 字符流字符流Reader 和 Writer字符输入流&#xff08;Reader&#xff09;**FileReader构造方法****FileReader读取字符数据** 字符输出流&am…...

亚马逊云代码AI助手CodeWhisperer使用教程

一、CodeWhisperer 简介 1、CodeWhisperer是一款基于机器学习的通用代码生成器&#xff0c;由Amazon出品&#xff0c;可以给我们提供代码建议。 2、CodeWhisperer 基于各种上下文线索提供建议&#xff0c;包括光标在源代码中的位置、位于光标前面的代码、注释&#xff0c;以及…...

2023全新小程序广告流量主奖励发放系统源码 流量变现系统

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 分享软件&#xff0c;吃瓜视频&#xff0c;或其他资源内容&#xff0c;通过用户付费买会员来变现&#xff0c;用户需要付费&#xff0c;有些人喜欢白嫖&#xff0c;所以会流失一部分用户&#xff0c;所以就写了这个系统…...

最详细STM32,cubeMX外部中断

这篇文章将详细介绍 cubeMX外部中断的配置&#xff0c;实现过程。 文章目录 前言一、外部中断的基础知识。二、cubeMX 配置外部中断三、自动生成的代码解析四、代码实现。总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xff1a;keil5 &#xff0c; cubeMX 。实…...

云栖大会?全部免费!!抢先一步看!

2023云栖大会定档10月31日&#xff01; 点击链接免费预约云栖门票&#xff1a; 2023云栖大会-领票页面 2023 云栖大会将于 10.31-11.2 在杭州云栖小镇举办&#xff0c;深度拥抱大数据AI 核心技术&#xff0c;见证阿里云大数据AI产品年度重磅发布及创新。开放融合的科技展示平…...

Linux常用的调试工具

在开发和调试Linux的过程中&#xff0c;经常会遇到各种各样的问题&#xff0c;如程序崩溃、性能低下、内存泄漏等。这时候&#xff0c;调试就显得尤为重要。调试技巧和工具能够帮助开发人员快速定位问题并快速解决。在本文中&#xff0c;我们将介绍一些常用的Linux调试技巧和工…...

PX4-Autopilot下载与编译

文章目录 1 Git clone 代码2 下载子模块3 编译4 可能遇到的问题参考 1 Git clone 代码 Github Repository 链接&#xff1a;PX4-Autopilot 查看现有版本&#xff1a; 在终端用命令下载&#xff0c;-b表示branch git clone -b v1.14.0 https://github.com/PX4/PX4-Autopilot.…...

关于数据可视化那些事

干巴巴的数据没人看&#xff0c;数据可视化才能直观展现数据要点&#xff0c;提升数据分析、数字化运营决策效率。那关于可视化的实现方式、技巧、工具等&#xff0c;你了解几分&#xff1f;接下来&#xff0c;我们就来聊聊数据可视化那些事。 1、什么是数据可视化&#xff1f…...

【Java小知识点】类加载器的区别

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Java类加载器的区别&#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1faf0;&#x1faf…...

分布式微服务技术栈-SpringCloud<Eureka,Ribbon,nacos>

微服务技术栈 一、微服务 介绍了解1 架构结构案例与 springboot 兼容关系拆分案例拆分服务拆分-服务远程调用 2 eureka注册中心Eureka-提供者与消费者Eureka-eureka原理分析Eureka-搭建eureka服务Eureka-服务注册Eureka-服务发现 3 Ribbon组件 负载均衡Ribbon-负载均衡原理Ribb…...

Unity解决:导出AndroidStudio工程 出现如下报错的解决方法

unity2019.4+ androidStudio2023.x+ 问题1: cvc-complex-type.2.4.a: 发现了以元素 base-extension 开头的无效内容。应以 {layoutlib} 之一开头。 解决:第一个Build.gradle更改如下 // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING …...

Mac电脑怎么在Dock窗口预览,Dock窗口预览工具DockView功能介绍

DockView是一款Mac电脑上的软件&#xff0c;它可以增强Dock的功能&#xff0c;让用户更方便地管理和切换应用程序。 DockView的主要功能是在 DockQ&#xff0c;栏上显示每个窗口的缩略图&#xff0c;并提供了一些相关的操作选项。当用户将鼠标悬停在Dock栏上的应用程序图标上时…...

协程异常捕获失效?超时自动恢复失败?PHP 8.9 Fiber生产级错误处理全链路解析,

第一章&#xff1a;协程异常捕获失效&#xff1f;超时自动恢复失败&#xff1f;PHP 8.9 Fiber生产级错误处理全链路解析PHP 8.9 引入的 Fiber 原生协程机制虽大幅简化异步编程模型&#xff0c;但在生产环境中频繁暴露异常穿透、超时未中断、错误上下文丢失等关键问题。根本原因…...

Android逆向进阶:深入理解CRC检测与Frida绕过技巧

Android逆向工程实战&#xff1a;CRC检测机制深度解析与Frida高级对抗策略 在移动安全领域&#xff0c;Android应用的防护手段日益复杂&#xff0c;其中基于CRC&#xff08;循环冗余校验&#xff09;的内存校验机制已成为主流反调试方案的核心组件。这种技术通过比对文件与内存…...

CogVideoX-2b实战落地:中小企业低成本视频制作新路径

CogVideoX-2b实战落地&#xff1a;中小企业低成本视频制作新路径 1. 引言&#xff1a;视频制作的门槛&#xff0c;真的降下来了吗&#xff1f; 对于很多中小企业的市场、运营或内容团队来说&#xff0c;制作一个高质量的视频&#xff0c;曾经是一件既费钱又费时的事情。要么外…...

告别CUDA!用OpenAI Triton写GPU Kernel,Python开发者也能玩转高性能计算

用Python解锁GPU算力&#xff1a;OpenAI Triton实战指南 当Python遇上GPU计算&#xff0c;传统路径总是绕不开CUDA C的陡峭学习曲线。但现在&#xff0c;OpenAI Triton正在改写这一规则——它让开发者能够用熟悉的Python语法编写高性能GPU内核&#xff0c;像操作NumPy数组一样自…...

三、选择排序

算法原理一种简单直观的排序算法&#xff0c;其基本思想是每次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完。排序步骤初始化&#xff1a;在未排序序列中找到最小&#xf…...

避坑指南:MediaPipe安装常见报错解决方案(附虚拟环境配置技巧)

MediaPipe实战避坑手册&#xff1a;从环境配置到高效开发的完整指南 在计算机视觉和机器学习领域&#xff0c;MediaPipe作为Google开源的多媒体处理框架&#xff0c;因其强大的实时感知能力和跨平台特性而备受开发者青睐。然而&#xff0c;许多开发者在初次接触MediaPipe时&…...

OpenClaw配置备份:Qwen3-14b_int4_awq环境迁移与恢复指南

OpenClaw配置备份&#xff1a;Qwen3-14b_int4_awq环境迁移与恢复指南 1. 为什么需要备份OpenClaw配置 上周我经历了一次痛苦的教训——因为系统重装&#xff0c;丢失了精心调校的OpenClaw配置。那些花了几周时间调试的模型参数、飞书机器人集成设置、自定义技能模块全部归零。…...

二极管工作原理与应用全解析

1. 二极管基础认知&#xff1a;电子世界的单向阀门我第一次接触二极管是在大学电子实验课上&#xff0c;当时看着这个小小的玻璃管状元件&#xff0c;很难想象它能在电路中起到如此关键的作用。直到亲眼目睹它只允许电流单向通过的特性&#xff0c;才真正理解为什么工程师们称它…...

如何用IBAnimatable与Swift Concurrency打造流畅异步动画:完整指南

如何用IBAnimatable与Swift Concurrency打造流畅异步动画&#xff1a;完整指南 【免费下载链接】IBAnimatable Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable. …...

VS Code开发STM32:高效嵌入式开发环境搭建指南

1. 为什么选择VS Code开发STM32&#xff1f; 作为一名嵌入式开发工程师&#xff0c;我最初接触STM32开发时使用的也是Keil MDK。但随着项目复杂度提升&#xff0c;Keil的局限性逐渐显现&#xff1a;收费高昂&#xff08;虽然可以找到特殊版本&#xff09;、代码补全功能弱、界…...