任务函数分析

news2024/11/17 22:32:08

一、页面存储栈 PageStack

1、头文件

#include "ui.h"

#define MAX_DEPTH 6

typedef long long int StackData_t;

typedef struct 
{
    StackData_t Data[MAX_DEPTH];
    uint8_t Top_Point;

}user_Stack_T;

uint8_t user_Stack_Push(user_Stack_T* stack, StackData_t datain);
uint8_t user_Stack_Pop(user_Stack_T* stack);
uint8_t user_Stack_isEmpty(user_Stack_T* stack);
void user_Stack_Clear(user_Stack_T* stack);

 首先用typedef定义了一种数据类型, long long int 

我在想32位单片机最大的数据类型长度不就是int型 的 4个字节吗,好奇怪,只有在PC机上 long long int才是64位吧,也就是8个字节

去串口验证了一下,确实是8个字节

 这个数组长度是6 。一看到这个我就想起来了任务的堆栈空间,寄存器和栈之间保存上下文的时候。

后面定义了一个1个字节的变量 看名字是栈顶指针的意思(其实是表示栈中元素个数的意思吧)。

后面声明了4个函数,在C文件里再进行解析

2、c文件

#include "PageStack.h"

uint8_t user_Stack_Push(user_Stack_T* stack, StackData_t datain)
{
  if(stack->Top_Point == MAX_DEPTH - 1)
	{return -1;}
	
	stack->Data[stack->Top_Point++] = datain;
	return 0;
}

uint8_t user_Stack_Pop(user_Stack_T* stack)
{
  if(stack->Top_Point == 0)
	{return -1;}
	
	stack->Data[--stack->Top_Point] = NULL;
	return 0;
}

uint8_t user_Stack_isEmpty(user_Stack_T* stack)
{
	if(stack->Top_Point == 0)
	{return 1;} 

	return 0;
}

void user_Stack_Clear(user_Stack_T* stack)
{
	while(!user_Stack_isEmpty(stack))
	{
		user_Stack_Pop(stack);
	}
}

 2.1 user_Stack_Push 入栈

uint8_t user_Stack_Push(user_Stack_T* stack, StackData_t datain)
{
  if(stack->Top_Point == MAX_DEPTH - 1)
	{return -1;}
	
	stack->Data[stack->Top_Point++] = datain;
	return 0;
}

这个名字一听就懂,压栈 。栈这个数据结构遵循先进后出的顺序。(ARM)栈底指针指向地址最高位,栈是向下增长的。栈顶指针就指向第一个无元素的位置。可能栈的类型也不全一样,我记得还有栈指针指向-1的,空栈的时候。

这里的栈明显是低地址增长的。有些许不太一样,而且是数组构成的栈

如果栈顶指针指向最高地址也就是 5 这时候栈内已经填满了。这个数组是个a[6]类型,地址最高到5,逻辑应该是这样的。栈顶指针永远指向最后一个入栈的元素的下一个位置,开始指向0的话是不满足的。我猜测是这样的

这里确实对我来说有点绕,但是栈内最多存到5又是没错的,因为6已经超出数组的范围了。它是现存再自增的,存到第5个元素后,Top_Point已经为5了,假如从零开始初始化。第六个元素存不进去啊?第一个if就推出了。只有当初始化为-1,且++在左边我认为才正常。

索引先自增为0 压入第一个元素

最后一次入栈,索引等于4,先自增索引为5.压入最后一个元素。下次判断也是栈满的情况。

我还是问问GPT吧,文心一言的判断与我相同,豆包和kimi的判断一致。

让文心一言给我修改过后是这样

if(stack->Top_Point == MAX_DEPTH)
{
    return -1; // 栈已满
}
stack->Data[stack->Top_Point++] = datain;
return 0; // 成功推入

2.2 user_Stack_Pop 出栈

uint8_t user_Stack_Pop(user_Stack_T* stack)
{
  if(stack->Top_Point == 0)
	{return -1;}
	
	stack->Data[--stack->Top_Point] = NULL;
	return 0;
}

出栈的话,跟入栈是相反的过程,如果栈索引到 最低地址(也就是数组首地址)退出。意思也就是初始化的时候,栈索引使指向数组首地址的。

那上面的解答了,最大栈存的元素个数 是深度-1  然后这里弹出栈的逻辑好像有点奇怪。先自减再赋值,这不是等于栈索引得指向第6个才能生效,这样自减后索引到数组的第五个,赋值NULL意思就是出栈吧,一般出栈有人来取,这里可能没人取吧。

我们就假设入栈判断是 最大深度。刚好就是6 这样二者才能联系起来。不然意义就是少存一个(也不能算错),申请M个元素大小的栈空间,却只利用了M-1个,土豪 可以这么做。

2.3 user_Stack_isEmpty 栈是否为空

uint8_t user_Stack_isEmpty(user_Stack_T* stack)
{
	if(stack->Top_Point == 0)
	{return 1;} 

	return 0;
}

这里就是判断索引位置来判断,很简单。

2.4 user_Stack_Clear 清空栈

void user_Stack_Clear(user_Stack_T* stack)
{
	while(!user_Stack_isEmpty(stack))
	{
		user_Stack_Pop(stack);
	}
}

也就是逐个出栈的步骤,将整个数组的元素清空

二、user_KeyTask 按键任务

/* Private includes -----------------------------------------------------------*/
//includes
#include "user_TasksInit.h"
#include "user_StopEnterTask.h"
#include "user_ScrRenewTask.h"
#include "ui_HomePage.h"
#include "main.h"
#include "key.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/


/**
  * @brief  Key press check task
  * @param  argument: Not used
  * @retval None
  */
void KeyTask(void *argument)
{
	uint8_t keystr=0;
	uint8_t Stopstr=0;
	uint8_t IdleBreakstr=0;
	while(1)
	{
		switch(KeyScan(0))
		{
			case 1:
				keystr = 1;
				osMessageQueuePut(Key_MessageQueue, &keystr, 0, 1);
				osMessageQueuePut(IdleBreak_MessageQueue, &IdleBreakstr, 0, 1);
				break;
				
			case 2:
				break;
		}
		osDelay(1);
	}
}

从按键任务引用的头文件可以 了解到 涉及到停止、进入某些特定任务,屏幕刷新任务, ui的主界面相关。

按键任务 首先定义了三个 uint8_t 类型的局部变量 keystrStopstr 和 IdleBreakstr,初始值都设为 0keystr 可能用于后续构建要发送到消息队列中的按键相关消息内容,Stopstr 和 IdleBreakstr 目前从代码看暂未在其他地方使用

任务死循环内 执行按键扫描,不支持连按 

如果按下就把keystr这个键值赋值为1 ,freertos的队列是地址传递节省了值传递的复制的开销

分别向两个消息队列 发送消息 优先级为 0 普通消息 超时时间1ms,基本不会阻塞

扫描期间也加入1ms阻塞延时。

三、user_MessageSendTask 消息发送任务

/* Private includes -----------------------------------------------------------*/
//includes
#include "string.h"
#include "stdio.h"

#include "main.h"
#include "stm32f4xx_it.h"
#include "rtc.h"

#include "user_TasksInit.h"
#include "user_MessageSendTask.h"

#include "ui.h"
#include "ui_EnvPage.h"
#include "ui_HRPage.h"
#include "ui_SPO2Page.h"
#include "ui_HomePage.h"
#include "ui_DateTimeSetPage.h"


/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
struct 
{
	RTC_DateTypeDef nowdate;
	RTC_TimeTypeDef nowtime; 
	int8_t humi;
	int8_t temp;
	uint8_t HR;
	uint8_t SPO2;
	uint16_t stepNum;
}BLEMessage;

struct 
{
	RTC_DateTypeDef nowdate;
	RTC_TimeTypeDef nowtime; 
}TimeSetMessage;

/* Private function prototypes -----------------------------------------------*/

void StrCMD_Get(uint8_t * str,uint8_t * cmd)
{
	uint8_t i=0;
  while(str[i]!='=')
  {
      cmd[i] = str[i];
      i++;
  }
}

//set time//OV+ST=20230629125555
uint8_t TimeFormat_Get(uint8_t * str)
{
	TimeSetMessage.nowdate.Year = (str[8]-'0')*10+str[9]-'0';
	TimeSetMessage.nowdate.Month = (str[10]-'0')*10+str[11]-'0';
	TimeSetMessage.nowdate.Date = (str[12]-'0')*10+str[13]-'0';
	TimeSetMessage.nowtime.Hours = (str[14]-'0')*10+str[15]-'0';
	TimeSetMessage.nowtime.Minutes = (str[16]-'0')*10+str[17]-'0';
	TimeSetMessage.nowtime.Seconds = (str[18]-'0')*10+str[19]-'0';
	if(TimeSetMessage.nowdate.Year>0 && TimeSetMessage.nowdate.Year<99 
		&& TimeSetMessage.nowdate.Month>0 && TimeSetMessage.nowdate.Month<=12
		&& TimeSetMessage.nowdate.Date>0 && TimeSetMessage.nowdate.Date<=31
		&& TimeSetMessage.nowtime.Hours>=0 && TimeSetMessage.nowtime.Hours<=23
		&& TimeSetMessage.nowtime.Minutes>=0 && TimeSetMessage.nowtime.Minutes<=59
		&& TimeSetMessage.nowtime.Seconds>=0 && TimeSetMessage.nowtime.Seconds<=59)
	{
		RTC_SetDate(TimeSetMessage.nowdate.Year, TimeSetMessage.nowdate.Month,TimeSetMessage.nowdate.Date);
		RTC_SetTime(TimeSetMessage.nowtime.Hours,TimeSetMessage.nowtime.Minutes,TimeSetMessage.nowtime.Seconds);
		printf("TIMESETOK\r\n");
	}
		
}

/**
  * @brief  send the message via BLE, use uart
  * @param  argument: Not used
  * @retval None
  */
void MessageSendTask(void *argument)
{
	while(1)
	{
		if(HardInt_uart_flag)
		{
			HardInt_uart_flag = 0;
			uint8_t IdleBreakstr=0;
			osMessageQueuePut(IdleBreak_MessageQueue,&IdleBreakstr,NULL,1);
			printf("RecStr:%s\r\n",HardInt_receive_str);
			if(!strcmp(HardInt_receive_str,"OV"))
			{
				printf("OK\r\n");
			}
			else if(!strcmp(HardInt_receive_str,"OV+VERSION"))
			{
				printf("VERSION=V2.3\r\n");
			}
			else if(!strcmp(HardInt_receive_str,"OV+SEND"))
			{
				HAL_RTC_GetTime(&hrtc,&(BLEMessage.nowtime),RTC_FORMAT_BIN);
				HAL_RTC_GetDate(&hrtc,&BLEMessage.nowdate,RTC_FORMAT_BIN);
				BLEMessage.humi = ui_EnvHumiValue;
				BLEMessage.temp = ui_EnvTempValue;
				BLEMessage.HR = ui_HRValue;
				BLEMessage.SPO2 = ui_SPO2Value;
				BLEMessage.stepNum = ui_StepNumValue;

				printf("data:%2d-%02d\r\n",BLEMessage.nowdate.Month,BLEMessage.nowdate.Date);
				printf("time:%02d:%02d:%02d\r\n",BLEMessage.nowtime.Hours,BLEMessage.nowtime.Minutes,BLEMessage.nowtime.Seconds);
				printf("humidity:%d%%\r\n",BLEMessage.humi);
				printf("temperature:%d\r\n",BLEMessage.temp);
				printf("Heart Rate:%d%%\r\n",BLEMessage.HR);
				printf("SPO2:%d%%\r\n",BLEMessage.SPO2);
				printf("Step today:%d\r\n",BLEMessage.stepNum);
			}
			//set time//OV+ST=20230629125555
			else if(strlen(HardInt_receive_str)==20)
			{
				uint8_t cmd[10];
				memset(cmd,0,sizeof(cmd));
				StrCMD_Get(HardInt_receive_str,cmd);
				if(user_APPSy_EN && !strcmp(cmd,"OV+ST"))
				{
					TimeFormat_Get(HardInt_receive_str);
				}
			}
			memset(HardInt_receive_str,0,sizeof(HardInt_receive_str));
		}
		osDelay(1000);
	}
}


string.h 和 stdio.h 是 C 语言标准库头文件,分别提供了字符串处理函数(如 strcpystrcmpmemset 等)和输入输出函数(如 printf)相关的声明,在这里用于字符串操作以及向控制台(可能是通过调试接口)输出信息 

main.h 通常包含主程序模块相关的一些通用定义,例如全局变量声明、主函数中使用到的宏等。

stm32f4xx_it.h 一般是 STM32F4 系列单片机的中断相关的头文件,可能包含了中断服务函数的声明以及一些与中断处理相关的宏定义等内容,用于处理单片机的各种中断事件。

rtc.h 应该是与实时时钟(RTC)模块相关的头文件,里面会有实时时钟操作函数(如 RTC_SetDateRTC_SetTime 等函数的声明),用于获取和设置系统时间日期。

user_TasksInit.h 包含了对freertos的引用 还有一个屏幕刷新深度。

user_MessageSendTask.h 里面没有东西

struct 
{
	RTC_DateTypeDef nowdate;
	RTC_TimeTypeDef nowtime; 
	int8_t humi;
	int8_t temp;
	uint8_t HR;
	uint8_t SPO2;
	uint16_t stepNum;
}BLEMessage;

struct 
{
	RTC_DateTypeDef nowdate;
	RTC_TimeTypeDef nowtime; 
}TimeSetMessage;

定义了两个匿名结构体类型的变量 BLEMessage 和 TimeSetMessage

BLEMessage 结构体包含了实时时钟的日期和时间信息(nowdate 和 nowtime),以及环境湿度(humi)、温度(temp)、心率(HR)、血氧饱和度(SPO2)和步数(stepNum)等信息。这个结构体可能用于封装要通过蓝牙(BLE,从变量名推测)发送给外部设备的各种数据,方便统一管理和传输。

TimeSetMessage 结构体只包含了实时时钟的日期和时间信息,主要用于在设置系统时间的操作中临时存储解析出来的日期和时间数据,以便后续调用 RTC_SetDate 和 RTC_SetTime 函数来更新系统时间。

取出字符串的一部分

void StrCMD_Get(uint8_t * str,uint8_t * cmd)
{
	uint8_t i=0;
  while(str[i]!='=')
  {
      cmd[i] = str[i];
      i++;
  }
}

估计是将一个字符串 等于号左边的取到cmd里

时间格式获取

//set time//OV+ST=20230629125555
uint8_t TimeFormat_Get(uint8_t * str)
{
	TimeSetMessage.nowdate.Year = (str[8]-'0')*10+str[9]-'0';
	TimeSetMessage.nowdate.Month = (str[10]-'0')*10+str[11]-'0';
	TimeSetMessage.nowdate.Date = (str[12]-'0')*10+str[13]-'0';
	TimeSetMessage.nowtime.Hours = (str[14]-'0')*10+str[15]-'0';
	TimeSetMessage.nowtime.Minutes = (str[16]-'0')*10+str[17]-'0';
	TimeSetMessage.nowtime.Seconds = (str[18]-'0')*10+str[19]-'0';
	if(TimeSetMessage.nowdate.Year>0 && TimeSetMessage.nowdate.Year<99 
		&& TimeSetMessage.nowdate.Month>0 && TimeSetMessage.nowdate.Month<=12
		&& TimeSetMessage.nowdate.Date>0 && TimeSetMessage.nowdate.Date<=31
		&& TimeSetMessage.nowtime.Hours>=0 && TimeSetMessage.nowtime.Hours<=23
		&& TimeSetMessage.nowtime.Minutes>=0 && TimeSetMessage.nowtime.Minutes<=59
		&& TimeSetMessage.nowtime.Seconds>=0 && TimeSetMessage.nowtime.Seconds<=59)
	{
		RTC_SetDate(TimeSetMessage.nowdate.Year, TimeSetMessage.nowdate.Month,TimeSetMessage.nowdate.Date);
		RTC_SetTime(TimeSetMessage.nowtime.Hours,TimeSetMessage.nowtime.Minutes,TimeSetMessage.nowtime.Seconds);
		printf("TIMESETOK\r\n");
	}
		
}

就是把字符串解析成时间并进行设置时间消息,如果解析的数据无误,消息设置完还要对RTC的时间寄存器更新。这些消息应该是时间任务在用 。

消息发送任务 

void MessageSendTask(void *argument)
{
    while (1)
    {
        if (HardInt_uart_flag)
        {
            HardInt_uart_flag = 0;
            uint8_t IdleBreakstr = 0;
            osMessageQueuePut(IdleBreak_MessageQueue, &IdleBreakstr, NULL, 1);
            printf("RecStr:%s\r\n", HardInt_receive_str);
            if (!strcmp(HardInt_receive_str, "OV"))
            {
                printf("OK\r\n");
            }
            else if (!strcmp(HardInt_receive_str, "OV+VERSION"))
            {
                printf("VERSION=V2.3\r\n");
            }
            else if (!strcmp(HardInt_receive_str, "OV+SEND"))
            {
                HAL_RTC_GetTime(&hrtc, &(BLEMessage.nowtime), RTC_FORMAT_BIN);
                HAL_RTC_GetDate(&hrtc, &BLEMessage.nowdate, RTC_FORMAT_BIN);
                BLEMessage.humi = ui_EnvHumiValue;
                BLEMessage.temp = ui_EnvTempValue;
                BLEMessage.HR = ui_HRValue;
                BLEMessage.SPO2 = ui_SPO2Value;
                BLEMessage.stepNum = ui_StepNumValue;

                printf("data:%2d-%02d\r\n", BLEMessage.nowdate.Month, BLEMessage.nowdate.Date);
                printf("time:%02d:%02d:%02d\r\n", BLEMessage.nowtime.Hours, BLEMessage.nowtime.Minutes, BLEMessage.nowtime.Seconds);
                printf("humidity:%d%%\r\n", BLEMessage.humi);
                printf("temperature:%d\r\n", BLEMessage.temp);
                printf("Heart Rate:%d%%\r\n", BLEMessage.HR);
                printf("SPO2:%d%%\r\n", BLEMessage.SPO2);
                printf("Step today:%d\r\n", BLEMessage.stepNum);
            }
            //set time//OV+ST=20230629125555
            else if (strlen(HardInt_receive_str) == 20)
            {
                uint8_t cmd[10];
                memset(cmd, 0, sizeof(cmd));
                StrCMD_Get(HardInt_receive_str, cmd);
                if (user_APPSy_EN &&!strcmp(cmd, "OV+ST"))
                {
                    TimeFormat_Get(HardInt_receive_str);
                }
            }
            memset(HardInt_receive_str, 0, sizeof(HardInt_receive_str));
        }
        osDelay(1000);
    }
}

通过判断 HardInt_uart_flag 的值来确定是否接收到了新的 UART 数据。当这个标志为 1 时,表示有新数据到达,进入处理分支

产生一次串口数据中断进入这个任务的if分支

没有中断这个任务就一直阻塞。

HardInt_uart_flag = 0;
uint8_t IdleBreakstr=0;
osMessageQueuePut(IdleBreak_MessageQueue,&IdleBreakstr,NULL,1);
printf("RecStr:%s\r\n",HardInt_receive_str);

首先将 HardInt_uart_flag 清零,准备下一次数据接收判断,然后定义一个 uint8_t 类型的变量 IdleBreakstr 并初始化为 0,接着通过 osMessageQueuePut 函数将 IdleBreakstr 的地址放入 IdleBreak_MessageQueue 消息队列中,具体这个消息队列的作用和后续接收处理它的任务需要参考项目的其他部分代码,但从命名推测可能和任务空闲状态打破等相关操作有关

但是空闲任务一般优先级不是最低吗

if(!strcmp(HardInt_receive_str,"OV"))
			{
				printf("OK\r\n");
			}
			else if(!strcmp(HardInt_receive_str,"OV+VERSION"))
			{
				printf("VERSION=V2.3\r\n");
			}
			else if(!strcmp(HardInt_receive_str,"OV+SEND"))
			{
				HAL_RTC_GetTime(&hrtc,&(BLEMessage.nowtime),RTC_FORMAT_BIN);
				HAL_RTC_GetDate(&hrtc,&BLEMessage.nowdate,RTC_FORMAT_BIN);
				BLEMessage.humi = ui_EnvHumiValue;
				BLEMessage.temp = ui_EnvTempValue;
				BLEMessage.HR = ui_HRValue;
				BLEMessage.SPO2 = ui_SPO2Value;
				BLEMessage.stepNum = ui_StepNumValue;

				printf("data:%2d-%02d\r\n",BLEMessage.nowdate.Month,BLEMessage.nowdate.Date);
				printf("time:%02d:%02d:%02d\r\n",BLEMessage.nowtime.Hours,BLEMessage.nowtime.Minutes,BLEMessage.nowtime.Seconds);
				printf("humidity:%d%%\r\n",BLEMessage.humi);
				printf("temperature:%d\r\n",BLEMessage.temp);
				printf("Heart Rate:%d%%\r\n",BLEMessage.HR);
				printf("SPO2:%d%%\r\n",BLEMessage.SPO2);
				printf("Step today:%d\r\n",BLEMessage.stepNum);
			}
			//set time//OV+ST=20230629125555
			else if(strlen(HardInt_receive_str)==20)
			{
				uint8_t cmd[10];
				memset(cmd,0,sizeof(cmd));
				StrCMD_Get(HardInt_receive_str,cmd);
				if(user_APPSy_EN && !strcmp(cmd,"OV+ST"))
				{
					TimeFormat_Get(HardInt_receive_str);
				}
			}

命令解析及对应操作逻辑(多个 if - else if 分支)

OV" 命令处理:当接收到的字符串是 "OV" 时,简单地输出 "OK"

"OV+VERSION" 命令处理:如果接收到的字符串是 "OV+VERSION",则输出软件版本信息 "VERSION=V2.3",说明该命令用于查询设备的软件版本情况

"OV+SEND" 命令处理:当接收到 "OV+SEND" 命令时,会通过 HAL_RTC_GetTime 和 HAL_RTC_GetDate 函数(这两个函数应该是 STM32 相关的 HAL 库函数,用于获取实时时钟的时间和日期信息)分别获取当前的时间和日期,并存储到 BLEMessage 结构体的相应成员中。然后将 ui_EnvHumiValueui_EnvTempValueui_HRValueui_SPO2Valueui_StepNumValue 这些来自用户界面不同页面显示的传感器数据(从变量名推测)赋值给 BLEMessage 结构体中的湿度、温度、心率、血氧饱和度和步数成员。最后通过一系列 printf 函数将 BLEMessage 结构体中的各项数据输出显示,可能用于向外部设备(比如通过蓝牙发送时先在控制台显示确认一下内容)展示当前系统的状态信息

类似于蓝牙模块的指令吧?

长度为 20 的字符串命令处理(设置时间相关):当接收到的字符串长度为 20 时(从注释 //set time//OV+ST=20230629125555 可知,这可能是用于设置时间的特定格式字符串),首先定义一个长度为 10 的 uint8_t 类型数组 cmd,并通过 memset 函数将其内容初始化为全 0。然后调用 StrCMD_Get 函数从接收到的完整字符串中提取命令部分(存储到 cmd 数组中),接着判断 user_APPSy_EN(这个变量应该是一个用于控制是否允许进行相关系统操作的标志,比如是否允许设置时间功能开启)是否为真,并且提取出来的命令字符串是否为 "OV+ST",如果都满足条件,则调用 TimeFormat_Get 函数来解析并设置系统时间,这个函数内部会对解析出来的时间日期数据进行合法性检查,并通过 RTC_SetDate 和 RTC_SetTime 函数更新实时时钟的时间和日期信息

uint8_t user_APPSy_EN=0;这里设置的是不支持串口进行设置时间。

最后把缓冲区全部清零。

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

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

相关文章

Springboot 微信小程序定位后将坐标转换为百度地图坐标,在百度地图做逆地址解析

问题解析以及解决思路 业务:微信小程序定位后,将坐标转换为百度地图坐标,在百度地图做逆地址解析 问题:微信小程序的定位是拿的腾讯地图的经纬度,但是我们app端这边使用的百度地图,如果直接使用腾讯地图的经纬度再使用腾讯地图的逆地址解析需要腾讯和百度商业授权,为了减少授权…

vue注册全局组件,其他地方可以直接方便的调用

文章目录 问题注册全局组件完结 问题 本来我们想使用某个组件&#xff0c;需要在各个地方引入对应的参数&#xff0c;并配置好components内容&#xff0c;才可以使用 但是随着用的越来越多&#xff0c;这种方法变得重复且易出错 注册全局组件 修改main.js文件&#xff0c;放…

Kubernetes 10 问,测测你对 k8s 的理解程度

Kubernetes 10 问 假设集群有 2 个 node 节点&#xff0c;其中一个有 pod&#xff0c;另一个则没有&#xff0c;那么新的 pod 会被调度到哪个节点上&#xff1f; 应用程序通过容器的形式运行&#xff0c;如果 OOM&#xff08;Out-of-Memory&#xff09;了&#xff0c;是容器重…

Java项目实战II基于微信小程序的课堂助手(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在数字化教…

高光谱深度学习调研

综述 高光谱深度学习只有小综述&#xff0c;没有大综述。小综述里面场景分类、目标检测的综述比较多。 Wang C, Liu B, Liu L, et al. A review of deep learning used in the hyperspectral image analysis for agriculture[J]. Artificial Intelligence Review, 2021, 54(7)…

抖音热门素材去哪找?优质抖音视频素材网站推荐!

是不是和我一样&#xff0c;刷抖音刷到停不下来&#xff1f;越来越多的朋友希望在抖音上创作出爆款视频&#xff0c;但苦于没有好素材。今天就来推荐几个超级实用的抖音视频素材网站&#xff0c;让你的视频内容立刻变得高大上&#xff01;这篇满是干货&#xff0c;直接上重点&a…

人工智能之数学基础:数学在人工智能领域中的地位

人工智能&#xff08;AI&#xff09;是一种新兴的技术&#xff0c;它的目标是构建能够像人类一样思考、学习、推理和解决问题的智能机器。AI已经成为了许多行业的重要组成部分&#xff0c;包括医疗、金融、交通、教育等。而数学则是AI领域中不可或缺的基础学科。本文将阐述数学…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十三)图优化SLAM的本质

一、直白解释slam与图优化的结合 我从b站上学习理解的这个概念。 视频的大概位置是1个小时以后&#xff0c;在第75min到80min之间。图优化SLAM是怎么一回事。 slam本身是有运动方程的&#xff0c;也就是运动状态递推方程&#xff0c;也就是预测过程。通过t1时刻&#xff0c…

STM32单片机设计防儿童人员误锁/滞留车内警报系统

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 近年来在车辆逐渐普及的情况下&#xff0c;由于家长的疏忽&#xff0c;将…

stm32——通用定时器时钟知识点

&#xff08;该图来自小破站 铁头山羊老师的stm32标准库教学&#xff09;

GPIO相关的寄存器(重要)

目录 一、GPIO相关寄存器概述 二、整体介绍 三、详细介绍 1、端口配置低寄存器&#xff08;GPIOx_CRL&#xff09;&#xff08;xA...E&#xff09; 2、端口配置高寄存器&#xff08;GPIOx_CRH&#xff09;&#xff08;xA...E&#xff09; 3、端口输入数据寄存器&#xff…

CSS基础也要进行模电实验

盒子阴影 圆角边框已经介绍过哩&#xff0c;现在先介绍一下盒子阴影的效果如何实现 CSS3中新增了盒子阴影&#xff0c;可以使用box-shadow属性为盒子添加阴影 这是固定的语法&#xff1a; text-shadow: h-shadow v-shadow blur color; 它有这些可选的值&#xff1a; 哦。 …

i春秋-登陆(sql盲注爆字段,.git缓存利用)

练习平台地址 竞赛中心 题目描述 先登陆再说 题目内容 就是一个登录框 测试登录 用户名&#xff1a;admin or 11# 密码&#xff1a;随便输 返回密码错误 用户名&#xff1a;随便输 密码&#xff1a;随便输 返回用户名不存在 这里就可以确定时一个bool盲注了 这里提供一个lik…

探索KubeVirt:如何利用InfiniBand提升虚拟机性能

在高性能计算&#xff08;HPC&#xff09;中&#xff0c;网络性能对于集群效率起着至关重要的作用。为了支持大规模并行计算&#xff0c;HPC集群通常依赖高带宽、低延迟的网络&#xff0c;而InfiniBand&#xff08;IB&#xff09;正是其中的首选技术。它能够提供超过100Gbps的带…

基于树莓派的边缘端 AI 目标检测、目标跟踪、姿态估计 视频分析推理 加速方案:Hailo with ultralytics YOLOv8 YOLOv11

文件大纲 加速原理硬件安装软件安装基本设置系统升级docker 方案Demo 测试目标检测姿态估计视频分析参考文献前序树莓派文章hailo加速原理 Hailo 发布的 Raspberry Pi AI kit 加速原理,有几篇文章介绍的不错 https://ubuntu.com/blog/hackers-guide-to-the-raspberry-pi-ai-ki…

小白进!QMK 键盘新手入门指南

经常玩键盘的伙伴应该都知道&#xff0c;现在的键盘市场可谓是百花齐放&#xff0c;已经不是之前的单一功能产品化时代。我们可以看到很多诸如&#xff1a;机械轴键盘、磁轴键盘、光轴键盘、电感轴键盘&#xff0c;以及可能会上市的光磁轴键盘&#xff0c;更有支持屏幕的、带旋…

《操作系统 - 清华大学》3 -3:连续内存分配:内存碎片与分区的动态分配

文章目录 0. 概述1. 内存碎片问题2. 动态分配3. 首次适配算法4. 最优适配算法5. 最差适配算法 0. 概述 内存分配是操作系统管理过程中很重要的环节&#xff0c;首先需要考虑的是一块连续区域分配的过程&#xff0c;这个过程中会有很多问题&#xff0c;首先比较关注的一个问题是…

vue内置指令和自定义指令

常见的指令&#xff1a; v-bind : 单向绑定解析表达式, 可简写为 :xxx v-model : 双向数据绑定 v-for : 遍历数组/对象/字符串 v-on : 绑定事件监听, 可简…

蓝桥杯备赛(持续更新)

16届蓝桥杯算法类知识图谱.pdf 1. 格式打印 %03d&#xff1a;如果是两位数&#xff0c;将会在前面添上一位0 %.2f&#xff1a;会保留两位小数 如果是long&#xff0c;必须在数字后面加上L。 2. 进制转化 2.1. 十进制转任意进制&#xff1a; 十进制转任意进制时&#xff…

vue 项目使用 nginx 部署

前言 记录下使用element-admin-template 改造项目踩过的坑及打包部署过程 一、根据权限增加动态路由不生效 原因是Sidebar中路由取的 this.$router.options.routes,需要在计算路由 permission.js 增加如下代码 // generate accessible routes map based on roles const acce…