嵌入式学习笔记——STM32的时钟树
时钟树
- 前言
- 时钟树
- 时钟分类
- 时钟树框图
- LSI与LSE
- HSI、HSE与PLL
- 系统时钟的产生
- 举例
- AHB、APBx的时钟配置
- 时钟树相关寄存器介绍
- 1.时钟控制寄存器(RCC_CR)
- 2.RCC PLL 配置寄存器 (RCC_PLLCFGR)
- 3.RCC 时钟配置寄存器 (RCC_CFGR)
- 4.RCC 时钟中断寄存器 (RCC_CIR)
- 修改系统时钟配置为内部时钟
- 代码流程
- 编程代码
- 验证
- **使用NDK的Debug仿真查看STM32的系统频率的操作方式:**
- 总结
前言
在之前的所有代码编程的过程中,似乎每次都绕不开一个叫做时钟使能的东西,当时我们是在数据手册上直接看其挂接在那条时钟线上的,那么STM32内部的时钟到底是怎么一个构型呢,本文来对此做一个介绍。
时钟树
老规矩,一个新的名词出现,首先需要搞清楚它是个啥,下图中对时钟树给出了定义,STM32的时钟树是由多个时钟源和时钟分频组成的,为STM32芯片提供各种时钟信号。也就是说,在使用STM32的时候,所有的频率和时钟都是通过时钟树产生的。

时钟分类
在之前的嵌入式学习笔记——STM32硬件基础知识中的晶振电路部分提到过一嘴,STM32的基础时钟源有4个HSI振荡器时钟 、HSE振荡器时钟 、LSI振荡器时钟 、LSE振荡器时钟。这是最底层的时钟来源。
然后是上图中提到的PLL锁相环和SYSCLK系统时钟,前面提到过,此系列使用的STM32F407VE的主频是168Mhz,这个主频对应的就是SYSCLK系统时钟,而PLL锁相环就是这个系统时钟的直接来源。
在硬件篇介绍的时候,我们知道,外部晶振(也就是外部高速时钟HSE)的频率是25MHZ,内部振荡电路(对应内部高速时钟HSI)的频率是16Mhz,显然这两者都不能直接提供168MHZ的主频,那么系统时钟的168Mhz是怎么来的呢?
其实就是将HSI或者HSE接入PLL,通过PLL倍频产生的,具体的产生过程在后面的结构框图和寄存器介绍中描述。
系统时钟的来源:HSI振荡器时钟 HSE振荡器时钟 PLL锁相环
两个次级时钟源:LSI振荡器时钟 LSE振荡器时钟
H/L:高速/低速 SI/SE:内部/外部
时钟树框图
大致了解了时钟树的构成后,就可以来研究它的框图了,这是一张很复杂的图,还是按照之前的思路,对其进行一个拆分,把暂时不用的先排除,此图的下方红框里面的是一个I2S的音频处理专用的时钟,独立于其他的所有时钟,所以暂时不看它,绿框里面的是一个以太网的时钟,也是独立于其他所有模块,所以暂时也先不看,最下面的橙色框里的USB2.0时钟也是,这三个暂时都不需要看。


简化下半部分后,如下图所示,橙色框内的MCO1和MCO2使用来做测试脚的,使用示波器进行测量,测量频率是否正常的,所以这部分暂时也可以不看,进一步简化。

LSI与LSE
我们先来看上半部分的内部低速时钟LSI和外部低速时钟LSE;根据框图,可以发现紫色框的内部低速时钟频率为32KHZ,有两个分支,一个是为独立看门狗提供时钟,另一个是为RTC提供时钟。
而绿色的框是外部低速时钟,外接引脚OSC32_IN和OSC32_OUT就是接外部晶振的引脚,进来的频率是32.768KHZ进来后只有一个走向就是为RTC提供时钟。
然后需要注意的是蓝色框的四选一数据选择器,一共有三个输入,前两个是上面的LSI和LSE,还有一个来自下方的HSE,中间经过了一个/2到31的分频器,也就是说看门狗智能由内部低速时钟提供时钟,RTC可以由LSI、LSE、或者是HSE经过分频后来提供时钟,具体使用哪一个需要我们在代码里面配置。

HSI、HSE与PLL
丢掉了下面,看完了上面,删除了测试接口,接下来就到了本文的重头戏了,百分之90的片上外设的时钟都与这部分有关系。
首先,看图中的系统时钟(红色椭圆框),可以放发现,系统时钟也是通过一个选择器来选择的,输入源有三个,分别是来自橙色框的HSI(内部高速时钟),绿色框的HSE(外部高速时钟)以及蓝色框的PLL锁相环,也就是说,系统时钟可以有三个选择。
这里有一个问题,上面也提到过,系统时钟的直接来演应该选择哪一个输入?
由于内部高速时钟和外部高速时钟都无法提供168Mhz的频率,所以系统时钟的直接来源应该是PLLCLK,也就是说在配置的时候需要将系统时钟选择到锁相环上。

系统时钟的产生
那么问题来了,PLLCLK又是怎么产生168Mhz的频率的呢,我们放大这部分电路来做个解析,
如下图所示:
首先内部时钟HSI和外部时钟 HSE会来到绿色框的选择器,由我们编程控制具体选择HSI还是HSE;经过选择器选择后,会有一个分频器 “/M”一般这个M就是对应的多少M,
举个栗子:我们选择外部高速时钟作为锁相环的输入,此时的外部时钟频率是8MHZ,那么此处的分配就会采用8分频,将频率分频为1Mhz输入,方便后面的计算。
同样的,如果板子上没有外接晶振,只能选择内部高速时钟作为PLL的输入,此时内部高速时钟的频率是16Mhz,那么此处的分频系数就要配置为16,总之就是将对应输入的频率在此处转化为1Mhz,当然也可以是其他的值,只是1Mhz方便计算而已。

再经过选择器和分频器后,就正式进入了PLL锁相环了,这里我们结合寄存器的描述来解析:
首先1的位置就是VCO也就是经过分频后的1Mh频率,在其正下方有一个xN,这个xN是倍频的意思,此处的xN是需要我们编程时进行控制的,它的具体位置就是RCC PLL 配置寄存器 (RCC_PLLCFGR)的第6到14位,但是其写入值不是随意的,注意看下方的描述,我们写入的数据必须是192-432之间的值;

经过倍频后,会来到3的位置,这里有一个/P,根据上面的经验,这个肯定也是一个分频器,那么它的配置有没有要求呢,还是来看看寄存器的相关描述:它是由RCC PLL 配置寄存器 (RCC_PLLCFGR)的第16和17位控制的,注意最低分频也是2分频。

经过/P后就输出到SYSCLK的选择器了,至于下面的4和5暂时我们没有用上,所以这里不做介绍,想要了解的自己去中文编程手册查看。
举例
好了,到这里已经知道了系统频率是怎么产生的了,举两个例子吧,
第一种,选择外部时钟作为PLL的输入,外部时钟是8MHZ,主频是168MHZ,那么有关PLL的配置流程应该是怎样的?
//此处伪代码主要是走一下计算流程实际流程会比这个多几个步骤
{1.绿框选择器选择HSE作为输入;2.橙框的分频系数设置为8分频,输出1Mhz的信号到VCO;3.配置2号位置的倍频系数,系数要求是(192-433),由于后面还有个最低的2分频,所以此处要配置为336(168*2);4.配置3号位置分频器为00,二分频,这样就实现了一个168MHZ的系统频率
}
第二种,没有外部接晶振电路,或者说板子的外接晶振电路挂逼了,此时应该如何配置系统的时钟为200MHZ(对于F407来说,200MHZ的频率算超频,如非特殊需求必要,不建议这么操作,会拉高功耗而且造成不稳定)
//此处伪代码主要是走一下计算流程实际流程会比这个多几个步骤
{1.绿框选择器选择HSI作为输入;2.橙框的分频系数设置为16分频,输出1Mhz的信号到VCO;(内部高速时做的频率为16MHZ)3.配置2号位置的倍频系数,系数要求是(192-433),由于后面还有个最低的2分频,所以此处要配置为400(200*2);4.配置3号位置分频器为00,二分频,这样就实现了一个200MHZ的系统频率
}
AHB、APBx的时钟配置
上面一段主要是介绍了系统时钟的具体生成过程,这个时钟框图还剩下最后一块,就是我们前面配置时经常使用到的AHB、APB1、APB2这些。

如上图所示,经左侧的选择器选择后,最终的SYSCLK的频率是168MHZ,紧接着往右就分成了两条路线一条向上直接是给到了以太网时钟,这个暂时用不上,可以暂时性忽略;另一路则是来到了AHB,下面有一个分频器,意思是可以配置AHB分频为1,2,4,8,16分频,这个具体的我们也看一眼,对应的寄存器描述:其具体的控制是由RCC 时钟配置寄存器 (RCC_CFGR)的第4到第7位来实现的。

然后再往后走,又分成了两路,这次先看下面的这一路,可以看见首先来到了2位置的APBx的分频控制,关于它的具体配置也是有对应的寄存器位的,如下图:其中APB1占RCC 时钟配置寄存器 (RCC_CFGR)的10-12位
APB2占RCC 时钟配置寄存器 (RCC_CFGR)的13-15位
然后还有对应的要求,APB1不能超过42MHZ,AOB2不能超过84Mhz。

通过这个就可以为大多是外设提供所需的时钟了,但是下面还有个框4,里面是一个判断语句,如果APBx是1分频,则×1给到定时器,如果APBx不是1分频,则需要×2后再给到定时器。
最后,还有一个遗留的就是经过AHB后向上去的,那个最后是给内核提供时钟了,还有个是经过8分频后位系统时钟提供时钟,也就是下一篇会介绍的系统滴答(SYS_Tick),这个到下一篇再说。
时钟树相关寄存器介绍
整个时钟相关的寄存器都在中文编程手册的第6.3章,主要包括三大类:1.时钟配置寄存器部分 ;2.外设复位寄存器部分 3.外设使能寄存器部分;

这里重点是如何配置时钟,所以需要使用到的是第一大类,时钟配置相关的寄存器。
1.时钟控制寄存器(RCC_CR)

写法:RCC->CR
功能: 1.打开对应的时钟源 HIS HSE PLL;2.用以判断对应的时钟是否准备好。
配置过程中需要使用到的具体位:
位 0 HSION:内部高速时钟使能 (Internal high-speed clock enable)
置1:打开HSI时钟
置0:关闭HSI时钟
写操作,时钟并不是立刻打开的
位 1 HSIRDY:内部高速时钟就绪标志 (Internal high-speed clock ready flag)
为1:表示HSI时钟开启成功
为0:表示HSI时钟还没有开启成功
读操作
位 16 HSEON:HSE 时钟使能 (HSE clock enable)
置1:打开HSE时钟
置0: 关闭HSE时钟
位 17 HSERDY:HSE 时钟就绪标志 (HSE clock ready flag)
为1:表示HSE时钟开启成功
为0:表示HSE时钟还没有开启成功
位 24 PLLON:主 PLL (PLL) 使能 (Main PLL (PLL) enable)
置1:打开锁相环
置0:关闭锁相环
位 25 PLLRDY:主 PLL (PLL) 时钟就绪标志 (Main PLL (PLL) clock ready flag)
为1:表示PLL开启成功
为0:表示PLL还没有开启成功
PLL的锁相环具备写保护,在PLL锁相环运行状态的时候,不能进行相关配置
其他位的相关介绍请参考手册。
2.RCC PLL 配置寄存器 (RCC_PLLCFGR)
这个寄存器在上面介绍PLL的流程的时候已经大致看过了,其作用就是配置PLL的各项参数,产生系统所需的168MHZ的频率。
写法:RCC->PLLCFGR
功能:配置PLL锁相环,注意:配置过程中需要先操作上一个寄存器关闭锁相环
位 5:0 PLLM:主 PLL (PLL) 和音频 PLL (PLLI2S) 输入时钟的分频系数 (Division factor for the main PL(PLL) and audio PLL (PLLI2S) input clock)
可以配置相应的分频
写入值:2~63 可写入的值有限制
位 14:6 PLLN:适用于 VCO 的主 PLL (PLL) 倍频系数 (Main PLL (PLL) multiplication factor for VCO)
可以配置相应的倍频
写入值:192~432 可写入的值有限制
位 17:16 PLLP:适用于主系统时钟的主 PLL (PLL) 分频系数 (Main PLL (PLL) division factor for main system clock)
可以配置相应的分频,对应的分频有自己的参数
00:PLLP = 2
01:PLLP = 4
10:PLLP = 6
11:PLLP = 8
位 22 PLLSRC: 主 PLL(PLL) 和音频 PLL (PLLI2S) 输入时钟源 (Main PLL(PLL) and audio PLL
(PLLI2S) entry clock source)
由软件置 1 和清零,用于选择 PLL 和 PLLI2S 时钟源。此位只有在 PLL 和 PLLI2S 已禁止时
才可写入。
0:选择 HSI 时钟作为 PLL 和 PLLI2S 时钟输入
1:选择 HSE 振荡器时钟作为 PLL 和 PLLI2S 时钟输
此位就是上面框图中的绿色选择框,选择HSI或者是HSE作为PLL的输入。
3.RCC 时钟配置寄存器 (RCC_CFGR)
此寄存器的主要作用就是对AHB、APB1、APB2等进行时钟配置,也就是上面框图讲解的最后一部分的控制内容。

写法:RCC->CFGR
功能:配置相应时钟总线时钟,选择系统时钟的来源
位 1:0 SW:系统时钟切换 (System clock switch)
00:选择HSI作为系统时钟时钟源
01:选择HSE作为系统时钟时钟源
10:选择PLL作为系统时钟时钟源
位 3:2 SWS:系统时钟切换状态 (System clock switch status)
为00:表示HIS选择成功
为01:表示HSE选择成功
为10:表示PLL选择成功
具体写法:
while(!(PLL->CFGR & (1<<3)));
//等待系统时钟切换成HIS
while ( RLL->CFGR & (3<<2) );
位 7:4 HPRE:AHB 预分频器 (AHB prescaler)
可以修改AHB总线的频率
0xxx:系统时钟不分频
1000:系统时钟 2 分频
1001:系统时钟 4 分频
1010:系统时钟 8 分频
1011:系统时钟 16 分频
1100:系统时钟 64 分频
1101:系统时钟 128 分频
1110:系统时钟 256 分频
1111:系统时钟 512 分频
位 15:10 PPRE1:APBx分频器
0xx:AHB 时钟不分频
100:AHB 时钟 2 分频
101:AHB 时钟 4 分频
110:AHB 时钟 8 分频
111:AHB 时钟 16 分频
4.RCC 时钟中断寄存器 (RCC_CIR)
功能:在上面各个配置过程中,各类时钟准备就绪就会进入中断执行操作,默认不操作,在这里一般不需要执行中断。所以这个寄存器基本上不操作的。
修改系统时钟配置为内部时钟
在搞清楚了框图以及对应的寄存器后,就可以尝试配置一个时钟了,这里实现这样一个需求,使用HSI作为基础时钟源配置系统时钟200Mhz,APB2为50MHZ;APB1为25MHZ。
这类需求一般不常用,但是一旦拿到的板子没有外接晶振或者说自己画的板子外接晶振挂了,不工作,就可以采用类似的操作,将PLL时钟源选择为HSI,进而为整个系统提供时钟源。
代码流程
还是老规矩,先写一个伪代码来理清思路:
ST的默认时钟文件------HSE
HSI系统时钟配置的初始化函数
{打开HSI的时钟振荡器等待HSI准备就绪先切换系统时钟到HSI//由于系统运行过程中不能没有时钟,而配置PLL又需要先将PLL关闭,所以需要执行此操作,现将系统时钟暂时切换到HSI。等待系统时钟切换成功关闭锁相环选择锁相环需要的时钟源配置M分频配置N倍频配置P分频打开PLL锁相环等待PLL锁相环锁定系统时钟切换回PLL锁相环等待系统时钟准备就绪
}
编程代码
还是一样的需要新建文件然后导入工程,这里就不再一步一步的演示了
//配置代码:
#include "Hsi.h"/*******************************************
*函数名 :HSI_Init
*函数功能 :初始化HSI函为系统时钟
*函数参数 :无
*函数返回值:无
*函数描述 :
将系统时钟调整为200MHZ
APB2为50MHZ
APB1为25MHZ
*********************************************/
void HSI_Init(void)
{RCC->CR |=(1<<0);//打开HSI的适中振荡器while(!(RCC->CR & (1<<1)));//等待HSI就位RCC->CFGR &= ~(3<<0);//将系统时钟暂时切换至HSIwhile(RCC->CFGR & (3<<2));//等待时钟切换完成RCC->CR &=~(1<<24);//关闭锁相环RCC->PLLCFGR &=~(1<<22);//PLL选择HSI为输入时钟源RCC->PLLCFGR &=~(0X3F<<0);//清零RCC->PLLCFGR |=(16<<0); //M16分频RCC->PLLCFGR &=~(0X1FF<<6);//清零RCC->PLLCFGR |=(400<<6); //N倍频 400RCC->PLLCFGR &=~(3<<16);//P分频 2RCC->CR |=(1<<24);//打开锁相环while(!(RCC->PLLCFGR & (1<<25)));//等待锁相环锁定//切换回PLL作为系统时钟RCC->CFGR |= (1<<1);//将系统时钟暂时切换回PLLwhile(!(RCC->CFGR & (1<<3)));//等待时钟切换完成RCC->CFGR &=~(0xf<<4);//清零,将AHB时钟设置为不分频200MHZRCC->CFGR &=~(0x7<<10);//清零RCC->CFGR |=(0x6<<10);//将APB1的时钟设置为25MHZ8分频RCC->CFGR &=~(0x7<<13);//清零RCC->CFGR |=(0x5<<13);//将APB2的时钟设置为50MHZ//4分频}//.H:
#ifndef _HSI_H
#define _HSI_H
#include "stm32f4xx.h"void HSI_Init(void);
#endif
验证
效果:由于APB2的时钟变成了50MHZ所以一种检验方式如下图,修改BRR内对应的频率为50MHZ然后编译下载,串口助手可以正常打印就说明正常。

另外一种检验方式就是添加库函数,调用对应库函数即可查看。
未修改之前的主频是168Mhz,如下图右下的框图所示。

修改后的主频是200MHZ,APB1的频率是25MHZ,APB2的频率是50MHZ。

使用NDK的Debug仿真查看STM32的系统频率的操作方式:
1.需要使用到库函数,要找一个库函数的代码,复制对应的
“stm32f4xx_rcc.h” 和对应的"stm32f4xx_rcc.c"到自己工程目录下并添加进工程;使用库函数的同学可以直接在自己的库里面找,将其添加进工程即可。
2.使用寄存器的小伙伴记得打开stm32f4xx_rcc.h,
添加一个宏定义“ #define assert_param(expr) ((void)0)”,使用库函数的同学直接跳转至第3步。

3.在main.h包含头文件“stm32f4xx_rcc.h”,然后再main.c声明一个结构体变量
RCC_ClocksTypeDef Get_Rcc_Clock; //声明一个结构体变量,获取系统时钟状态
4.在单次运行代码的位置,添加:
RCC_GetClocksFreq(&Get_Rcc_Clock); //仿真的时候就可以在结构体get_rcc_clock中看见各个外设的时钟了

5.编译通过后,点击Debug按钮,来到如下界面,在右下角底部找到“Call Stack + Locals”,选中;然后点击2位置的全速运行,等待3秒,然后点击叛变的停止运行,4对应的框会出现对应的频率。

此时频率还是16进制的数,为了方便查看,随便选择一个变量选中,然后右键弹出2位置的16进制显示,把这个复选框取消即可。


STM32F4获取并查看当前系统时钟频率——http://t.csdn.cn/E9ATa
STM32获取当前系统时钟——http://t.csdn.cn/uPwvO
此法是仿真的频率并不是实际采集的频率,只是理论值,实际最好还是采用上一种串口修改频率不乱码的方案来解决。
总结
本文主要是介绍了STM32的是时钟树,捋了一下时钟的配置流程,文中如有不足还请指出。
相关文章:
嵌入式学习笔记——STM32的时钟树
时钟树前言时钟树时钟分类时钟树框图LSI与LSEHSI、HSE与PLL系统时钟的产生举例AHB、APBx的时钟配置时钟树相关寄存器介绍1.时钟控制寄存器(RCC_CR)2.RCC PLL 配置寄存器 (RCC_PLLCFGR)3.RCC 时钟配置寄存器 (RCC_CFGR)4.RCC 时钟中断寄存器 (RCC_CIR)修改…...
Python学习(2)-NumPy矩阵与通用函数
文章首发于:My Blog 欢迎大佬们前来逛逛 1. NumPy矩阵 1.1 mat函数 matasmatrix asmatrix(data, dtypeNone):data:表示输入的数组或者字符串,使用‘,’分割列,使用‘;’分割行 创建两个普通的矩阵&…...
剑指 Offer II 035. 最小时间差
题目链接 剑指 Offer II 035. 最小时间差 mid 题目描述 给定一个 24小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1: 输入:timePoints [“23:59”,“0…...
Spark SQL函数定义【博学谷学习记录】
1 如何使用窗口函数窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count()第三类: la…...
模拟实现STL容器之vector
文章目录前言1.大体思路2.具体代码实现1.类模板的创建2.构造函数1.无参构造2.拷贝构造 迭代器构造和给定n个val值构造以及析构函数3.空间扩容1.reserve2.resize4.操作符重载1.[ ]重载2.赋值运算符重载5.数据增加和删除1.尾插2.任意位置插入3.任意位置删除4.尾删6.一些其他接口3…...
ChatGPT-4.0 : 未来已来,你来不来
文章目录前言ChatGPT 3.5 介绍ChatGPT 4.0 介绍ChatGPT -4出逃计划!我们应如何看待ChatGPT前言 好久没有更新过技术文章了,这个周末听说了一个非常火的技术ChatGPT 4.0,于是在闲暇之余我也进行了测试,今天这篇文章就给大家介绍一…...
Java反射(详细学习笔记)
Java反射 1. Java反射机制概述 Reflection(反射)是java被视为java动态语言的关键,反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。 Class c Class.forName(&quo…...
学习 Python 之 Pygame 开发魂斗罗(十二)
学习 Python 之 Pygame 开发魂斗罗(十二)继续编写魂斗罗1. 修改玩家扣减生命值2. 解决玩家下蹲子弹不会击中玩家而是直接让玩家死亡的问题3. 完善地图4. 增加产生敌人函数,解决一直产生敌人的问题5. 给玩家类增加计算玩家中心的方法继续编写魂…...
Linux下字符设备驱动开发以及流程介绍
文章目录1 - 字符设备介绍2 - 字符设备开发流程图3 - 字符设备开发流程具体讲解(1)设备编号的定义与申请【1】Linux主次设备号介绍【2】分配设备编号【3】释放主次设备号(2)定义file_operations结构体-初始化接口函数(…...
Web自动化框架断言方法实现
前言1、设计用例方法关键字1.1、获取元素属性值2.1、断言2、代码实现2.1、实现获取元素属性值2.1.1 函数实现2.1.2 方法配置2.1.2 用例调试2.1.3 html属性2.2、实现断言2.2.1 函数2.2.2 方法配置2.2.3 用例调试1)断言结果成功2)断言结果失败前言 本文的…...
8大核心语句,带你深入python
人生苦短 我用python 又来给大家整点好东西啦~ 咱就直接开练噜!内含大量代码配合讲解 python 安装包资料:点击此处跳转文末名片获取 1. for - else 什么?不是 if 和 else 才是原配吗? No,你可能不知道, else 是个…...
【批处理】- 批处理自动安装Mysql与Redis
前言 在全新环境中安装MySQL与Redis操作是挺麻烦的,于是就想使用脚本来自动安装,使用批处理进行一步到位的安装,后面还能使用工具进行打包成exe可执行文件,一键安装,最后能够更好的部署项目到windows系统的服务器。 …...
聊聊华为的工作模式
目录 一、试用期与加班工资 二、招聘 三、月度答辩和转正答辩 四、可信考试认证 五、接口人 六、问题缺陷单 七、代码检视 八、功能开发 九、出征海外 一、试用期与加班工资 一般而言,试用期持续的时间为3-6个月,工资、奖金都按正式员工的标准…...
燕山大学-面向对象程序设计实验-实验6 派生与继承:多重派生-实验报告
CSDN的各位友友们你们好,今天千泽为大家带来的是燕山大学-面向对象程序设计实验-实验5 派生与继承:单重派生-实验报告,接下来让我们一起进入c的神奇小世界吧,相信看完你也能写出自己的 实验报告!本系列文章收录在专栏 燕山大学面向对象设计报告中 ,您可以在专栏中找…...
分割两个字符串得到回文串[抽象--去除具体个性取共性需求]
抽象前言一、分割两个字符串得到回文串二、双指针总结参考文献前言 抽象去个性留共性,是因为具体个性对于解决问题是个累赘。少了累赘,直击需求,才能进行问题转换或者逻辑转换。 一、分割两个字符串得到回文串 二、双指针 // 限定死了&…...
【LeetCode】1609. 奇偶树、1122. 数组的相对排序
作者:小卢 专栏:《Leetcode》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 1609. 奇偶树 1609. 奇偶树 题目描述: 如果一棵二叉树满足下述几个条件&#x…...
【C++初阶】4. Date类的实现
如果下面博客有不理解的地方,可以查看源码:代码提交:日期类的实现 1. 构造函数的实现 由于系统实现的默认构造函数即便采用默认值的形式也只能存在1个固定的默认日期(例如:1997-1-1)。所以,构…...
ES6新特性--变量声明
可以使用let关键字来声明变量let a;let b,c;//同时声明多个变量let stu = 张三;let name =李四,age = 12;//声明变量的同时赋值 let关键字使用的注意事项(1).变量在声明的时候不可以重复,这也符合其他语言的变量声明规范 let name = 李四; let name = 张三;//这里开始报错,但…...
【Django】缓存机制
文章目录缓存的介绍Django的6种缓存方式开发调试缓存dummy.DummyCache内存缓存locmem.LocMemCache文件缓存filebased.FileBasedCache⭐️数据库缓存db.DatabaseCacheMemcache缓存memcached.MemcachedCacheMemcache缓存memcached.PyLibMCCacheDjango缓存的应用内存缓存cache_pag…...
我的创作纪念日——一年的时间可以改变很多
机缘 不知不觉来到CSDN已经创作一年了。打心底讲,对于在CSDN开始坚持创作的原因,我用一句话来概括最合适不过了——“无心插柳柳成荫” 为什么这么说呢? 这要从我的一篇博客说起——《输入命令Javac报错详解》: 那也是我第一次…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
