【ESP32+freeRTOS学习笔记-(九)事件组】

news2024/11/26 0:55:50

目录

  • 1、概述
  • 2、事件组的特性
    • 2.1 事件组、事件标志和事件位
    • 2.2 事件组位长的设置
    • 2.3 多任务访问
  • 3、使用事件组管理事件
    • 3.1 xEventGroupCreate()
    • 3.2 xEventGroupSetBits()
    • 3.3 xEventGroupGetBits()
    • 3.4 xEventGroupWaitBits()
    • 3.5 示例
  • 4、使用事件组同步任务
    • 4.1 xEventGroupSync()
    • 4.2 实例
    • 5 总结

1、概述

实时嵌入式系统必须采取行动来响应事件。前面描述了 FreeRTOS 允许将事件传递给任务的功能。此类功能包括信号量和队列,它们都具有以下属性:
-》它们允许任务在阻塞状态下等待单个事件发生。
-》当事件发生时,它们解除对单个任务的阻塞——解除阻塞的任务是等待事件的最高优先级任务。

事件组是 FreeRTOS 的另一个功能,它允许将事件传达给任务。与队列和信号量不同:
事件组允许任务在阻塞状态下等待多个事件之一的组合发生。
事件组在事件发生时解除等待同一事件或事件组合的所有任务的阻塞。

事件组的这些独特属性使其可用于同步多个任务、将事件广播到多个任务、允许任务在阻塞状态等待一组事件中的任何一个发生
,以及允许任务处于阻塞状态中等待多个操作的完成

事件组还提供了减少应用程序使用的 RAM 的机会,因为通常可以用单个事件组替换许多二进制信号量。
事件组功能是可选的。要包含事件组功能,请将 FreeRTOS 源文件 event_groups.c 构建为项目的一部分。

2、事件组的特性

2.1 事件组、事件标志和事件位

一个事件组可以同时设置8个或24个事件。

事件“标志”是一个布尔值(1 或 0),用于指示事件是否发生。
事件“组”是一组事件标志。

一个事件标志只能为 1 或 0,允许将一个事件标志的状态存储在一个位中,并将一个事件组中所有事件标志的状态存储在一个变量中;事件组中每个事件标志的状态由 EventBits_t 类型变量中的单个位表示。因此,事件标志也称为事件“位”。

如果 EventBits_t 变量中的某个位设置为 1,则该位表示的事件已经发生。如果EventBits_t 变量中的某个位设置为0,则该位表示的事件尚未发生。
在这里插入图片描述

例如:如果事件组的值为 0x92(二进制 1001 0010),即,仅设置事件位 1、4 和 7,因此仅发生了位 1、4 和 7 表示的事件。
在这里插入图片描述
而1,4,7对应的事件含义是由开发者定义的。比如,将事件组中的位 1 定义为“已从网络接收到消息”;将事件组中的第 4位定义为“一条消息已准备好发送到网络上”;将事件组中的第 7 位定义为“中止当前网络连接”。

2.2 事件组位长的设置

事件组中的事件位数取决于 FreeRTOSConfig.h 中的 configUSE_16_BIT_TICKS 编译时间配置的常量:
如果 configUSE_16_BIT_TICKS 为 1,则每个事件组包含 8 个可用事件位。
如果 configUSE_16_BIT_TICKS 为 0,则每个事件组包含 24 个可用事件位。

2.3 多任务访问

事件组本身就是对象,任何知道它们存在的任务或 ISR 都可以访问这些对象。任意数量的任务可以设置同一事件组中的位,任意数量的任务可以从同一事件组中读取位。

3、使用事件组管理事件

3.1 xEventGroupCreate()

在这里插入图片描述

描述

创建一个新的事件组并返回一个句柄,通过该句柄可以引用所创建的事件组。

事件组存储在EventGroupHandle_t类型的变量中。如果configUSE_16_BIT_TICKS设置为1,则事件组中实现的位数(或标志)为8;如果configUSE_1 6_BIT_TIC设置为0,则为24。

返回值

NULL : 事件组创建失败。因为没有足够的堆内存。

非NULL的其它值:事件组创建成功,返回的是事件组的句柄。

3.2 xEventGroupSetBits()

在这里插入图片描述
描述

xEventGroupSetBits() API 函数设置事件组中的一个或多个位,通常用于通知任务已发生由正在设置的一个或多个位表示的事件。
设置RTOS事件组中的位(标志)。不能从中断调用此函数。
有关可以从中断调用的版本,请参阅xEventGroupSetBitsFromISR()。
在事件组中设置的位将自动解除那些处于阻塞状态的任务。这些任务正等待这些被设置的位而处于阻塞状态。

参数

参数说明
xEventGroup要被设置的事件组的句柄
uxBitsToSet一种位掩码,指定事件组中要设置为1的单个或多个事件位。事件组的值通过将事件组的现有值与uxBitsToSet中传递的值按位“或”来更新例如,将uxBitsToSet设置为0x08以设置位3。将uxBitsToSet设置为0x09以设置位3和位0。同时保持事件组中所有其他事件位不变。

反回值

返回调用xEventGroupSetBits()时事件组中位的值。
返回值被uxBitsToSet参数指定的位可能被清除,原因有两个:
1.如果设置的位导致等待此位的任务离开阻塞状态,则该位可能已被自动清除(请参阅xEventGroupWaitBits()的xClearBitsOnExit参数。
2.由于位被设置而离开阻塞状态的任何任务(或任何就绪状态任务),其优先级高于调用xEventGroupSetBits()的任务的优先级,将执行该高优先级任务,并可能在调用xEventGroup SetBits)返回之前更改事件组值。

3.3 xEventGroupGetBits()

在这里插入图片描述

描述
返回事件组中事件位(事件标志)的当前值。此功能不能在中断中使用。有关可用于中断的版本,请用xEventGroupGetBitsFromISR()。

参数

xEventGroup : 目标事件组句柄。

3.4 xEventGroupWaitBits()

在这里插入图片描述

描述
xEventGroupWaitBits() API 函数允许任务读取事件组的值,如果尚未设置事件位,则可选择在阻塞状态等待事件组中的一个或多个事件位被设置。

参数

参数说明
xEventGroup事件组句柄
uxBitsToWaitFor一个位值,指示事件组中要检测的位。例如,要等待位0 and/or 位2,请将uxBitsToWaitFor设置为0x05。要等待位0 and/ or 位1 and / or 2,请将uxBitsToWaitFor设置为0x07。uxBitsToWaitFor不能设置为0。
xClearOnExit如果xClearOnExit设置为pdTRUE,则如果xEventGroupWaitBits()因超时以外的任何原因返回,则在xEventGroupWaitBits)返回之前,将在事件组中清除作为uxBitsToWaitFor参数传递的值中设置的任何位。超时值由xTicksToWait参数设置。如果xClearOnExit设置为pdFALSE,则当对xEventGroupWaitBits()的调用返回时,不会更改事件组中设置的位。
xWaitForAllBitsxWaitForAllBits用于创建逻辑AND测试(所有检测位必须都被置1)或逻辑or测试(一个或多个检测位被置1就可以)。
xTicksToWait阻塞等待时长,以tick计数的时间单位

返回值

等待的事件位被设置或块时间到期时事件组的值。如果较高优先级的任务或中断在调用任务离开阻止状态和退出xEventGroupWaitBits()函数之间更改了事件位的值,则事件组中事件位的当前值将与返回值不同。
测试返回值以了解设置了哪些位。如果xEventGroupWaitBits()因超时而返回,则不会设置所有等待的位。如果xEventGroupWaitBits()返回是因为它等待的位被设置,则返回的值是在xClearOnExit参数设置为pdTRUE的情况下自动清除任何位之前的事件组值。

3.5 示例

此示例演示如何创建一个事件组,通过中断服务程序设置事件组中的位,从任务中设置事件组中的位,阻塞一个事件组。
xEventGroupWaitBits() xWaitForAllBits 参数的效果通过首先执行 xWaitForAllBits 设置为 pdFALSE 的示例,然后执行
xWaitForAllBits 设置为 pdTRUE 的示例来演示。
事件位 0 和事件位 1 从任务中设置。事件位 2 通过中断服务程序设置。

使用下方代码所示的 #define 语句为这三位指定描述名称。
在这里插入图片描述

以下代码显示了设置事件位 0 和事件位 1 的任务的实现。它位于一个循环中,重复设置一个位,然后另一个位,每次调用EventGroupSetBits() 之间有 200 毫秒的延迟。在设置每个位之前打印出一个字符串,以允许在控制台中看到执行顺序。

以下代码 显示了在事件组中设置位 2 的中断服务例程的实现。同样,在设置位之前打印出一个字符串,以允许在控制台中看到执行顺序。然而,在这种情况下,由于不应直接在中断服务例程中执行控制台输出,因此 xTimerPendFunctionCallFromISR() 用于在 RTOS 守护程序任务的上下文中执行输出。
与前面的示例一样,中断服务程序由一个强制软件中断的简单周期性任务触发。在此示例中,每 500 毫秒生成一次中断。

static uint32_t ulEventBitSettingISR( void )
{
	static const char *pcString = "Bit setting ISR -\t about to set bit 2.\r\n";
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 	/* Print out a message to say bit 2 is about to be set. Messages cannot be
 	printed from an ISR, so defer the actual output to the RTOS daemon task by
 	pending a function call to run in the context of the RTOS daemon task. */
 	xTimerPendFunctionCallFromISR( vPrintStringFromDaemonTask, 
 									( void * ) pcString, 
 									0, 
 									&xHigherPriorityTaskWoken );
 	/* Set bit 2 in the event group. */
 	xEventGroupSetBitsFromISR( xEventGroup, mainISR_BIT, &xHigherPriorityTaskWoken );
 	/* xTimerPendFunctionCallFromISR()和xEventGroupSetBitsFromISR()都写入计时器命令队列,并且都使用相同的
	xHigherPriorityTaskWoken变量。如果写入计时器命令队列导致RTOS守护进程任务离开阻塞状态,如果RTOS守护进程任务的优先
	级高于当前正在执行的任务的优先级(该中断中断的任务),则xHigherPriorityTaskWoken将被设置为pdTRUE.
	.xHigherPriorityTaskWoken用作portYIELD_FROM_ISR()的参数。如果xHigherPriorityTaskWoken等于pdTRUE,
	则调用portYIELD_FROM_ISR()将请求上下文切换。如果xHigherPriorityTaskWoken仍然是pdFALSE,
	那么调用portYIELD_FROM_ISR()将无效。 */
 	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

以下的代码 显示了调用 xEventGroupWaitBits() 以阻塞事件组的任务的实现。该任务为事件组中设置的每个位打印一个字
符串。
xEventGroupWaitBits() xClearOnExit 参数设置为 pdTRUE,因此导致调用 xEventGroupWaitBits() 返回的事件位将在
xEventGroupWaitBits() 返回之前自动清除。

static void vEventBitReadingTask( void *pvParameters )
{
	EventBits_t xEventGroupValue;
	const EventBits_t xBitsToWaitFor = ( mainFIRST_TASK_BIT | mainSECOND_TASK_BIT | mainISR_BIT );
 	for( ;; )
 	{
 		/* 阻塞以等待事件组中的对应事件位被置位。 */
 		xEventGroupValue = xEventGroupWaitBits( xEventGroup,      //事件组
 												xBitsToWaitFor,   //检测的事件位
 												pdTRUE,    //退出阻塞后,清除对应的事件位。
 												pdFALSE,   // 或操作,只要有一个需要的事件位被置位就退出。
 												portMAX_DELAY   /* 一直等待 */
 											);
 		/* 打印对应事件位的信息. */
 		if( ( xEventGroupValue & mainFIRST_TASK_BIT ) != 0 )
 		{
 			vPrintString( "Bit reading task -\t Event bit 0 was set\r\n" );
 		}
 		if( ( xEventGroupValue & mainSECOND_TASK_BIT ) != 0 )
 		{
 			vPrintString( "Bit reading task -\t Event bit 1 was set\r\n" );
 		}
 		if( ( xEventGroupValue & mainISR_BIT ) != 0 )
 		{
 			vPrintString( "Bit reading task -\t Event bit 2 was set\r\n" );
 		}
 	}
 }

main() 函数在启动调度程序之前创建事件组和任务。从事件组中读取的任务的优先级高于写入事件组的任务的优先级,保证每次满足读取任务的解锁条件时,读取任务都会抢占写入任务。

int main( void )
{
 	xEventGroup = xEventGroupCreate();  //创建事件组
 	/* 创建任务,用以设置事件组中的事件位 */
 	xTaskCreate( vEventBitSettingTask, "Bit Setter", 1000, NULL, 1, NULL );
 	/* 创建任务,用以读取事件组中的事件位。 */
 	xTaskCreate( vEventBitReadingTask, "Bit Reader", 1000, NULL, 2, NULL );
 	/* 创建任务用以生成中断 */
 	xTaskCreate( vInterruptGenerator, "Int Gen", 1000, NULL, 3, NULL );
 	/* 设置中断ISR. */
 	vPortSetInterruptHandler( mainINTERRUPT_NUMBER, ulEventBitSettingISR );
 	vTaskStartScheduler();
 	for( ;; );
 	return 0;
}

xEventGroupWaitBits()函数中的xWaitForAllBits 参数被设置为pdFALSE时的输出。
在这里插入图片描述

xEventGroupWaitBits()函数中的xWaitForAllBits 参数被设置为pdTRUE时的输出。

在这里插入图片描述

4、使用事件组同步任务

应用程序的设计有时需要两个或多个任务相互同步。例如,考虑一个设计,其中任务 A 接收事件,然后将事件所需的一些处理委托给其他三个任务:任务 B、任务 C 和任务 D。如果任务 A 直到任务 B、C 和任务 D 已完成它们自已的工作后才能接收另一个事件。 那么所有四个任务都需要相互同步。每个任务的同步点将在该任务完成其处理之后,并且在其他每个任务都完成相同的操作之前无法继续进行。任务 A 只能在所有四个任务都达到它们的同步点后才能接收另一个事件。

也就是说,任务A,B,C,D四个任务都会分别阻塞在一个同步点上,然后当大家都达到同步点后,才同时离开阻塞进入READY状态。

但是,在这种场景下不能使用 xEventGroupSetBits() 和 xEventGroupWaitBits() API 函数。如果它们被使用,那么位的设置(表明一
个任务已经到达它的同步点)和位的测试(以确定其他同步任务是否已经到达它们的同步点)将作为两个独立的操作来执行。要了
解为什么会出现问题,请考虑任务 A、任务 B 和任务 C 尝试使用事件组进行同步的场景:

  1. 任务A和任务B已经到达同步点,所以它们的事件位在事件组中被置位,它们处于阻塞状态等待任务C的事件位也被置位。
  2. 任务 C 到达同步点,并使用 xEventGroupSetBits() 设置其在事件组中的位。一旦任务 C 的位置位,任务 A 和任务 B 就会离开阻塞
    状态,并清除所有三个事件位。
  3. 然后任务 C 调用 xEventGroupWaitBits() 等待所有三个事件位都被置位,但此时所有三个事件位都已被清除,任务 A 和任务 B 已离
    开各自的同步点,因此同步失败了。

要成功地使用事件组创建同步点,事件位的设置和事件位的后续测试必须作为单个不间断操作执行。为此提供了 xEventGroupSync()
API 函数。

4.1 xEventGroupSync()

提供 xEventGroupSync() 以允许两个或多个任务使用事件组相互同步。该函数允许任务在一个事件组中设置一个或多个事件位,
然后等待在同一事件组中设置一组事件位,然后等待在同一事件组中设置事件位的组合作为单个不间断操作。

在这里插入图片描述

参数

参数说明
xEventGroup事件组句柄
uxBitsToSet一个位掩码,指定要在事件组中设置为 1 的事件位或事件位。事件组的值通过将事件组的现有值与uxBitsToSet 中传递的值进行按位或运算来更新。例如,将 uxBitsToSet 设置为 0x04(二进制 0100)将导致设置事件位3(如果尚未设置),同时保持事件组中的所有其他事件位不变。
uxBitsToWaitFor一个位掩码,指定要在事件组中测试的一个或多个事件位。例如,如果调用任务想要等待事件组中的事件位 0、1 和 2 被设置,则将 uxBitsToWaitFor 设置为 0x07(二进制 111)
xTicksToWait等待阻塞时间,时间单位是tick

返回值
Returned Value:如果xEventGroupSync() 因为调用任务的解锁条件被满足而返回,那么返回的值就是事件的值满足调用任务的解锁条件时的值(在任何位自动清零之前)。在这种情况下,返回值也将满足调用任务的解锁条件。
如果 xEventGroupSync() 是因为xTicksToWait 参数指定的阻塞时间到期而返回,则返回值是阻塞时间到期时事件组的值。在这种情况下,返回值将不满足调用任务的解锁条件。

4.2 实例

本示例 使用 xEventGroupSync() 同步单个任务实现的三个实例。 task 参数用于将任务在调用 xEventGroupSync() 时设置的事件位传
递给每个实例。该任务在调用 xEventGroupSync() 之前打印一条消息,并在返回对 xEventGroupSync() 的调用之后再次打印。每条消息都包含一个时间戳。这允许在产生的输出中观察执行顺序。伪随机延迟用于防止所有任务同时到达同步点。

static void vSyncingTask( void *pvParameters )
{
	const TickType_t xMaxDelay = pdMS_TO_TICKS( 4000UL );
	const TickType_t xMinDelay = pdMS_TO_TICKS( 200UL );
	TickType_t xDelayTime;
	EventBits_t uxThisTasksSyncBit;
	const EventBits_t uxAllSyncBits = ( mainFIRST_TASK_BIT | 
 										mainSECOND_TASK_BIT | 
 										mainTHIRD_TASK_BIT );
 	/* 创建三个任务的实例-每个任务使用一个不同事件位用于同步。事件位通过每个任务实例的参数*pvParameters传递进任务。
  	并存在uxThisTaskSyncBit变量中。*/
 	uxThisTasksSyncBit = ( EventBits_t ) pvParameters;
 	for( ;; )
 	{
 		/* 通过延迟伪随机时间来花费一些时间执行操作。这可以防止此任务的所有三个实例同时到达同步点,因此可以更容易地观察示例的行为。*/
 		xDelayTime = ( rand() % xMaxDelay ) + xMinDelay;
 		vTaskDelay( xDelayTime );
 		/* 打印一条消息以显示此任务已达到其同步点。pcTaskGetTaskName()是一个API函数,它返回创建任务时分配给任务的名称。 */
 		vPrintTwoStrings( pcTaskGetTaskName( NULL ), "reached sync point" );
 		/*等待所有任务到达同步点 */
 		xEventGroupSync( xEventGroup,    //事件组句柄
  						uxThisTasksSyncBit,    //此任务设置的位,表示它已到达同步点。
  						uxAllSyncBits,  //等待的位,每个参与同步的任务一位。
  						portMAX_DELAY );
 		/* 打印一条消息以显示此任务已通过其同步点。由于使用了无限期延迟,因此只有在所有任务到达各自的同步点后才会执行以下行。*/
 		vPrintTwoStrings( pcTaskGetTaskName( NULL ), "exited sync point" );
 	}
}

以下为主函数

/* Definitions for the event bits in the event group. */
#define mainFIRST_TASK_BIT ( 1UL << 0UL ) /* Event bit 0, set by the first task. */
#define mainSECOND_TASK_BIT( 1UL << 1UL ) /* Event bit 1, set by the second task. */
#define mainTHIRD_TASK_BIT ( 1UL << 2UL ) /* Event bit 2, set by the third task. */
/* Declare the event group used to synchronize the three tasks. */
EventGroupHandle_t xEventGroup;
int main( void )
{
 	/* Before an event group can be used it must first be created. */
 	xEventGroup = xEventGroupCreate();
 	/* 创建任务的三个实例。每个任务都有一个不同的名称,稍后打印出来,以直观地指示正在执行的任务。
 	当任务到达其同步点时要使用的事件位使用任务参数传递到任务中。 */
 	xTaskCreate( vSyncingTask, "Task 1", 1000, mainFIRST_TASK_BIT, 1, NULL );
 	xTaskCreate( vSyncingTask, "Task 2", 1000, mainSECOND_TASK_BIT, 1, NULL );
	xTaskCreate( vSyncingTask, "Task 3", 1000, mainTHIRD_TASK_BIT, 1, NULL );
 	
 	vTaskStartScheduler();
 
 	for( ;; );
 	return 0;
}

执行示例 时产生的输出如下图 所示。可以看出,即使每个任务在不同(伪随机)时间到达同步点,但每个任务同
时退出同步点 1(即最后一个任务到达同步点的时间)
在这里插入图片描述

5 总结

事件组同时处理一组事件,可以做为事件广播,以及任务同步的工具。

事件广播可以将一个事件通知给一个或多个任务。也可以将多个任务通知给多个任务。这里主要用到的API为xEventGroupSetBits() 和 xEventGroupWaitBits。

事件组用于任务同步时,可以让多个任务同时退出阻塞,同步启动。这里主要用到的API为xEventGroupSync()。

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

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

相关文章

MobaXterm安装与使用

MobaXterm安装与使用 我们首先进入MobaXterm官网&#xff0c;其提供了收费版和免费版&#xff0c;我们使用免费版即可 随后便是安装过程了&#xff0c;很简单。解压后运行该文件一路next即可。 安装完成后我们便可以使用了点击session 选择SSH连接方式&#xff0c;输入服务器…

vue项目——获取指定日期是周几和第几周的信息——表格展示

最近在写后台管理系统&#xff0c;遇到以下的要求&#xff0c;就是要展示 年月日和周几和第几周的情况。 下面记录一下用到的函数&#xff1a; 1.跟据日期获取第几周 //根据日期获取第几周 getWeek(dateTime) {let temptTime new Date(dateTime);//周几let weekday temptT…

浏览器用一行JS代码导出cookies.txt,Python的requests库导入cookies格式化为字典格式

在Python进行爬虫时&#xff0c;如果仅使用requests库打开某个网页&#xff0c;requests的session.cookies保存的cookies信息少得可怜&#xff0c;有时cookies甚至是空白&#xff01;但浏览器里打开同一个网页&#xff0c;cookies信息非常详尽&#xff0c;比如浏览器的cookies保…

2023-02-22 学习记录--TS-邂逅TS(二)

TS-邂逅TS&#xff08;二&#xff09; 不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。&#x1f4aa;&#x1f3fb; 一、接口&#xff08;interface&#xff09; 在 ts 中&#xff0c;子类只能继承一个父类&#xff0c;不可多继承&#xff0c;但是…

2020蓝桥杯真题单词分析 C语言/C++

题目描述 小蓝正在学习一门神奇的语言&#xff0c;这门语言中的单词都是由小写英文字母组 成&#xff0c;有些单词很长&#xff0c;远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词&#xff0c;他准备不再完全记忆这些单词&#xff0c;而是根据单词中哪个字母出…

恭喜!龙蜥社区荣登 2022 科创中国“开源创新榜”

2 月 20 日&#xff0c;中国科协召开以“创新提振发展信心&#xff0c;科技激发产业活力”为主题的2023“科创中国”年度会议。会上&#xff0c;“科创中国”联合体理事长、中国工程院院士周济介绍了 2022 年系列榜单征集遴选情况&#xff0c;并与中国科协副主席、中国工程院院…

音箱上8键触摸芯片绿芯GTC08L完美替换启攀微

由工采网代理提供的韩国GreenChip电容式触摸芯片-GTC08L是GreenTouch5CTM电容式触摸传感器系列之一&#xff1b;可以在发动机运行下进行8通道电容传感&#xff1b;对电磁兼容、电磁干扰、温湿度变化、电压干扰、温度漂移、湿度漂移等都有较强的抗干扰能力。不会对CS, RS,EFT&am…

在vue3+ts的项目中,如何解决vant组件自带表单校验不生效?

问题描述&#xff1a; 点击发送验证码后&#xff0c;为了让逻辑更加严谨&#xff0c;使用了vant组件自带的表单校验&#xff0c;进行二次校验&#xff0c;防止验证码发送成功后&#xff0c;登录手机号被二次修改&#xff0c;但根据官网描述cv之后不生效&#xff0c;甚至连获取…

3年自动化测试,月薪1.2W,不敢跳槽,每天都很焦虑

在我们的身边&#xff0c;存在一个普遍现象&#xff1a;很多人从事软件测试坎&#xff0c;不计其数&#xff0c;经历的心酸难与外人道也。可是技术确难以提升、止步不前&#xff0c;薪资也只能看着别人水涨船高&#xff0c;自己却没有什么起色。虽然在公司里属于不可缺少的一员…

轮播图、阅读注册协议、网页时钟、随机点名、小米搜索框、轮播图点击切换——web APIs练习

目录 一、获取元素&#xff08;DOM&#xff09; 1. 随机轮播图案例 2. 阅读注册协议&#xff08;定时器间歇函数的应用&#xff09; 3. 轮播图定时器版 4. 网页时钟 二、事件基础&#xff08;DOM&#xff09; 1. 随机点名案例 2. 轮播图点击切换&#xff08;重点&#…

Python、Java、JavaScript、C、Go等编程语言如何实现“定时器”功能

这是CSDN平台2月推出的一个活动(活动链接为&#xff1a;CSDN 征文活动)&#xff0c;聊聊时间的话题&#xff0c;小编我也不知道有什么好聊的时间的话题&#xff0c;看了CSDN给出的部分话题上&#xff0c;有一个这样的话题&#xff0c;如何用各种编程语言实现“定时器”&#xf…

初识SpringSpring核心容器

初识Spring Spring生态&#xff1a; Spring FrameWork发展&#xff1a; Spring FrameWork系统架构&#xff1a; Spring FrameWork学习路线&#xff1a; Spring核心概念 Ioc DI 实现IoC 1、导入Spring坐标 2、定义Spring管理的类&#xff08;接口&#xff09; 3、创建spring配…

tensorflow 学习笔记(三):神经网络八股

本节内容&#xff1a; 前两节使用 Tensorflow2 的原生代码大叫神经网络。本节使用 keras 搭建神经网络&#xff08;八股&#xff1a;六步法&#xff0c;有 Sequential 和 class 两种&#xff09;。 文章目录一、搭建网络八股 sequential1.1、keras 介绍1.2、六步法搭建 keras …

Mac搭建appium+python+Android自动化环境

mac搭建appium+python+Android自动化环境 一、安装jdk二、安装Android-SDK三、配置 Android 环境四、安装Appium五、打开appium一、安装jdk 自己百度 二、安装Android-SDK 1)下载地址: http://www.android-studio.org/index.php/download 下载mac版本的dmg 2) 下载完成后…

HTTPS:让数据传输更安全

鉴于 HTTP 的明文传输使得传输过程毫无安全性可言&#xff0c;且制约了网上购物、在线转账等一系列场景应用&#xff0c;于是引入加密方案。 从 HTTP 协议栈层面来看&#xff0c;我们可以在 TCP 和 HTTP 之间插入一个安全层&#xff0c;所有经过安全层的数据都会被加密或者解密…

关于虚拟数字人你想知道的都在这里

2022年底&#xff0c;微软旗下的人工智能实验室Open AI发布的对话式大型语言模型ChatGPT聊天机器人一夜蹿红&#xff0c;5天用户量超百万&#xff0c;在各大中外媒体平台掀起了一阵热潮。也带火了人工智能相关产业&#xff0c;AI虚拟数字人就是其中之一&#xff0c;一个随着元宇…

损失函数与反向传播

一、损失函数计算实际输出和目标之间的差距为我们更新输出提供一定的依据&#xff08;反向传播&#xff09;1.nn.L1Lossimport torch from torch.nn import L1Loss inputs torch.tensor([1,2,3],dtypetorch.float) targets torch.tensor([1,2,5],dtypetorch.float) # reshape…

Docker之路(4.Docker命令大全、docker镜像命令、docker容器命令以及docker常用命令)

1.帮助命令 1.1 docker version(显示docker的版本信息) sudo docker version1.2 docker info(显示docker的系统信息&#xff0c;包括镜像和容器数量) sudo docker info1.3 --help (万能命令) sudo 命令 --help1。4 帮助文档的地址 https://docs.docker.com/engine/referenc…

纯手动搭建hadoop3.x集群记录001_搭建虚拟机_调通网络_配置静态IP_安装JDK---大数据之Hadoop3.x工作笔记0162

1.首先准备机器,172.19.126.115 172.19.126.116 172.19.126.117 我准备了3台 Windows机器 2.然后我打算在Windows机器上使用虚拟机,搭建3台Centos虚拟机来进行安装hadoop 3.这里我们的3台windows机器中的,3台linux虚拟机也使用了3个IP,分别是 172.19.126.120 172.19.126.1…

自然语言处理(NLP)之跳字(元)模型<skip-gram>与连续词袋模型<continuous bag of words>

自然语言处理(Natural Language Processing, NLP)是AI里的一个非常重要的领域&#xff0c;比如现在很火爆的ChatGPT&#xff0c;首先就需要很好的理解输入内容的意思才能够做出合理的回复。自然语言处理应用非常广泛&#xff0c;比如机器翻译、问题回答、文本语义对比、语音识别…