FreeRTOS 低功耗 Tickless 模式

news2024/11/22 20:08:05

文章目录

  • 一、低功耗模式
    • 1. 睡眠(Sleep)模式
    • 2. 停止(Stop)模式
    • 3. 待机(Standby)模式
  • 二、Tickless 模式详解
    • 1. 如何降低功耗?
    • 2. Tickless 具体实现


一、低功耗模式

STM32 本身就支持低功耗模式,有三种低功耗模式:
● 睡眠(Sleep)模式。
● 停止(Stop)模式。
● 待机(Standby)模式。

这三种模式对比如下表所示:
在这里插入图片描述
这三种低功耗模式对应三种不同的功耗水平,根据实际的应用环境选择相对应的低功耗模式。接下来我们就详细的看一下这三者有何区别。

1. 睡眠(Sleep)模式

● 进入睡眠模式
进入睡眠模式有两种指令:WFI(等待中断)和WFE(等待事件)。根据Cortex-M 内核的SCR(系统控制)寄存器可以选择使用立即休眠还是退出时休眠,当 SCR 寄存器的 SLEEPONEXIT(bit1)位为 0 的时候使用立即休眠,当为 1 的时候使用退出时休眠。

CMSIS(Cortex 微控制器软件接口标准)提供了两个函数来操作指令 WFI 和 WFE,我们可以直接使用这两个函数:__WFI 和__WFE。FreeRTOS 系统会使用 WFI 指令进入休眠模式。

● 退出休眠模式
如果使用 WFI 指令进入休眠模式的话那么任意一个中断都会将 MCU 从休眠模式中唤醒,如果使用 WFE 指令进入休眠模式的话那么当有事件发生的话就会退出休眠模式,比如配置一个 EXIT 线作为事件。

当 STM32F103 处于休眠模式的时候 Cortex-M3 内核停止运行,但是其他外设运行正常,比如 NVIC、SRAM 等。休眠模式的功耗比其他两个高,但是休眠模式没有唤醒延时,应用程序可以立即运行。

2. 停止(Stop)模式

停止模式基于 Cortex-M3 的深度休眠模式与外设时钟门控,在此模式下 1.2V 域的所有时钟都会停止,PLL、HSI 和 HSE RC 振荡器会被禁止,但是内部 SRAM 的数据会被保留。调压器可以工作在正常模式,也可配置为低功耗模式。如果有必要的话可以通过将 PWR_CR 寄存器的FPDS 位置 1 来使 Flash 在停止模式的时候进入掉电状态,当 Flash 处于掉电状态的时候 MCU从停止模式唤醒以后需要更多的启动延时。停止模式的进入和退出如下表所示:
在这里插入图片描述

3. 待机(Standby)模式

相比于前面两种低功耗模式,待机模式的功耗最低。待机模式是基于 Cortex-M3 的深度睡眠模式的,其中调压器被禁止。1.2V 域断电,PLL、HSI 振荡器和 HSE 振荡器也被关闭。除了备份区域和待机电路相关的寄存器外,SRAM 和其他寄存器的内容都将丢失。待机模式的进入和退出如下表所示:
在这里插入图片描述
退出待机模式的话会导致 STM32F1 重启,所以待机模式的唤醒延时也是最大的。实际应用中要根据使用环境和要求选择合适的待机模式。

二、Tickless 模式详解

1. 如何降低功耗?

在之前介绍获取任务运行时间信息的时候可以看出,一般的简单应用中处理器大量的时间都在处理空闲任务,所以我们就可以考虑当处理器处理空闲任务的时候就进入低功耗模式,当需要处理应用层代码的时候就将处理器从低功耗模式唤醒。FreeRTOS 就是通过在处理器处理空闲任务的时候将处理器设置为低功耗模式来降低能耗。一般会在空闲任务的钩子函数中执行低功耗相关处理,比如设置处理器进入低功耗模式、关闭其他外设时钟、降低系统主频等等。

本篇后面均以 STM32F103 三个低功耗模式中的睡眠模式为例讲解。
FreeRTOS 的系统时钟是由滴答定时器中断来提供的,系统时钟频率越高,那么滴答定时器中断频率也就越高。中断是可以将 STM32F03 从睡眠模式中唤醒,周期性的滴答定时器中断就会导致 STM32F4103 周期性的进入和退出睡眠模式。因此,如果滴答定时器中断频率太高的话会导致大量的能量和时间消耗在进出睡眠模式中,这样导致的结果就是低功耗模式的作用被大大的削弱。

为此,FreeRTOS 特地提供了一个解决方法——Tickless 模式,当处理器进入空闲任务周期以后就关闭系统节拍中断(滴答定时器中断),只有当其他中断发生或者其他任务需要处理的时候处理器才会被从低功耗模式中唤醒。为此我们将面临两个问题:

问题一: 关闭系统节拍中断会导致系统节拍计数器停止,系统时钟就会停止。
FreeRTOS 的系统时钟是依赖于系统节拍中断(滴答定时器中断)的,如果关闭了系统节拍中断的话就会导致系统时钟停止运行,这是绝对不允许的!该如何解决这个问题呢?我们可以记录下系统节拍中断的关闭时间,当系统节拍中断再次开启运行的时候补上这段时间就行了。这时候我们就需要另外一个定时器来记录这段该补上的时间,如果使用专用的低功耗处理器的话基本上都会有一个低功耗定时器,比如 STM32L4 系列(L 系列是 ST 的低功耗处理器)就有一个叫做 LPTIM(低功耗定时器)的定时器。STM32F103 没有这种定时器那么就接着使用滴答定时器来完成这个功能。

问题二: 如何保证下一个要运行的任务能被准确的唤醒?
即使处理器进入了低功耗模式,但是我的中断和应用层任务也要保证及时的响应和处理。中断自然不用说,本身就可以将处理器从低功耗模式中唤醒。但是应用层任务就不行了,它无法将处理器从低功耗模式唤醒,无法唤醒就无法运行!这个问题看来很棘手,既然应用层任务无法将处理器从低功耗模式唤醒,那么我们就借助其他的力量来完成这个功能。如果处理器在进入低功耗模式之前能够获取到还有多长时间运行下一个任务那么问题就迎刃而解了,我们只需要开一个定时器,定时器的定时周期设置为这个时间值就行了,定时时间到了以后产生定时中断,处理器不就从低功耗模式唤醒了。这里似乎又引出了一个新的问题,那就是如何知道还有多长时间执行下一个任务?这个时间也就是低功耗模式的执行时间,值得庆辛的是 FreeRTOS已经帮我们完成了这个工作。

2. Tickless 具体实现

(1)宏 configUSE_TICKLESS_IDLE
要想使用 Tickless 模式,首先必须将 FreeRTOSConfig.h 中的宏 configUSE_TICKLESS_IDLE设置为 1,代码如下:

#define configUSE_TICKLESS_IDLE 1 //1 启用低功耗 tickless 模式

(2)宏 portSUPPRESS_TICKS_AND_SLEEP()
使能 Tickless 模式以后当下面两种情况都出现的时候 FreeRTOS 内核就会调用宏
portSUPPRESS_TICKS_AND_SLEEP()来处理低功耗相关的工作。

● 空闲任务是唯一可运行的任务,因为其他所有的任务都处于阻塞态或者挂起态。
● 系统处于低功耗模式的时间至少大configEXPECTED_IDLE_TIME_BEFORE_SLEEP
个时钟节拍,宏 configEXPECTED_IDLE_TIME_BEFORE_SLEEP 默认在文件 FreeRTOS.h 中定义为 2,我们可以在 FreeRTOSConfig.h 中重新定义,此宏必须大于 2!

portSUPPRESS_TICKS_AND_SLEEP()有个参数,此参数用来指定还有多长时间将有任务进入就绪态,其实就是处理器进入低功耗模式的时长(单位为时钟节拍数),因为一旦有其他任务 进 入 就 绪 态 处 理 器 就 必 须 退 出 低 功 耗 模 式 去 处 理 这 个 任 务 。
portSUPPRESS_TICKS_AND_SLEEP()应该是由用户根据自己所选择的平台来编写的,此宏会被空闲任务调用来完成具体的低功耗工作。

宏 portSUPPRESS_TICKS_AND_SLEEP 在文件 portmacro.h 中如下定义:

#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
 vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif

从 上 面 的 代 码 可 以 看 出 portSUPPRESS_TICKS_AND_SLEEP() 的 本 质 就 是 函 数vPortSuppressTicksAndSleep(),此函数在文件 port.c 中有如下定义:

__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements,\
	 ulSysTickCTRL;
	TickType_t xModifiableIdleTime;
	//确保滴答定时器的 Reload(重装载)值不会溢出,也就是不能超过滴答定时器最大计数值。
	if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) (1)
	{
		xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
	}
	//停止滴答定时器。
	portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
	//根据参数 xExpectedIdleTime 来计算滴答定时器的重装载值。
	ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG +\ (2)
	 ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
	if( ulReloadValue > ulStoppedTimerCompensation ) (3)
	{
		ulReloadValue -= ulStoppedTimerCompensation;
	}
	__disable_irq(); (4)
	__dsb( portSY_FULL_READ_WRITE );
	__isb( portSY_FULL_READ_WRITE );
	//确认是否可以进入低功耗模式
	if( eTaskConfirmSleepModeStatus() == eAbortSleep ) (5)
	{
		//不能进入低功耗模式,重新启动滴答定时器
		portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
		portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
		portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
		__enable_irq(); (6)
	}
	else (7)
	{
		//可以进入低功耗模式,设置滴答定时器
		portNVIC_SYSTICK_LOAD_REG = ulReloadValue; (8)
		portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
		portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
		xModifiableIdleTime = xExpectedIdleTime;
		configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); (9)
		if( xModifiableIdleTime > 0 )
		{
			__dsb( portSY_FULL_READ_WRITE );
			__wfi(); (10)
			__isb( portSY_FULL_READ_WRITE );
		}
		//当代码执行到这里的时候说明已经退出了低功耗模式!
		configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); (11)
		//停止滴答定时器
		ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; (12)
		portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL &\
		 ~portNVIC_SYSTICK_ENABLE_BIT );
		__enable_irq(); (13)
		//判断导致退出低功耗的是由外部中断引起的还是滴答定时器计时时间到引起的
		if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) (14)
		{
			uint32_t ulCalculatedLoadValue;
			ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue -\
			 portNVIC_SYSTICK_CURRENT_VALUE_REG );
			if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) ||\
			 ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
			{
				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
			}
			portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
			ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
		}
		else //外部中断唤醒的,需要进行时间补偿
		{
			ulCompletedSysTickDecrements = ( xExpectedIdleTime * \
			ulTimerCountsForOneTick ) -\
			portNVIC_SYSTICK_CURRENT_VALUE_REG;
			ulCompleteTickPeriods = ulCompletedSysTickDecrements / \
			 ulTimerCountsForOneTick;
			portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * \
			ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
		}
		//重新启动滴答定时器,滴答定时器的重装载值设置为正常值。
		portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
		portENTER_CRITICAL();
		{
			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
			vTaskStepTick( ulCompleteTickPeriods ); (15)
			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
		}
		portEXIT_CRITICAL();
	}
}

(1)、参数 xExpectedIdleTime 表示处理器将要在低功耗模式运行的时长(单位为时钟节拍数),这个时间会使用滴答定时器来计时,但是滴答定时器的计数寄存器是 24 位的,因此这个时间值不能超过滴答定时器的最大计数值。xMaximumPossibleSuppressedTicks 是个静态全局变量,在文件 port.c 中有定义,此变量会在函数 vPortSetupTimerInterrupt()中被重新赋值,代码如下:

ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;

经过计算 xMaximumPossibleSuppressedTicks=0xffffff/(72000000/1000)≈233,因此可以得出进入低功耗模式的最大时长为 233 个时钟节拍,注意!这个值要根据自己所使用的平台以及FreeRTOS 的实际配置情况来计算。

(2)、根据参数 xExpectedIdleTime 来计算滴答定时器的重装载值,因为处理器进入低功耗模式以后的计时是由滴答定时器来完成的。

(3)、从滴答定时器停止运行到把统计得到的低功耗模式运行的这段时间补偿给 FreeRTOS系统时钟也是需要时间的,这期间也是有程序在运行的。这段程序运行的时间我们要留出来,具体的时间没法去统计,因为平台不同、编译器的代码优化水平不同导致了程序的执行时间也不同。这里只能大概的留出一个时间值,这个时间值由变量 ulStoppedTimerCompensation 来确定,这是一个全局变量,在文件 port.c 中有定义。此变量也会在函数 vPortSetupTimerInterrupt()中被重新赋值,代码如下:

#define portMISSED_COUNTS_FACTOR ( 45UL )
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / \
configSYSTICK_CLOCK_HZ );

由上面的公式可以得出ulStoppedTimerCompensation=45/(72000000/72000000)=45。如果要修改这个时间值的话直接修改宏 portMISSED_COUNTS_FACTOR 即可。

(4)、在执行 WFI 前设置寄存器 PRIMASK 的话处理器可以由中断唤醒但是不会处理这些
中断,退出低功耗模式以后通过清除寄存器 PRIMASK 来使 ISR 得到执行,其实就是利用PRIMASK 来延迟 ISR 的执行。函数__disable_irq()是用来设置寄存器 PRIMASK 的,清除寄存器 PRIMASK 使用函数__enable_irq(),这两个函数是由 CMSIS-Core 提供的,如果所使用的例程添加了 CMSIS 相关文件的话就可以直接拿来用,ALIENTEK 的所有例程都添加了。

(5)、调用函数 eTaskConfirmSleepModeStatus()来判断是否可以进入低功耗模式,此函数在文件 tasks.c 中有定义。此函数通过检查是否还有就绪任务来决定处理器能不能进入低功耗模式,如果返回 eAbortSleep 的话就表示不能进入低功耗模式,既然不能进入低功耗那就需要重新恢复滴答定时器的运行。

(6)、调用函数__enable_irq()重新打开中断,因为在(4)中我们调用函数__disable_irq()关闭了中断。

(7)、可以进入低功耗模式,完成低功耗相关设置。

(8)、进入低功耗模式的时间已经在(2)中计算出来了,这里将这个值写入到滴答定时器的重装载寄存器中。

(9)、configPRE_SLEEP_PROCESSING()是个宏,在进入低功耗模式之前可能有一些其他的事情要处理,比如降低系统时钟、关闭外设时钟、关闭板子某些硬件的电源等等,这些操作就可以在这个宏中完成,后面会讲解这个宏如何使用。

(10)、使用 WFI 指令使 STM32进入睡眠模式。

(11)、代码执行到这里说明处理器已经退出了低功耗模式,退出低功耗模式以后也可能需要处理一些事情。比如恢复系统时钟,使能外设时钟,打开板子某些硬件的电源等等,这些操作在宏 configPOST_SLEEP_PROCESSING()中完成,后面会讲解这个宏如何使用。

(12)、读取滴答定时器 CTRL(控制和状态)寄存器,后面要用。

(13)、调用函数__enable_irq()打开中断。

(14)、判断退出低功耗模式是由滴答定时器中断引起的还是由其他中断引起的,因为这两种原因所对应的系统时钟赔偿值的计算方法不同,这个系统时钟补偿值的单位是时钟节拍。

(15)、调用函数 vTaskStepTick()补偿系统时钟,函数参数是要补偿的值,此函数在文件 tasks.c中有如下定义:

void vTaskStepTick( const TickType_t xTicksToJump )
{
	configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
	xTickCount += xTicksToJump;
	traceINCREASE_TICK_COUNT( xTicksToJump );
}

可以看出,此函数很简单,只是给 FreeRTOS 的系统时钟节拍计数器 xTickCount 加上一个补偿值而已。

(3)宏 configPRE_SLEEP_PROCESSING ()和configPOST_SLEEP_PROCESSING()

在真正的低功耗设计中不仅仅是将处理器设置到低功耗模式就行了,还需要做一些其他的处理,比如:
● 将处理器降低到合适的频率,因为频率越低功耗越小,甚至可以在进入低功耗模式以后关闭系统时钟。
● 修改时钟源,晶振的功耗肯定比处理器内部的时钟源高,进入低功耗模式以后可以切换到内部时钟源,比如 STM32 的内部 RC 振荡器。
● 关闭其他外设时钟,比如 IO 口的时钟。
● 关闭板子上其他功能模块电源,这个需要在产品硬件设计的时候就要处理好,比如可以通过 MOS 管来控制某个模块电源的开关,在处理器进入低功耗模式之前关闭这些模块的电源。

有关产品低功耗设计的方法还有很多,大家可以上网查找一下,上面列举出的这几点在处理器进入低功耗模式之前就要完成处理。FreeRTOS 为我们提供了一个宏来完成这些操作,它就是 configPRE_SLEEP_PROCESSING(),这个宏的具体实现内容需要用户去编写。如果在进入低功耗模式之前我们降低了处理器频率、关闭了某些外设时钟等的话,那在退出低功耗模式以后就 需 要 恢 复 处 理 器 频 率 、 重 新 打 开 外 设 时 钟 等 , 这 个 操 作 在 宏configPOST_SLEEP_PROCESSING()中完成,同样的这个宏的具体内容也需要用户去编写。这两个宏会被函数 vPortSuppressTicksAndSleep()调用,我们可以在 FreeRTOSConfig.h 定义这两个宏,
如下:

/********************************************************************************/
/* FreeRTOS 与低功耗管理相关配置 */
/********************************************************************************/
extern void PreSleepProcessing(uint32_t ulExpectedIdleTime);
extern void PostSleepProcessing(uint32_t ulExpectedIdleTime);
//进入低功耗模式前要做的处理
#define configPRE_SLEEP_PROCESSING PreSleepProcessing
//退出低功耗模式后要做的处理
#define configPOST_SLEEP_PROCESSING PostSleepProcessing

(4)宏 configEXPECTED_IDLE_TIME_BEFORE_SLEEP
处理器工作在低功耗模式的时间虽说没有任何限制,1 个时钟节拍也行,滴答定时器所能计时的最大值也行。但是时间太短的话意义也不大啊,就 1 个时钟节拍,我这刚进去就得出来!

所 以 我 们 必 须 对 工 作 在 低 功 耗 模 式 的 时 间 做 个 限 制 , 不 能 太 短 了 , 宏
configEXPECTED_IDLE_TIME_BEFORE_SLEEP 就是用来完成这个功能的。此宏默认在文件FreeRTOS 中有定义,如下:

#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
#endif
#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2
#error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2
#endif

默认情况下 configEXPECTED_IDLE_TIME_BEFORE_SLEEP 为 2 个时钟节拍,并且最小不能小于 2 个时钟节拍。如果要修改这个值的话可以在文件 FreeRTOSConfi.h 中对其重新定义。此宏会在空闲任务函数 prvIdleTask()中使用!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5_服务编排_docker-compose

服务编排之Docker Compose 微服务架构的应用系统中一般包含若干个微服务&#xff0c;每个微服务一般都会部署多个实例&#xff0c;如果每个微服务都要手动启停&#xff0c;维护的工作量会很大。 要从Dockerfile build image 或者去dockerhub拉取image 要创建多个container 要…

GB/T25915.1法规基本标准-洁净室按粒子浓度划分洁净

《GB/T25915.1-2021洁净室及相关受控环境 第一部分&#xff1a;按粒子浓度划分空气洁净度等级》等4部国家标准。 今天小编跟大家分享一下参编的GB/T25915.1-2021相关法规文件内容&#xff0c;帮助大家更好的了解相关法规知识。 1 范围 本文件规定了按空气中悬浮粒子浓度划分洁…

9:00进去,9:05就出来了,这问的也太···

从外包出来&#xff0c;没想到死在另一家厂子了。 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到8月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内推…

纯前端 根据目录解析word,拆分不同段落

前期回顾 两分钟学会 制作自己的浏览器 —— 并将 ChatGPT 接入_0.活在风浪里的博客-CSDN博客自定义浏览器&#xff0c;并集合ChatGPT&#xff0c;源码已公开https://blog.csdn.net/m0_57904695/article/details/130467253?spm1001.2014.3001.5501 &#x1f44d; 本文专栏…

Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键

一.前言 当我们接入XR Interaction Toolkit之后&#xff0c;我们可以很方便的做不同VR设备的适配&#xff0c;这在很大程度上提升了我们的开发效率&#xff0c;我们除了通过射线和物体交互之外&#xff0c;偶尔我们也会希望监听手柄上的部分按键的点击事件&#xff0c;今天我们…

网络安全大厂面试题合集

以下为网络安全各个方向涉及的面试题合集&#xff0c;星数越多代表问题出现的几率越大&#xff0c;祝各位都能找到满意的工作。 注&#xff1a;本套面试题&#xff0c;已整理成pdf文档&#xff0c;但内容还在持续更新中&#xff0c;因为无论如何都不可能覆盖所有的面试问题&…

国考省考结构化面试:情景模拟题的答题思路,人际关系题的变种,就题答题,灵活多变,关键在自己多思考,说话要有艺术

国考省考结构化面试&#xff1a;情景模拟题的答题思路&#xff0c;人际关系题的变种&#xff0c;就题答题&#xff0c;灵活多变&#xff0c;关键在自己多思考&#xff0c;说话要有艺术 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带…

ansible常用模块总结

目录 一、 assert模块 二、 authorized_key模块 三、at模块 四、blockinfile模块 五、command模块 六、copy模块 七、 cron模块 八、 firewalld模块 九、 fail模块 十、 file模块 十一、 fetch模块 十二、filesystem模块 十三、 get_url模块 十四、group模块 十…

基于pytorch+transformers的车牌识别

目录 程序流程设计熟悉训练数据集CCPD2019数据集CCPD数据集标注信息单例再现 加载本地车牌数据集 程序流程设计 1&#xff0c;熟悉训练数据集&#xff1b; 2&#xff0c;加载本地车牌数据集&#xff1b; 3&#xff0c;定义网络模型&#xff1b; 4&#xff0c;输入数据集训练模…

关于复杂事件处理和事件驱动架构的争论

复杂事件处理&#xff08;Complex Event Processing&#xff0c;CEP&#xff09;系统和事件驱动架构&#xff08;Event Driven Architecture&#xff0c;EDA&#xff09;都被认为会在目前和未来的精致繁杂的系统设计中扮演重要角色。但是它们的角色是什么&#xff1f;会对业界产…

初识vue-模板

目录 模板语法 模板插值 指令 条件渲染&#xff08;v-if &#xff1b;v-show&#xff09; 列表循环&#xff08;v-for&#xff09; ref JSX&#xff08;render渲染&#xff09; 条件渲染 列表渲染 八皇后框架-背景格&#xff08;循环&#xff09; 模板语法 Vue.js使用了…

Vue3+Element Plus环境搭建和一键切换明暗主题的配置

Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。而Element Plus是一款基于Vue3面向设计师和开发者的组件库。 最终效果&#xff1a; 环境搭建 已安装 16.0 或更高版本的 Node.js&#xff0c;终端&#xff1a; npm init vuelatest这一…

智慧校园系统平台实现校内导航资产管线一体化管理

构建智慧校园系统平台是国家和大专院校共同倡议的校园信息化建设方向&#xff0c;是运用物联网技术搭建的一体化综合平台&#xff0c;基于各种应用服务系统&#xff0c;把学校的教务、办公、教学、学习、管理、资产、校园安全、安防、消防等各个环节融为一体&#xff0c;提高学…

MATLAB算法实战应用案例精讲-【人工智能】对比学习(概念篇)(补充篇)

目录 前言 几个高频面试题目 基于对比学习(ContrastiveLearning)的文本表示模型【为什么】能学到文本【相似】度&#xff1f; 为什么对比学习能学到很好的语义相似度&#xff1f; 那么如何评价这个表示空间的质量呢&#xff1f; 知识储备 监督学习和非监督学习 算法原理…

Web开发人员的10个数据库优化最佳实践

数据库优化已经成为web开发人员提高web应用程序性能&#xff0c;从而改善用户体验的关键。对一些人来说&#xff0c;这可能听起来不太吸引人&#xff0c;但如果能正确地优化数据库&#xff0c;就可以提高性能、减少瓶颈并节省资源。 幸运的是&#xff0c;有些优化技术在sql查询…

sqlserver object_id()函数学习

在SQLServer数据库中&#xff0c;如果查询数据库中是否存在指定名称的索引或者外键约束等&#xff0c;经常会用到object_id(name,type)方法&#xff0c; 语法&#xff1a;object_id(objectname)或object(objectname,type) 作用&#xff1a;该函数会返回指定对象的ID值&#xf…

springboot 整合ehchace 缓存教程

ehcache介绍 Ehcache是一种高性能、开源的Java缓存框架&#xff0c;被广泛应用于许多大规模、高并发的分布式系统中。它提供了一种快速、可扩展、分布式的数据缓存方案&#xff0c;支持各种内存级别的缓存、磁盘级别的缓存、分布式缓存等。Ehcache设计目标主要是提供高性能和可…

【LeetCode】198.打家劫舍

198.打家劫舍&#xff08;中等&#xff09; 思路 定义数组 dp&#xff0c; dp[i] 表示抢劫到第 i 个房子的时候&#xff0c;可以抢劫的最大数量。dp[i] 有两种可能&#xff1a;一种是我们选择不抢劫这个房子&#xff0c;此时累积金额为 dp[i-1] &#xff1b;另一种是我们选择抢…

儿童用灯哪个品牌好?推荐专业的儿童护眼台灯

一款好的儿童台灯&#xff0c;主要是从5个方面决定&#xff0c;照度及均匀度&#xff0c;蓝光&#xff0c;色温&#xff0c;显指&#xff0c;频闪 ① 照度及均匀度最高是国AA级&#xff0c;其次就是国A级 ② 蓝光一定要选择RG0无危险级&#xff0c;蓝光能量最强&#xff0c;…

给你安利一款不需要魔法就能免费使用的idea插件Bito-ChatGPT

一款不需要魔法就能免费使用的idea插件Bito-ChatGPT 一 、写在前面二、Bito是什么&#xff1f; &#x1f511;&#x1f511; **What does Bito AI do?**三 、安装Bito四、使用Bito4.1 创建个人工作空间4.2 使用Bito4.2.1 问任何技术问题&#xff08;Ask any technical questio…