【STM32】RTC实时时钟

1 unix时间戳

Unix 时间戳(Unix Timestamp)定义为从UTC/GMT197011000秒开始所经过的秒数,不考虑闰秒

时间戳存储在一个秒计数器中,秒计数器为32/64位的整型变量

世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间

(1)简化硬件电路;(2)方便计算时间间隔;(3)存储方便。

(1)占用软件资源;

时间戳工具:时间戳(Unix timestamp)转换工具 - 在线工具

1.1 UTC/GMT

GMT(Greenwich Mean Time格林尼治标准时间是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准

UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒。当原子钟计时一天的时间与地球自转一周的时间相差超过0.9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致

1.2 时间戳转换

C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换

函数

作用

time_t time(time_t*);

获取系统时钟

struct tm* gmtime(const time_t*);

秒计数器转换为日期时间(格林尼治时间

struct tm* localtime(const time_t*);

秒计数器转换为日期时间(当地时间)

time_t mktime(struct tm*);

日期时间转换为秒计数器(当地时间

char* ctime(const time_t*);

秒计数器转换为字符串(默认格式)

char* asctime(const struct tm*);

日期时间转换为字符串(默认格式)

size_t strftime(char*, size_t, const char*, const struct tm*);

日期时间转换为字符串(自定义格式)

2 BKP简介

BKP(Backup Registers)备份寄存器

BKP可用于存储用户应用程序数据。当VDD(2.0~3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位

TAMPER引脚产生的侵入事件将所有备份寄存器内容清除

RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲

存储RTC时钟校准寄存器

用户数据存储容量:20字节(中容量和小容量)/ 84字节(大容量和互联型)

2.1 BKP基本结构

后备区域:主电源断电时,仍然可以由VBAT的备用电池供电。当主电源上电时,后备区域的供电会由VBAT切换到VDD。

BKP主要有数据寄存器、控制寄存器、状态寄存器、RTC时钟校准寄存器。数据寄存器用来存储数据,每个数据寄存器16位;小容量10个寄存器(一个寄存器存两个字节,加起来就是20个字节)。

还有侵入检测、时钟输出等(公用一个引脚)

3 RTC简介

RTC(Real Time Clock)实时时钟

RTC是一个独立的定时器,可为系统提供时钟和日历的功能

RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD2.0~3.6V)断电后可借助VBAT1.8~3.6V)供电继续走时(和BKP一样)

32位的可编程计数器,可对应Unix时间戳的秒计数器

20位的可编程预分频器,可适配不同频率的输入时钟

可选择三种RTC时钟源:

  HSE时钟除以128(通常为8MHz/128

  LSE振荡器时钟(通常为32.768KHz

  LSI振荡器时钟(40KHz

HSE=高速外部时钟信号

HSl =高速内部时钟信号

LSl =低速内部时钟信号

LSE=低速外部时钟信号

高速时钟一般供内部程序运行和主要外设使用;

低速时钟一般供RTC、看门狗使用。

32.768KHz一般是提供给RTC的

只有中间的LSE可以通过备用电池供电。

3.1 RTC框图

左边是核心的、分频和计数计时部分;右边是中断输出使能和NVIC部分;上面是APB1总线读写部分;下面是和PWR相关的部分。图中灰色填充都处于后备区域。

首先看分频和计数计时部分。输入时钟是RTCCLK(可以选择上述三种,主要选择LSE振荡器时钟),进来的频率需要进行RTC预分频器进行分频;上面是重装载寄存器RTC_PRL,下面是余数寄存器RTC_DIV(和计数器那章的计数器CNT,重装值ARR一样的作用),PRL是计数目标(写入6就是7分频),下面的DIV就是每来一个时钟机一个数的作用了,不同的是DIV是自减计数器。

计数计数部分:32位可编程计数器RTC_CNT是核心部分,RTC_ALR闹钟计数器。两者一样时,闹钟响了,产生RTC_Alarm闹钟信号,通往右边的中断系统;闹钟还可以将STM32从待机模式唤醒。闹钟值是定值,只能响一次,下次想使用就得重新设置。

右侧是中断部分,有三个信号可以触发中断:RTC_SEcond秒中断(来源是CNT的输入时钟);RTC_Overflow溢出中断(来源是CNT的右边,CNT计满溢出了会触发一次中断);RTC_Alarm闹钟中断(计数器和闹钟值相等时,触发中断,可以把设备从待机模式唤醒)。F(Flag)结尾的是中断标志位,IE(Interrupt Enable)结尾的是中断使能,三个信号通过或门进入NVIC中断控制器。

最后下面退出待机模式,还有WKUP(Weak Up)引脚,闹钟信号和WKUP信号都可以唤醒设备。

3.2 RTC基本结构

左边是RTCCLK时钟来源,这里需要在RCC里面配置,三选一。之后RTCCLK通过预分频器对时钟进行分频;余数寄存器是一个自减计数器,存储当前的计数值;重装寄存器是计数目标,决定分频值,分频之后得到1Hz的秒计数信号,通向32位计数器CNT,一秒自增一次,下面的32位闹钟值可以设置闹钟;右边有3个信号可以触发中断,分别是秒信号、计数溢出信号、闹钟信号,三个信号通过中断输出控制,进行中断使能,使能的中断才可以通向NVIC,然后向CPU申请中断。

配置数据选择器可以配置时钟来源;配置重装寄存器可以选择分频系数;配置32位计数器可以进行日期时间的读写;需要闹钟的话,配置32位闹钟即可;需要中断先允许中断,再配置NVIC,最后写对应的中断函数即可。

3.3 硬件电路

备用电池供电(推荐连接)、外部低速晶振

3.4 RTC操作注意事项

执行以下操作将使能对BKPRTC的访问:

      设置RCC_APB1ENRPWRENBKPEN,使能PWRBKP时钟

      设置PWR_CRDBP,使能对BKPRTC的访问

若在读取RTC寄存器时,RTCAPB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1

必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRLRTC_CNTRTC_ALR寄存器

对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器

手册

4 读写备份寄存器

4.1 接线图

思路是先初始化,然后写DR,读DR

注意事项

执行以下操作将使能对BKPRTC的访问:

      设置RCC_APB1ENRPWRENBKPEN,使能PWRBKP时钟

      设置PWR_CRDBP,使能对BKPRTC的访问

4.2 模块封装

BKP相关的库函数

// 恢复缺省配置
void BKP_DeInit(void);


void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel);
void BKP_TamperPinCmd(FunctionalState NewState);

// 中断配置
void BKP_ITConfig(FunctionalState NewState);
// 时钟输出功能的配置
void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource);

// 设置RTC校准值
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue);

// 写备份寄存器
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);
// 读备份寄存器
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);

// 获取状态/清空状态
FlagStatus BKP_GetFlagStatus(void);
void BKP_ClearFlag(void);
ITStatus BKP_GetITStatus(void);
void BKP_ClearITPendingBit(void);

PWR库函数

// 备份寄存器访问使能, 设置PWR_CR的DBP,使能对BKP和RTC的访问
void PWR_BackupAccessCmd(FunctionalState NewState);

测试

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

int main()
{
	OLED_Init();								// 初始化OLED
	
	// 1初始化:分两步
	// (1)设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);			// 开启PWR的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);			// 开启BKP的时钟
	// (2)设置PWR_CR的DBP,使能对BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	// 写入,中小容量BKP_DR1范围在1~10
	BKP_WriteBackupRegister(BKP_DR1, 0x1234);
	// 读出
	uint16_t data = BKP_ReadBackupRegister(BKP_DR1);
	OLED_ShowHexNum(1, 1, data, 4);
	
	while (1)
	{
		
	}
}

OLED显示1234

是不是断电不丢失呢,继续测试

注释掉写入的代码/复位/主电源断电,读取都是1234

完整测试

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"

// 写入和读出数组
uint16_t arrayWrite[] = {0x1234, 0x5678};
uint16_t arrayRead[2];

uint8_t keyNum;


int main()
{
	OLED_Init();								// 初始化OLED
	KEY_Init();									// 初始化按键
	OLED_ShowString(1, 1, "W:");
	OLED_ShowString(2, 1, "R:");
	
	// 1初始化:分两步
	// (1)设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);			// 开启PWR的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);			// 开启BKP的时钟
	// (2)设置PWR_CR的DBP,使能对BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	while (1)
	{
		keyNum = KEY_GetNum();
		if (keyNum == 1)
		{
			arrayWrite[0]++;
			arrayWrite[1]++;
			// 写数据
			BKP_WriteBackupRegister(BKP_DR1, arrayWrite[0]);
			BKP_WriteBackupRegister(BKP_DR2, arrayWrite[1]);
			// 显示
			OLED_ShowHexNum(1, 3, arrayWrite[0], 4);
			OLED_ShowHexNum(1, 8, arrayWrite[1], 4);
		}
		// 读数据
		arrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);
		arrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);
		// 显示
		OLED_ShowHexNum(2, 3, arrayRead[0], 4);
		OLED_ShowHexNum(2, 8, arrayRead[1], 4);
		
	}
}

现象:按键按下一次,数据自增一次并显示在OLED上。

5 实时时钟

5.1 接线图

5.2 模块封装

按这个图来配置

左边是RTCCLK时钟来源,这里需要在RCC里面配置,三选一。之后RTCCLK通过预分频器对时钟进行分频;余数寄存器是一个自减计数器,存储当前的计数值;重装寄存器是计数目标,决定分频值,分频之后得到1Hz的秒计数信号,通向32位计数器CNT,一秒自增一次,下面的32位闹钟值可以设置闹钟;右边有3个信号可以触发中断,分别是秒信号、计数溢出信号、闹钟信号,三个信号通过中断输出控制,进行中断使能,使能的中断才可以通向NVIC,然后向CPU申请中断。

配置数据选择器可以配置时钟来源;配置重装寄存器可以选择分频系数;配置32位计数器可以进行日期时间的读写;需要闹钟的话,配置32位闹钟即可;需要中断先允许中断,再配置NVIC,最后写对应的中断函数即可。

RCC时钟部分的库函数

// 配置LSE外部低速时钟
void RCC_LSEConfig(uint8_t RCC_LSE);
// 配置LSI内部低速时钟
void RCC_LSICmd(FunctionalState NewState);
// RTCCLK配置,选择时钟源
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
// RTCCLK使能
void RCC_RTCCLKCmd(FunctionalState NewState);
// 获取标志位
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);

RTC库函数

// 配置中断输出
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);
// 进入配置模式
void RTC_EnterConfigMode(void);
// 退出配置模式
void RTC_ExitConfigMode(void);
// 获取CNT计数器
uint32_t  RTC_GetCounter(void);
// 设置CNT的值
void RTC_SetCounter(uint32_t CounterValue);
// 写入预分频器
void RTC_SetPrescaler(uint32_t PrescalerValue);
// 写入闹钟
void RTC_SetAlarm(uint32_t AlarmValue);
// 获取余数寄存器,自减计数器
uint32_t  RTC_GetDivider(void);
// 等待上次操作完成
void RTC_WaitForLastTask(void);
// 等待同步
void RTC_WaitForSynchro(void);
// 获取/清除标志位
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
void RTC_ClearFlag(uint16_t RTC_FLAG);
ITStatus RTC_GetITStatus(uint16_t RTC_IT);
void RTC_ClearITPendingBit(uint16_t RTC_IT);

MyRTC.h

#include "stm32f10x.h"                  // Device header
#include <time.h>

uint16_t myRTC_Time[] = {2023, 1, 1, 23, 59, 55};

// 初始化
void MyRTC_Init(void)
{
	// 1初始化:分两步
	// (1)设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);			// 开启PWR的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);			// 开启BKP的时钟
	// (2)设置PWR_CR的DBP,使能对BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	// 防止重复初始化和时间重置。在BKP_DR1写入0xA5A5,如果备用电池不断电,则BKP_DR1中还是0xA5A5
	if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
	{
		// 2启动RTC的时钟,使用LSE作为系统时钟,需要开启LSE的时钟(默认是关闭的),等待启动完成
		RCC_LSEConfig(RCC_LSE_ON);
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);
		
		// 3配置RTCCLK数据选择器,指定LSE为RTCCLK
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);			// 32768Hz
		RCC_RTCCLKCmd(ENABLE);
		
		// 4等待函数,等待同步;等待上一次写入操作完成
		RTC_WaitForSynchro();
		RTC_WaitForLastTask();

		// 5配置预分频器,给PRL重装寄存器一个合适的分频值(确保输出是1Hz)
		// 需要进入配置模式,但是不用写代码
		RTC_SetPrescaler(32768 - 1);
		RTC_WaitForLastTask();
		
		// 6配置CNT的值,闹钟/中断
		RTC_SetCounter(1672588795);				// 2023-1-1 23:59:55
	//	MyRTC_SetTime();
		RTC_WaitForLastTask();
		// CNT的值就会以1672588795这个值开始,以1s的频率开始自增,读取CNT的值就能获取时间了
		
		// 在寄存器BKP_DR1写入0xA5A5
		BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
	}
	else
	{
		RTC_WaitForSynchro();
		RTC_WaitForLastTask();
	}
}


// 设置时间,把数组的时间转换为秒数,写到CNT中
void MyRTC_SetTime(void)
{
	time_t time_cnt;
	struct tm time_date;
	
	// 填充时间
	time_date.tm_year = myRTC_Time[0] - 1900;
	time_date.tm_mon = myRTC_Time[1] - 1;
	time_date.tm_mday = myRTC_Time[2];
	time_date.tm_hour = myRTC_Time[3];
	time_date.tm_min = myRTC_Time[4];
	time_date.tm_sec = myRTC_Time[5];
	
	// 日期时间到秒数的转换,北京时间-8
	time_cnt = mktime(&time_date) - 8 * 60 * 60;
	
	// 把指定的秒数写入到CNT中
	RTC_SetCounter(time_cnt);	
	RTC_WaitForLastTask();
}

// 读取时间的函数
void MyRTC_ReadTime(void)
{
	time_t time_cnt;
	struct tm time_date;
	
	// 获取秒数,北京时间+8
	time_cnt = RTC_GetCounter() + 8 * 60 * 60;
	
	// 得到日期
	time_date = *localtime(&time_cnt);
	
	// 日期时间转移到数组里
	myRTC_Time[0] = time_date.tm_year + 1900;
	myRTC_Time[1] = time_date.tm_mon + 1;
	myRTC_Time[2] = time_date.tm_mday;
	myRTC_Time[3] = time_date.tm_hour;
	myRTC_Time[4] = time_date.tm_min;
	myRTC_Time[5] = time_date.tm_sec;
}

5.3 主函数

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"

int main()
{
	OLED_Init();								// 初始化OLED
	MyRTC_Init();
	OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
	OLED_ShowString(2, 1, "Time:XX:XX:XX");
	OLED_ShowString(3, 1, "CNT:");
	OLED_ShowString(4, 1, "DIV:");				// 余数计数器
	
	while (1)
	{
		MyRTC_ReadTime();
		OLED_ShowNum(1, 6, myRTC_Time[0], 4);			// 年
		OLED_ShowNum(1, 11, myRTC_Time[1], 2);			// 月
		OLED_ShowNum(1, 14, myRTC_Time[2], 2);			// 日
		OLED_ShowNum(2, 6, myRTC_Time[3], 2);			// 时
		OLED_ShowNum(2, 9, myRTC_Time[4], 2);			// 分
		OLED_ShowNum(2, 12, myRTC_Time[5], 2);			// 秒
		
		OLED_ShowNum(3, 6, RTC_GetCounter(), 10);		// 显示CNT的值
		OLED_ShowNum(4, 6, RTC_GetDivider(), 10);		// 显示DIV的值 范围32767~0
//		OLED_ShowNum(4, 6, (32767 - RTC_GetDivider()) / 32767.0 * 999, 10);        // 显示DIV的值。显示毫秒0-999
	}
}

现象

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

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

相关文章

虚幻UE 材质-边界混合之PDO像素深度偏移量

2024年的第一天&#xff01;&#xff01;&#xff01;大家新年快乐&#xff01;&#xff01;&#xff01; 可能是长大了才知道 当你过得一般 你的亲朋好友对你真正态度只可能是没有表露出来的冷嘲热讽了 希望大家新的一年平安、幸福、 永远活力满满地追求自己所想做的、爱做的&…

Unix操作系统的前世今生

Unix是一种多用户、多任务操作系统&#xff0c;最初由AT&T贝尔实验室的肯汤普逊&#xff08;Ken Thompson&#xff09;和丹尼斯里奇&#xff08;Dennis Ritchie&#xff09;等人开发于上世纪70年代初。它被设计成一种通用的操作系统&#xff0c;支持跨多种硬件平台&#xf…

开发经验:代码编译、打包正常,运行提示包不存在

天天提交代码&#xff0c;合并代码。经常会发生&#xff0c;代码提交过后&#xff0c;本地的代码跑不起来的情况出现。遇到脾气好点的同事会仔细检查检查下&#xff0c;是否是自己的环境出现的问题&#xff0c;遇到脾气不好的同事&#xff0c;直接就开喷了。怎么每次你一提交代…

C++: 求1+2+3+...+n

int i 1; int sum 0; class Sum { public:Sum(){sum i;i;} };class Solution { public:int Sum_Solution(int n) {Sum a[n]; //调用n次sum的构造函数return sum;} };

Docker 镜像以及镜像分层

Docker 镜像以及镜像分层 1 什么是镜像2 Docker镜像加载原理2.1 UnionFs&#xff1a;联合文件系统2.2 Docker镜像加载原理2.3 Docker镜像的特点 3 镜像的分层结构4 可写的容器层 1 什么是镜像 镜像是一种轻量级、可执行的独立软件包&#xff0c;用来打包软件运行环境和基于运行…

1_开闭原则(Open Closed Principle)

开闭原则(Open Closed Principle) 1.概念 开闭原则&#xff08;Open-Closed Principle&#xff09;是指一个软件实体如类、模块和函数应该对扩展开放&#xff0c; 对修改关闭。所谓的开闭&#xff0c;也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架&#xff…

python总结高阶-异常处理机制

文章目录 异常是什么&#xff1f;try和except结构try...一个except结构try...多个except结构try...except...else结构try...except...finally结构return语句和异常处理问题 常见异常常见异常的解决SyntaxError &#xff1a;语法错误NameError &#xff1a;尝试访问一个没有申明…

算法第十二天-矩形区域不超过K的最大数值和

矩形区域不超过K的最大数值和 题目要求 解题思路 来自[宫水三叶] 从题面来看显然是一道[二维前缀和]的题目。本题预处理前缀和的复杂度为O(m* n) 搜索所有子矩阵需要枚举[矩形左上角]和[矩形右下角]&#xff0c;复杂度是 O ( m 2 ∗ n 2 ) O(m^2 * n^2) O(m2∗n2)&#xff0c…

如何安装 Python

1.打开浏览器 输入网址 :www.python.org ​ 2.根据电脑系统配置进行下载 ​ 3.确定电脑系统属性&#xff0c;此处我们以win10的64位操作系统为例 ​ 4.安装python 3.6.3 双击下载的安装包 python-3.6.3.exe 注意要勾选&#xff1a;Add Python 3.6 to PATH 点击 Customize…

听GPT 讲Rust源代码--compiler(27)

File: rust/compiler/rustc_mir_build/src/build/expr/as_place.rs 在Rust编译器的源代码中&#xff0c;文件rust/compiler/rustc_mir_build/src/build/expr/as_place.rs的作用是用于处理表达式的转换为L-value的过程。L-value是指那些可接受赋值操作的表达式&#xff0c;如变量…

企业Aspera替代方案有哪些推荐

随着企业数据量的不断增加&#xff0c;数据传输和共享成为了一个重要的问题。Aspera是一款高性能、低延迟的数据传输工具&#xff0c;但是它并不是万能的&#xff0c;随着数据量的不断增大&#xff0c;也有一些企业需要寻找Aspera的替代方案。本文将介绍三种常用的企业Aspera替…

复旦MBA科创青干营(二期):探索合肥科创企业的创新之路

11月18日-19日&#xff0c;复旦MBA科创青干营二期学生开启了整合实践活动的第三次企业参访&#xff0c;前往位于合肥的蔚来第二先进制造基地、安徽万邦医药科技股份有限公司和合肥国轩高科动力能源有限公司&#xff0c;在学术导师和科创企业家“双导师”的指导下&#xff0c;深…

近屿智能OJAC带您从0到1全方位深度学习AI大模型,星辰大海和你开创!

Look&#xff01;&#x1f440;我们的大模型商业化落地产品&#x1f4d6;更多AI资讯请&#x1f449;&#x1f3fe;关注Free三天集训营助教在线为您火热答疑&#x1f469;&#x1f3fc;‍&#x1f3eb; 在这个信息爆炸的数字时代&#xff0c;你是否也想掌握那种像魔法一样的AI技…

Git - 强制替换覆盖 master 分支解决方案

问题描述 在版本迭代中&#xff0c;通常会保持一个主分支 master&#xff0c;及多个 dev 分支&#xff0c;但是因为 dev 分支的开发周期过长&#xff0c;迭代太多而没有及时维护 master &#xff0c;导致后来发版上线的大部分代码都在 dev 分支上&#xff0c;如果将代码在 mas…

【Python学习】Python学习4-运算符

目录 【Python学习】Python学习4-运算符 前言算术运算符比较&#xff08;关系&#xff09;运算符赋值运算符逻辑运算符位运算符成员运算符身份运算符运算符优先级参考 文章所属专区 Python学习 前言 本章节主要说明Python的运算符。主要有 算术运算符 比较&#xff08;关系&…

MYSQL - SQL优化

插入数据优化 小批量数据 批量插入 最好插入500-1000条比较好 手动提交事务 主键顺序插入 大批量插入数据 主键优化 页分裂 页合并 主键优化设计原则 order by优化 group by优化 limit优化 count优化 count(1)里面不一定必须1&#xff0c;数字都可以 update优化 更新字…

Ubuntu同步两个剪切板

众所周知&#xff0c;ubuntu系统中有两套剪切板。第一个剪切板是用鼠标操作&#xff0c;鼠标选中则复制&#xff0c;点击鼠标中键则粘贴&#xff08;这个剪切板通常叫做——选择缓冲区&#xff09;。第二个剪切板则是真正的剪切板&#xff0c;使用ctrlc&#xff08;在终端中默认…

响应式开发

响应式开发的原理Bootstrap前端开发框架Bootstrap栅格系统阿里百秀首页案例 响应式开发原理 1 响应式需要一个父级做为布局容器&#xff0c;来配合子级元素来实现变化效果。 2 在不同屏幕下&#xff0c;通过媒体查询来改变这个布局容器的大小&#xff0c;再改变里面子元素的排…

JDK 11:崭新特性解析

JDK 11&#xff1a;崭新特性解析 JDK 11&#xff1a;崭新特性解析1. HTTP Client&#xff08;标准化&#xff09;示例代码 2. 局部变量类型推断的扩展示例代码 3. 新的字符串方法示例代码 4. 动态类文件常量示例代码 5. Epsilon 垃圾收集器使用方式 结语 JDK 11&#xff1a;崭新…

LeetCode-有效的字母异位词(242)

题目描述&#xff1a; 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 思路&#xff1a; 这题还是比较简单的&#xff0c;首先将两个字符…