这一节我们要讲的主要内容是RTC实时时钟,实时时钟本质上是一个定时器,但是这个定时器是专门用来产生年月日时分秒,这种日期和时间信息的。所以学会了STM32的RTC就可以在STM32内部拥有一个独立运行的钟表。想要记录或读取日期和时间,就可以通过操作RTC来实现。

RTC这个外设比较特殊,它和备份寄存器(BKP)、电源控制(PWR)这两章关联性比较强,因此在RTC这一章中,就把BKP和RTC放在一起讲。

我们首先就先介绍备份寄存器(BKP),其实备份寄存器(BKP)和SPI章节中学过的Flash存储器类似,都是用来存储数据的,只是Flash的数据是真正的掉电不丢失;而BKP的数据是需要VBAT引脚接上备用电池来维持的,只要VBAT有电池供电,即使STM32主电源断电,BKP的值也可以维持原状。

首先我们来看一下时间戳的知识点。Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始到现在所经过的秒数,不考虑闰秒。在计算机的底层我们使用秒计数器来计时,需要给人类观看时,就转换为年月日时分秒这样的格式。时间戳存储在一个秒计数器中,秒计数器为32/64位的整型变量,计算机为了存储这样一个永不进位的秒数,这个数据变量类型还是要定义大一些,这个变量类型在不同系统中定义是不一样的。我们本节STM32中的RTC,其核心的计时部分是一个32位的可编程计数器,说明我们这款STM32,它的时间戳是32位的数据类型。世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间。

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

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

接下来我们学习时间戳中秒计数器和日期时间如何进行相互转换,这时候我们需要用到time.h模块,C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换,在time.h里主要有表格内的这些主要函数

时间戳转换关系如下图所示

接下来我们学习BKP和RTC的外设部分,我们首先学习BKP的相关知识点。BKP全称Backup Registers,翻译过来就是备份寄存器,BKP的用途就是可用于存储用户应用程序数据。其特性就是当VDD2.0~3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。如果VDD断电,VBAT也没电,那BKP里的数据就会清零,因为BKP本质上是RAM存储器,没有掉电不丢失的能力。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位;TAMPER引脚产生的侵入事件将所有备份寄存器内容清除,TEMPER是一个接到STM32外部的引脚,其位置就是VBAT旁边的2号引脚,其与PC13、RTC共用,这个TAMPER引脚是一个安全保障设计,比如如果做一个安全系数非常高的设备,设备需要有防拆功能,BKP里也存储了一些敏感数据,那就可以使能这个TEMPER引脚的侵入检测功能;设计者把下面两个RTC功能也放在了BKP中:  1.引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲,RTC的引脚也是在PC13这个位置     2.存储RTC时钟校准寄存器。最后看一下BKP中,用户数据的存储容量,在中容量和小容量设备里,BKP是20个字节,在大容量和互联型设备里,BKP是84个字节。可以看出来BKP的容量其实非常小,一般只能用来存储少量的参数。BKP的简介我们就介绍到这里。

下面看一下BKP的基本结构,图中橙色部分我们可以叫做后备区域,BKP处于后备区域,但后备区域不只有BKP,还有RTC的相关电路。STM32后备区域的特性就是当VDD主电源掉电时,后备区域仍然可以由VBAT的备用电池供电,当VDD主电源上电时,后备区域供电会由VBAT切换到VDD,也就是主电源有电时,VBAT不会用到,这样可以节省电池电量。BKP是位于后备区域的,BKP里主要有数据寄存器、控制寄存器、状态寄存器和RTC时钟校准寄存器。其中数据寄存器是主要部分,用来存储数据,每个数据寄存器都是16位的,也就是一个数据寄存器可以存2个字节,对于中容量和小容量的设备,里面有DR1、DR2一直到DR10,总共10个数据寄存器,那一个寄存器两个字节,所以容量是20个字节。对于大容量和互联型设备,里面除了DR1到DR10还有DR11、DR12一直到DR42,总共42个数据寄存器,容量是84个字节。侵入检测可以从PC13位置的TAMPER引脚引入一个检测信号,当TAMPER产生上升沿或者下降沿时,清除BKP所有的内容,以保证安全,时钟输出可以把RTC的相关时钟从PC13位置的RTC引脚输出出去,供外部使用。其中,输出校准时钟时,再配合校准寄存器,可以对RTC的误差进行校准。以上就是BKP外设的结构和功能。

接下来我们就继续学习以下RTC外设,RTC英文全称  Real Time Clock  中文翻译为实时时钟,在STM32中,RTC是一个独立的定时器,可为系统提供时钟和日历的功能,RTC实时时钟,一般就指提供年月日时分秒这种日期时间信息的计时装置;RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD2.0~3.6V)断电后可借助VBAT1.8~3.6V)供电继续走时;其内部设有32位的可编程计数器,可对应Unix时间戳的秒计数器。在读取时间时,我们先得到这个计数器中的秒数,然后使用time.h模块里的localtime函数就能立刻知道年月日时分秒的信息了,在写入时间时,我们先填充年月日时分秒信息到struct tm结构体,然后用mktime函数得到秒数,再写入到这个32位计数器即可。RTC外设中配有20位的可编程预分频器,可适配不同频率的输入时钟,由于32位的秒计数器显然1秒要自增一次,所以驱动计数器的时钟,需要是一个1Hz的信号,但是实际提供给RTC模块的时钟,也就是RTCCLK一般频率都比较高。所以显然我们需要在RTCCLK和计数器时钟输入之间加入一个分频器,给RTCCLK降一降频率,保证分频器输出给计数器的频率为1Hz。那为了适配各种频率的RTCCLK,就在其中间加入了一个20位的分频器,可以选择对输入时钟进行1-2^20这么大范围的分频,这样就可以适配不同频率的输入时钟,这就是这个可编程分频器的作用;可选择三种RTC时钟源:1.  HSE时钟除以128(通常为8MHz/128) 2.   LSE振荡器时钟(通常为32.768KHz) 3.  LSI振荡器时钟(40KHz) 这三个时钟可以选择其中一个介入到RTCCLK。

在时钟树中,高速时钟一般供内部程序运行和主要外设使用;低速时钟一般供RTC、看门狗这些东西使用,红色所圈出来的地方最右侧箭头通往RTC,就是RTCCLK,RTCCLK有三个来源,第一个是OSC引脚接的HSE,外部高速晶振,这个晶振是主晶振,一般用的8MHz,8MHz进来,通过128分频,可以产生RTCCLK信号,128分频的原因是8MHz的主晶振太快了,如果不提前分频,直接给RTCCLK,后续即使再通过RTC的20位分频器也分不到1Hz这么低的频率。中间这一路的时钟来源是LSE,外部低速晶振,我们在OSC32这两个引脚接上外部低速晶振,这个晶振产生的时钟可以直接提供给RTCCLK,这个OSC32的晶振是内部RTC的专用时钟,这个晶振的值也不是随便选的,通常跟RTC有关的晶振,都是统一的数值,就是32.768KHz,选择这个数值的原因是32KHz这个值附近的频率是这个晶振工艺比较合适的频率,另一方面是32768是一个2的次方数,2^15 = 32768 ,所以32.768KHz即32768Hz,经过一个15位分频器的自然溢出,就能很方便地得到1Hz的频率。自然溢出的意思就是设计一个15位的计数器,这个计数器不用设置计数目标,直接从0计到最大值,就是计到32767,计满后自然溢出,这个溢出信号就是1Hz。所以,目前在RTC电路中,基本都是清一色的32.768KHz的晶振。最后第三路时钟源来自LSI,内部低速RC振荡器,LSI固定是40kHz,如果选择LSI当作RTCCLK,后续再经过40K的分频,就能得到1Hz的计数时钟了。当然内部的RC振荡器一般精准度没有外部晶振高,所以LSI给RTCCLK可以当作一个备选方案。另外LSI还可以提供给看门狗,这个之后我们讲看门狗的时候再说。

这三路时钟中我们最常用的就是中间这一路外部32.768KHz的晶振,提供RTCCLK的时钟。不仅因为中间这一路32.768KHz的晶振本身就是专供RTC使用的,其余的时钟其实各自都有各自的主要任务,另外一个更重要的原因就是只有中间这一路的时钟可以通过VBAT备用电池供电,上下两路时钟,在主电源断电后,是停止运行的。所以要想实现RTC主电源掉电继续走时的功能,必须选择中间这一路的RTC专用时钟。

接下来我们看一下RTC的框图,看一下RTC外设具体是怎么设计的。先整体上划分一下,左边的一块是核心的分频和计数计时部分,右边这一块是中断输出使能和NVIC部分,最上面一块是APB1总线读写部分,最下面一块是和PWR关联的部分,意思就是RTC的闹钟可以唤醒设备,推出待机模式。在图中,有灰色填充的部分都处于后备区域,这些电路在主电源掉电后,可以使用备用电池维持工作,其他未被填充的部分就是待机时不供电,有关睡眠、停机、待机这些低功耗相关的内容,我们下节学PWR的时候再细讲。

我们依次详细看一下。首先看分频和计数计时部分,这一块的输入时钟是RTCCLK,RTCCLK的来源需要在RCC里进行配置。因为可选的三路时钟频率各不相同,而且都远大于我们所需要的1Hz的秒计数频率,所以RTCCLK进来,需要首先经过RTC预分频器进行分频,这个分频器由两个寄存器组成,上面这个是重装载寄存器RTC_PRL,下面这个RTC_DIV,手册里叫做余数寄存器,但实际上这一块跟我们之前定时器时基单元里的计数器CNT和重装值ARR是一样的作用。分频器其实就是一个计数器,计几个数溢出一次,那就是几分频,所以对于可编程的分频器来说,需要有两个计数器,RTC_DIV寄存器用来不断地计数,另一个RTC_PRL寄存器,我们写入一个计数目标值,用来配置是几分频。那么PRL中就是计数目标,我们写入6,那就是7分频,写入9,那就是10分频;下面这个DIV,就是每来一个时钟计一个数的用途了,当然这个DIV计数器是一个自减计数器,每来一个输入时钟,DIV的值自减一次,自减到0时,再来一个输入时钟,DIV输出一个脉冲,产生溢出信号,同时DIV从PRL获取重装值,回到重装值继续自减。分频输出后的时钟频率是1Hz,提供给后续的秒计数器。然后看一下计数计时部分,32位可编程计数器RTC_CNT就是计时最核心的部分,我们可以把这个计数器看作是Unix时间戳的秒计数器,这样借助time.h的函数就可以很方便地得到年月日时分秒了,在其下面还设计有一个闹钟寄存器RTC_ALR,这个ALR也是一个32位的寄存器,和上面这个CNT是等宽的,它的作用顾名思义就是设置闹钟,我们可以在ALR写一个秒数,设定闹钟,当CNT的值跟ALR设定的闹钟值一样时,这时就会产生RTC_Alarm闹钟信号,通往右边的中断系统,在中断函数里,你可以执行相应的操作,同时这个闹钟还兼具一个功能,就是下面这里的闹钟信号可以让STM32退出待机模式。这个功能就可以对应一些用途,比如你设计一个数据采集设备,需要在环节非常恶劣的地方工作,比如海底、高原、深井这些地方,然后要求是每天中午12点采集一次环节数据,其他时间为了节省电量,避免频繁换电池,芯片都必须处于待机模式,这样的话我们就可以用这个RTC自带的闹钟功能。另外这个闹钟值是一个定值,只能响一次,所以你想实现周期性的闹钟,那在每次闹钟响之后,都需要再重新设置一下下一个闹钟时间。继续往右看就是中断部分了,在左边这里有三个信号可以触发中断,第一个是RTC_Second,秒中断,它的来源就是CNT的输入时钟,如果开启这个中断,那么程序就会每秒进一次RTC中断;第二个是RTC_Overflow,溢出中断,它的来源是CNT的右边,意思就是CNT的32位计数器计满溢出了会触发一次中断,所以这个中断一般不会触发;第三个RTC_Alarm,闹钟中断,刚才说过,当计数器和闹钟值相等时,触发中断,同时,闹钟信号可以把设备从待机模式唤醒。中断信号到右边这里就是中断标志位和中断输出控制,F结尾的是对应的中断标志位,IE结尾的是中断使能,最后三个信号通过一个或门汇聚到NVIC中断控制器。最上面这部分APB1总线和APB1接口就是我们程序读写寄存器的地方了,读写寄存器可以通过APB1总线来完成,另外也可以看出RTC是APB1总线上的设备。最后,最下面这一块,推出待机模式还有一个WKUP引脚,闹钟信号和WKUP引脚都可以唤醒设备。到这里这个RTC外设框图就已经全部了解清楚了。

接下来看一下下面的基本结构图,再总结一下以上内容,最左边是RTCCLK时钟来源,这一块需要在RCC里配置,3个时钟,选择一个,当作RTCCLK,之后RTCCLK先通过预分频器,对时钟进行分频,余数寄存器是一个自减寄存器,存储当前的计数值,重装寄存器是计数目标,决定分频值。分频之后得到1Hz的秒计数信号,通向32位计数器,1s自增一次,下面还有一个32位的闹钟值可以设定闹钟,右边有三个信号可以触发中断,分别是秒信号、计数器溢出信号和闹钟信号,三个信号先通过中断输出控制进行中断使能,使能的中断才能通向NVIC,然后向CPU申请中断。在程序中,我们配置这个数据选择器,可以选择时钟来源;配置重装寄存器,可以选择分频系数;配置32位计数器,可以进行日期时间的读写,需要闹钟的话,配置32位闹钟值即可;需要中断的话,先允许中断,再配置NVIC,最后写对应的中断函数即可,这就是RTC外设的主要内容。

最后,我们再看一些这个RTC的一些操作注意事项

1.执行以下操作将使能对BKPRTC的访问:设置RCC_APB1ENRPWRENBKPEN,使能PWRBKP时钟;设置PWR_CRDBP,使能对BKP和RTC的访问。正常的外设开启了时钟就能使用了,但是BKP和RTC这两个外设开启稍微复杂些,首先要设置RCC_APB1ENR,这个实际上就是开启APB1外设的时钟,要同时开启PWR和BKP的时钟,对于RTC来说,并没有单独开启时钟的选项。然后我们还要设置PWR_CR的DBP位,来使能对BKP和RTC的访问

2. 若在读取RTC寄存器时,RTCAPB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1。这一步对应代码里的一个库函数,就是RTC等待同步,一般在刚上电的时候调用一下这个函数就行了。

3. 必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRLRTC_CNTRTC_ALR寄存器。就是RTC会有一个进入配置模式的标志位,把这一位置1,才能设置时间,其实这个操作在库函数中,每个写寄存器的函数都会自动加上这个操作,所以就不用再单独调用代码进入配置模式了。

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

2和3的注意事项都是因为读写数据时使用的APB1总线是在PCLK1的时钟频率下运行的,但是RTC外设内部的工作时钟是RTCCLK,PCLK1的频率远大于RTCCLK,因此任何读写操作都需要等待一会。

下面我们进入到代码编写的部分。

首先介绍一下备份寄存器BKP的库函数,其中,BKP_DeInit函数用于恢复缺省配置在BKP的外设中是有一个用途的,就是手动清空BKP所有的数据寄存器,因为如果有备用电池的话,BKP的数据主电源掉电不清零、上电复位也不清零,它就没清零的时候,如果我们确实想要清零,就可以使用这个函数,这样所有BKP的数据都会变0;BKP_TamperPinLevelConfig和BKP_TamperPinCmd用于配置TAMPER侵入检测功能,前者可以配置TAMPER引脚的有效电平,就是高电平触发还是低电平触发,后者就是配置是否开启侵入检测功能,如果需要侵入检测的话,那就先配置TAMPER有效电平,再使能侵入检测功能就行了;BKP_ITConfig,中断配置,就是配置是否开启中断;BKP_RTCOutputConfig这是配置时钟输出功能,可以选择在RTC引脚上输出时钟信号,输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲,该配置需要通过 BKP 模块的寄存器来实现,因此函数被归在了BKP的库文件之中;BKP_SetRTCCalibrationValue,用于设置RTC校准值,其实就是写入RTC校准寄存器,校准值的设置也需要写入 BKP 模块的相关寄存器,因此也被归在了BKP的库文件之中。以上这些函数就是我们在上面说的BKP附加的小功能。之后的这几个函数才是经常使用的:BKP_WriteBackupRegister,写备份寄存器,其第一个参数指定要写在哪个DR里,第二个参数填你要写入的数据;BKP_ReadBackupRegister,读备份寄存器。参数指定要读哪个DR,返回值就是DR里存的值。 此外,我们还需要特别关注PWR库函数中的PWR_BackupAccessCmd函数,即备份寄存器访问使能,该函数中的内容就是设置PWR_CR寄存器里的DBP位,我们来调用这个函数满足使用RTC和BKP外设时的注意事项1。

下面对于RTC实时时钟编程,我们总结其初始化步骤如下:

1.开启PWR时钟和BKP时钟,使能BKP和RTC的访问

2.启动RTC的时钟,我们计划使用LES作为系统时钟,所以使用RCC模块里的函数,开启LSE的时钟

3.配置RTCCLK这个数据选择器,指定LSE为RTCCLK,这一步的函数也是在RCC模块里的

4.调用注意事项中提到的等待函数,分别为等待同步和等待上一次操作完成

5.配置预分频器,给PRL重装寄存器一个合适的分频值,以确保输出给计数器的频率是1Hz

6.配置CNT的值,给这个RTC一个初始时间

如果需要闹钟的话,可以配置闹钟值;需要中断的话可以配置中断部分

因为RTC比较简单,所以库函数并没有使用结构体来配置,RTC也没有RTC_Cmd这样的函数,开启时钟就能自动运行了,不需要最后再启动一下的。

在RCC库函数中,存在着一些和RTC时钟相关的函数。其中RCC_LSEConfig用于配置LSE外部低速时钟,启动LSE时钟就调用这个函数;RCC_LSICmd函数用于配置LSI内部低速时钟,如果出现了外部时钟不起振的情况,也可以使用这个内部时钟来进行实验;RCC_RTCCLKConfig,RTCCLK配置,这个函数用来选择RTCCLK的时钟源,实际上就是配置简化结构图中的数据选择器;RCC_RTCCLKCmd,启动RTCCLK,在调用上一个函数选择时钟之后,还需要调用一下这个Cmd函数,使能一下;另外还需要用到RCC_GetFlagStatus函数获取标志位,因为LSE时钟不是你让它启动它就能立刻启动的,调用启动时钟的函数之后,我们还需要等待一下标志位,等RCC的标志位LSERDY置1之后,这个时钟才算启动完成,工作稳定。有关RCC时钟部分的函数就这么多。

接下来我们继续看RTC库函数中的函数:RTC_ITConfig用于配置中断输出;RTC_EnterConfigMode,进入配置模式,就是置CRL的CNF为1,进入配置模式,其对应注意事项中的第三条;RTC_ExitConfigMode,退出配置模式,就是把CNF位清零;RTC_GetCounter,获取CNT计数器的值,显然,读取时钟就靠这个函数;RTC_SetCounter,写入CNT计数器的值,显然,设置时间,就靠这个函数;RTC_SetPrescaler,写入预分频器,这个值会写入到预分频器的PRL重装寄存器中,用来配置预分频器的分频系数;RTC_SetAlarm,写入闹钟值;RTC_GetDivider,读取预分频器中的DIV余数寄存器,余数寄存器是一个自减寄存器,获取余数寄存器的值,一般是为了得到更细致的时间,因为CNT计数间隔最短就是1s,如果需要更细致的时间,比如分秒、厘秒、毫秒,那就得靠这个DIV余数寄存器来实现;RTC_WaitForLastTask,等待上次操作完成,对应注意事项中的第四条,等待前一次写操作结束;RTC_WaitForSynchro,等待同步,对应注意事项中的第二条。

在RTC显示实时时钟代码中,我如何保证在系统复位后,保证时间信息仍然不被重置呢?我可以借助BKP中存储内容在单片机供电断开时仍然能靠电池保存的特性,在初始化代码中加入判断:如果BKP中任一一个数据寄存器中内容不等于约定好的数字,说明现在是单片机电源掉电、电池电源掉电之后重新启动,因此需要进行初始化,并且在BKP对应寄存器中写入该数据;如果其中的内容等于数字了,说明电池并未掉电,则跳过初始化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917223.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917223.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917223.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【10】大恒相机SDK C++开发 ——对相机采集的原图像数据IFrameData裁剪ROI 实时显示在pictureBox中,3种方法实现(效率不同)

文章目录1 在回调函数中实现2 独立封装调用2.1 获取图像宽、高、pBuffer、channel2.2 内存图像数据截取ROI并显示2.3 回调函数调用3 for循环嵌套 方法24 for循环嵌套 方法35 按行复制数据提高效率,但很耗内存6 unsafe代码 解释及注意事项 看我另一篇文章7 ConvertTo…

ubuntu22.04系统入门 linux入门(二) 简单命令 多实践以及相关文件管理命令

以下有免费的4090云主机提供ubuntu22.04系统的其他入门实践操作 地址:星宇科技 | GPU服务器 高性能云主机 云服务器-登录 相关兑换码星宇社区---4090算力卡免费体验、共享开发社区-CSDN博客 之所以推荐给大家使用,是因为上面的云主机目前是免费使用的…

分布式ID方案(标记)

一、参考文章-标记 分布式ID方案有哪些?雪花算法如何搞定时钟回拨和动态机器ID? 二、应用 1.百度 uid-generator github项目地址 原理参考 2.百度 uid-generator 扩展应用 灯官网 灯 项目代码 lamp-util 单元模块 lamp-util 单元模块子模块 lamp-…

std::map 加锁

在并发环境下使用std::map,必须采取同步措施。 在并发环境下对 std::map 进行不加锁的读写操作会导致严重的线程安全问题,主要会产生以下几种问题: ⚠️ 主要风险与后果数据竞争(Data Race) 当多个线程同时修改同一个键…

学习笔记090——Ubuntu 中 UFW 防火墙的使用

文章目录1、允许特定的端口访问2、允许特定 IP 访问某个端口3、允许某个范围的端口4、查看 UFW 状态5、重新加载 UFW6、启用 UFW7、关闭 UFW1、允许特定的端口访问 # 允许 TCP 端口(例如 80): sudo ufw allow 80/tcp# 允许 UDP 端口&#xf…

移动端 WebView 内存泄漏与性能退化问题如何排查 实战调试方法汇总

在混合 App 应用中,WebView 页面常承载复杂业务逻辑与交互。随着用户使用时间增长,特别在切换多个页面或反复打开界面后,常常会出现性能下降、页面卡顿、甚至白屏崩溃等现象。这通常是因为页面存在内存泄漏、事件监听未解绑或垃圾回收阻塞导致…

JSON 对象在浏览器中顺序与后端接口返回不一致的问题

一、问题描述 后端接口返回一个字典表的JSON对象,页面展示排序与预期排序不一致。 在浏览器调试面板Response中看到接口原始响应字符串,是期望顺序:在Preview中看到, key “22” 被提到最前,顺序发生变化:页…

Spring MVC数据传递全攻略

Spring MVC数据传递一、前端到后端的数据传递1. 使用 RequestParam 传递简单参数2. 使用 PathVariable传递路径参数3. 使用RequestBody传递 JSON 数据二、后端到前端的数据传递1. 使用Model或 ModelAndView传递数据到前端2. 使用HttpServletResponse直接写回数据3.使用Response…

仓库管理系统-12-前端之头部区域Header基于嵌套路由访问个人中心

文章目录 1 个人中心 1.1 DateUtils.vue(子组件) 1.2 Home.vue(父组件) 1.3 router/index.js(嵌套路由) 1.4 index.vue(路由占位符) 2 Header.vue 2.1 页面布局 2.2 toUser方法 2.3 初始加载 2.4 Header.vue 头部区域Header中有一个个人中心下拉菜单,点击个人中心选项,通过嵌…

【智能协同云图库】第七期:基于AI调用阿里云百炼大模型,实现AI图片编辑功能

摘要:AI 高速发展赋能传统业务,图库网站亦有诸多 AI 应用空间。以 AI 扩图功؜能为例,让我们来学习如何在项目⁠中快速接入 AI 绘图大模型。‏用户可以选择一张已上传的图片,‌通过 AI 扩图得到新的图片,希望可以帮到大…

Notepad++插件安装

方式一:自动安装(有些notepad并不好用,推荐方式二)工具栏-》插件-》插件管理如下点击安装后会提示,后端安装,安装成功后自动启动,本人使用的v8.6.4的版本,插件基本都无法自动安装&am…

git pull和git fetch的区别

git pull和git fetch是git版本控制系统中的两个基本命令,它们都用于从远程仓库更新本地仓库的信息,但执行的具体操作不同。git fetch:git fetch下载远程仓库最新的内容到你的本地仓库,但它并不自动合并或修改你当前的工作。它取回了远程仓库的…

Item35:考虑virtual函数以外的其他选择

在C++中,虚函数是实现多态的传统方式,但并非唯一选择。过度依赖虚函数可能导致派生类与基类的强耦合,或难以在运行时灵活切换行为。《Effective C++》Item35指出:应根据场景选择更合适的替代方案,包括NVI模式、函数指针、策略模式等。本文解析这些方案的原理、适用场景及实…

Vue3 状态管理新选择:Pinia 从入门到实战

一、什么是pinia? 在 Vue3 生态中,状态管理一直是开发者关注的核心话题。随着 Vuex 的逐步淡出,Pinia 作为官方推荐的状态管理库,凭借其简洁的 API、强大的功能和对 Vue3 特性的完美适配,成为了新时代的不二之选。今天我们就来深…

Unity相机控制

相机的控制无非移动和旋转,每种操作各3个轴6个方向,一共12种方式。在某些需要快速验证的项目或Demo里常常需要丝滑的控制相机调试效果。相机控制虽然不是什么高深的技术,但是要写的好用还是很磨人的。 锁定Z轴的旋转 一个自由的相机可以绕 …

vue2 使用liveplayer加载视频

vue2 使用liveplayer加载视频 官网: https://www.liveqing.com/docs/manuals/LivePlayer.html支持WebRTC/MP4播放;支持m3u8/HLS播放;支持HTTP-FLV/WS-FLV/RTMP播放;支持直播和点播播放;支持播放器快照截图;支持点播多清晰度播放;支持全屏或比例显示;自动检测IE浏览器兼容播放;支…

JavaScript语法树简介:AST/CST/词法/语法分析/ESTree/生成工具

AST简介 在平时的开发中,经常会遇到对JavaScript代码进行检查或改动的工具,例如ESLint会检查代码中的语法错误;Prettier会修改代码的格式;打包工具会将不同文件中的代码打包在一起等等。这些工具都对JavaScript代码本身进行了解析…

Java函数式编程之【基本数据类型流】

一、基本数据类型与基本数据的包装类 在Java编程语言中,int、long和double等基本数据类型都各有它们的包装类型Integer、Long和Double。 基本数据类型是Java程序语言内置的数据类型,可直接使用。 而包装类型则归属于普通的Java类,是对基本数据…

.NET Core部署服务器

1、以.NET Core5.0为例,在官网下载 下载 .NET 5.0 (Linux、macOS 和 Windows) | .NET 根据自己需求选择x64还是x86,记住关键下载完成还需要下载 Hosting Bundel ,否则不成功 2、部署https将ssl证书放在服务器上,双击导入&#…

YOLO---04YOLOv3

YOLOV3 论文地址::【https://arxiv.org/pdf/1804.02767】 YOLOV3 论文中文翻译地址::【YOLO3论文中文版_yolo v3论文 中文版-CSDN博客】 YOLOv3 在实时性和精确性在当时都是做的比较好的,并在工业界得到了广泛应用 …