【蓝桥杯嵌入式】按键控制LED与LCD(必考三件套)

【蓝桥杯嵌入式】按键控制LED与LCD(必考三件套)

  • 前言
  • LED相关功能的实现
    • LED基础功能函数(点亮、全熄灭、翻转)
    • LED的闪烁与定时点亮熄灭
    • 流水灯的实现
  • 按键的扫描及长短按、双击的实现
    • 按键的短按
    • 按键业务逻辑程序进程
    • 按键的长短按
    • 长短按与双击
  • LCD移植与显示
    • LCD的移植与进程函数
    • LCD与LED冲突的问题解决
    • LCD的高亮显示

前言

按键、LED以及LCD是蓝桥杯每年必考的三个知识点,也作为工程建立的基础与突破口,因此熟练掌握该三个板块内容及其重要:

  1. 本人习惯自建user.c函数,将各种程序放在该文件内,方便程序编写

  2. LCD的实现不需要配置相关IO口,只需要对工程进行移植即可

    LCD_Init();
    LCD_SetBackColor(Black);	//设置背景颜色
    LCD_SetTextColor(White);	//设置字体颜色
    LCD_Clear(Black);			//清屏
    LCD_DisplayStringLine(Line4, (unsigned char *)"    Hello,world.   ");	//LCD显示函数
    
  3. 按键分为短按,长按和双击,长按考频率不高,双击至今还未考过

  4. LCD与LED共用引脚,需要对LCD相关函数进行优化

    u32 temp = GPIOC->ODR;
    
    GPIOC->ODR = temp;
    
  5. 业务逻辑在三个进程函数内实现,进程函数在while(1)中运行

  6. 亘古不变的变量

    uchar ui = 0;		//lcd显示的界面号
    char text[20];		//lcd的显存buf
    struct keys key[4] = {0,0,0};	//按键结构体变量					
    

注: 本文内容主要实现按键、LCD与LED的底层工程函数与配合使用功能的程序设计,相关cubemx工程配置请参考:【蓝桥杯嵌入式】Cubemx新建工程引脚配置与点亮LED

LED相关功能的实现

LED基础功能函数(点亮、全熄灭、翻转)

点亮一个LED灯

void led_show(uchar led, bool mode)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);					//打开锁存器
	if(mode)
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led-1),GPIO_PIN_RESET);	//点亮一个LED灯
	else
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led-1),GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);					//关闭锁存器
}

关闭所有LED灯(用于初始化熄灭全部LED,在main.c的while(1)之前调用)

void led_offAll(void)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

翻转LED

void led_toggle(uchar led)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8<<(led-1));
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

LED的闪烁与定时点亮熄灭

  led的闪烁通过定时器在特定的时间内改变led的亮灭来实现闪烁效果,其中led的闪烁采用系统滴答定时器实现,本人习惯将stm32g4xx_it.c中的滴答定时器中断服务函数SysTick_Handler剪切至user.c中用于控制led的闪烁。
全局变量

bool shake_flag = 0;	//闪烁标志位
bool led_mode = 1;		//led状态
bool sec5_flag = 0;		//5s计时器

led进程函数

void led_process(void)
{
	//led闪烁
	if(shake_flag)
		led_show(1,led_mode);
	else
		led_show(1,0);
	
	//5s计时启动,LED8亮
	if(sec5_flag == 1)
		led_show(8,1);
	else
		led_show(8,0);
}

led闪烁的定时器中断底层设计
通过系统滴答定时器计时,滴答定时器的定时时间为1ms

uint shake_tick = 0;
u32 sec5_tick = 0;
void SysTick_Handler(void)
{
	//控制led闪烁
	if(shake_flag)
	{
		shake_tick++;
		//led闪烁频率为1s
		if(shake_tick >= 500)
		{
			shake_tick = 0;
			led_mode = !led_mode;
		}
	}
	//5s计时器
	if(sec5_flag)
	{
		sec5_tick++;
		if(sec5_tick >= 5000)
		{
			sec5_flag = 0;
			sec5_tick = 0;
		}
	}
	
  HAL_IncTick();
}

流水灯的实现

/**********************全局变量*******************/
//流水灯标志位
bool flue_flag = 0;	
bool flue_cnt = 0;


u32 led_tick = 0;
void led_process(void)
{
	//控制进入led的时间 用于控制流水灯速度
	if(uwTick - led_tick < 150)
		return;
	led_tick = uwTick;
	
	if(flue_flag)
	{
		static uchar i = 1;		
		if(i > 4)				//流水灯的范围
		{
			i = 1;
			led_show(4,0);
		}
		led_show(i,1);			//点亮流水灯	
		led_show(i-1,0);		//熄灭之前的灯
		
		i++;					//流水
		flue_cnt = 1;			//用于只关闭流水范围内的灯一次
	}
	else if(flue_cnt && flue_cnt == 1)	//流水结束 关闭流水范围内的灯 关一次
	{
		for(uchar  i = 1; i <= 4; i++)
			led_show(i,0);
		flue_cnt = 0;
	}
}

按键的扫描及长短按、双击的实现

  开发板的按键四颗按键分别接在PB0~PB2以及PA0引脚,当按下按键时,IO口被拉低,通过定时器扫描按键IO口电平状态来检测按键是否被按下,按键原理图如下图所示:

定时器中断回调函数
记得在main.c函数的初始化中打开定时器中断!!!

HAL_TIM_Base_Start_IT(&htim6);

重写回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

直接去tim.c底下的stm32g4xx_hal_tim.h里面找即可,直接拖到文件末尾,倒数第三个板块的第一个函数。

按键的短按

按键结构体定义:

struct keys{
	uchar judge_sta;	//状态集	
	bool key_sta;		//IO口电平
	bool single_flag;	//短按标志位
};

按键变量的定义

struct keys key[4] = {0,0,0};

其中短按的程序设计逻辑为:

  1. IO口电平为0,按下
  2. 软件消抖(判断是否真实按下)
  3. 松手检测,短按标志置1

短按的定时器扫描实现:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM6)		//对应的定时器中断	 10ms
	{
		//读取IO口电平
		key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		for(uchar i = 0; i < 4; i++)
		{
			switch(key[i].judge_sta)
			{
				case 0:
					if(key[i].key_sta == 0)			//按键按下
						key[i].judge_sta = 1;
					break;
				
				case 1:								//消抖 10ms
					if(key[i].key_sta == 0)
						key[i].judge_sta = 2;
					else
						key[i].judge_sta = 0;
					break;
					
				case 2:
					if(key[i].key_sta == 1)			//松手 短按标志置1
					{
						key[i].single_flag = 1;
						key[i].judge_sta = 0;
					}
					break;
			}
		}
	}
}

按键业务逻辑程序进程

void key_process(void)
{
	if(key[0].single_flag == 1)		//按键1按下
	{
		//按键1短按业务逻辑程序
		led_toggle(1);
		ui = (ui + 1) % 3;	//按键1通常为切换界面
		LCD_Clear(Black);	//☆切换界面记得需要清屏
		
		key[0].single_flag = 0;		//清空按下标志位
	}
	
	if(key[1].single_flag == 1)		//按键2按下
	{
		//按键2短按业务逻辑程序
		led_toggle(2);
		
		key[1].single_flag = 0;
	}
	
	
	if(key[2].single_flag == 1)		//按键3按下
	{
		//按键3短按业务逻辑程序
		led_toggle(3);
		
		key[2].single_flag = 0;
	}
	
	
	if(key[3].single_flag == 1)		//按键4按下
	{
		//按键4短按业务逻辑程序
		led_toggle(4);
		
		key[3].single_flag = 0;
	}
	
	/*******以下是有长短按时的业务逻辑,其他按键同理******/
	if(key[3].long_flag == 1)		//按键4长按
	{
		//按键4短按业务逻辑程序
		led_show(5,1);
		
		key[3].long_flag = 0;
	}
		
	if(key[3].double_flag == 1)		//按键4双击
	{
		//按键4短按业务逻辑程序
		led_show(5,0);
		
		key[3].double_flag = 0;
	}
}

按键的长短按

按键结构体的定义

struct keys{
	uchar judge_sta;	//状态集	
	bool key_sta;		//IO口电平
	bool single_flag;	//短按按下标志位
	uint key_time;		//按键按下时间
	bool long_flag;		//长按标志位
};

按键变量的定义

struct keys key[4] = {0,0,0,0,0};

长按的程序设计逻辑为:

  1. IO口电平为0,按下,启动计时
  2. 软件消抖(判断是否真实按下)
  3. 计时,若按下时间超过0.8s,长按标志置1
  4. 松手检测,若按下时间小于0.8s,短按标志置1

按键的长短按定时器扫描实现

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{	
	if(htim->Instance == TIM6)			//对应的定时器中断	 10ms
	{
		//读取IO口电平
		key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		for(uchar i = 0; i < 4; i++)
		{
			switch(key[i].judge_sta)
			{
				case 0:
					if(key[i].key_sta == 0)			//按键按下 时间置0
					{
						key[i].judge_sta = 1;
						key[i].key_time = 0;
					}
					break;
					
				case 1:								//消抖 10ms
					if(key[i].key_sta == 0)
						key[i].judge_sta = 2;
					else
						key[i].judge_sta = 0;
					break;
					
				case 2:
					if(key[i].key_sta == 1)			//松手
					{
						if(key[i].key_time < 80)	//按下时间小于800ms 短按	
							key[i].single_flag = 1;
						key[i].judge_sta = 0;
					}
					else
					{
						key[i].key_time++;
						if(key[i].key_time >= 80)	//按下时间一旦大于800ms 长按	
							key[i].long_flag = 1;
					}
					break;
			}
		}
	}
}

长短按与双击

按键结构体的定义

struct keys{
	uchar judge_sta;	//状态集
	bool key_sta;		//IO口电平
	uint key_time1;		//第一次按下时间
	uint key_time2;		//松手后的时间
	bool single_flag;	//短按标志
	bool long_flag;		//长按标志
	bool double_flag;	//双击标志
};

按键变量的定义

struct keys key[4] = {0,0,0,0,0,0,0};

双击的程序设计逻辑为:

  1. IO口电平为0,按下,启动第一次按下计时
  2. 软件消抖(判断是否真实按下)
  3. 计时按下时间
  4. 松手,开始计时松手时间,若再次按下,则进入双击
  5. 松手超过300ms,判断为长短按,结束
  6. 进入双击,消抖
  7. 检测松手,双击标志置1
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{	
	if(htim->Instance == TIM6)			//对应的定时器中断	 10ms
	{
		//读取IO口电平
		key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		for(uchar i = 0; i < 4; i++)
		{
			switch(key[i].judge_sta)
			{
				case 0:
					if(key[i].key_sta == 0)			//按键按下 时间置0
					{
						key[i].judge_sta = 1;
						key[i].key_time1 = 0;
						key[i].key_time2 = 0;
					}
					break;
					
				case 1:								//消抖 10ms
					if(key[i].key_sta == 0)
						key[i].judge_sta = 2;
					else
						key[i].judge_sta = 0;
					break;
					
				case 2:
					if(key[i].key_sta == 1)			//松手
						key[i].judge_sta = 3;
					else
					{
						key[i].key_time1++;
						if(key[i].key_time1 >= 80)
							key[i].long_flag = 1;
					}
					break;
					
				case 3:
					if(key[i].key_sta == 1)
					{
						key[i].key_time2++;
						if(key[i].key_time2 >= 30)	//长短按
						{
							if(key[i].key_time1 < 80)
								key[i].single_flag = 1;
							key[i].judge_sta = 0;	
						}
					}
					else
						key[i].judge_sta = 4;		//双击了
					break;
				
				case 4:
					if(key[i].key_sta == 0)
						key[i].judge_sta = 5;		//消抖
					else
					{
						if(key[i].key_time1 >= 80)
								key[i].long_flag = 1;
						else
								key[i].single_flag = 1;	
							key[i].judge_sta = 0;
					}
					break;
				
				case 5:
					if(key[i].key_sta == 1)		//双击松手
					{
						key[i].double_flag = 1;
						key[i].judge_sta = 0;
					}
					break;
			}
		}
	}
}

LCD移植与显示

LCD的移植与进程函数

  LCD的相关引脚配置无需在cubemx中进行配置,只需要将官方提供的lcd.c复制到src文件夹,将lcd.h,fonts.h复制到ins文件夹中即可,并将lcd.c文件添加至工程中,复制例程中main.c的相关配置即可
初始化lcd

LCD_Init();

lcd相关配置

LCD_SetBackColor(Black);	//设置背景颜色
LCD_SetTextColor(White);	//设置字体颜色
LCD_Clear(Black);			//清屏

lcd进程函数

void lcd_process(void)
{
	if(ui == 0)					//第一个界面显示的内容
	{
		sprintf(text,"     Title1 ");
		LCD_DisplayStringLine(Line1, (unsigned char *)text);	//LCD显示函数
		/******************其他显示的内如下****************/
		
	}
	else if(ui == 1)		//第二个界面显示的内容
	{
		sprintf(text,"     Title2 ");
		LCD_DisplayStringLine(Line1, (unsigned char *)text);	//LCD显示函数
		/******************其他显示的内如下****************/
		
	}
	else if(ui == 2)		//第三个界面显示的内容
	{
		sprintf(text,"     Title3 ");
		LCD_DisplayStringLine(Line1, (unsigned char *)text);	//LCD显示函数
		/******************其他显示的内如下****************/
		
	}
}

LCD与LED冲突的问题解决

  对于蓝桥杯的开发板,几乎每题都会遇到LED与LCD显示冲突的情况,这是因为LCD与LED共用了PC8 ~ PC15的引脚,这使得LCD更新显示,PC的引脚电平就无法确定了,使得LCD显示与LED会冲突。

解决办法: 操作LCD之前保存GPIOC相关寄存器的值,对LCD操作结束后,重新恢复原值,对LCD的高亮显示

void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
void LCD_WriteRAM_Prepare(void);
void LCD_WriteRAM(u16 RGB_Code);

这三个函数进行处理,即,首行都加上u32 temp = GPIOC->ODR;,尾行都加上GPIO->ODR = temp;即可

如下所示,其他两个函数进行同理操作

void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{
	u32 temp = GPIOC->ODR;
	
    GPIOB->BRR  |= GPIO_PIN_9;
    GPIOB->BRR  |= GPIO_PIN_8;
    GPIOB->BSRR |= GPIO_PIN_5;

    GPIOC->ODR = LCD_Reg;
    GPIOB->BRR  |= GPIO_PIN_5;
    __nop();
    __nop();
    __nop();
    GPIOB->BSRR |= GPIO_PIN_5;
    GPIOB->BSRR |= GPIO_PIN_8;

    GPIOC->ODR = LCD_RegValue;
    GPIOB->BRR  |= GPIO_PIN_5;
    __nop();
    __nop();
    __nop();
    GPIOB->BSRR |= GPIO_PIN_5;
    GPIOB->BSRR |= GPIO_PIN_8;
		
	GPIOC->ODR = temp;
}

LCD的高亮显示

  LCD的高亮显示即设置LCD的背景颜色,若直接设置LCD的背景颜色则是对整个界面设置,因此需要再LCD_DisplayStringLine的内部设置颜色,从而确定高亮显示的位置,改写LCD_DisplayStringLine函数为LCD_DisplayStringLineHight代表高亮显示的函数,其中添加一个参数表示高亮显示的起点,高亮显示的终点或长度可自行决定设置,这里以第九届赛题为例:起始位置为参数,每次高亮长度为2个位置

高亮函数的实现

void LCD_DisplayStringLineHight(u8 Line, u8 *ptr,uint8_t start)
{
	u32 i = 0;
	u16 refcolumn = 319;//319;
	LCD_SetBackColor(Black);	//其他位置保持背景颜色为黑色 
	while ((*ptr != 0) && (i < 20))	 //	20
	{
		if(i >= start && i < (start + 2))
			LCD_SetBackColor(Green);	//特定位置设置背景颜色为绿色 
		else
			LCD_SetBackColor(Black);	//其他位置保持背景颜色为黑色 
			
		LCD_DisplayChar(Line, refcolumn, *ptr);
		refcolumn -= 16;
		ptr++;
		i++;
	}
	LCD_SetBackColor(Black);	//其他位置保持背景颜色为黑色 
}

LCD进程函数中调用高亮函数,实现特定位置的高亮显示

void lcd_process(void)
{
	if(ui == 0)					//第一个界面显示的内容
	{
		sprintf(text,"     Title1 ");
		LCD_DisplayStringLine(Line1, (unsigned char *)text);	//LCD显示函数
		/******************其他显示的内如下****************/
		sprintf(text,"     %02d:%02d:%02d  ",12,2,2);
		switch(choice)
		{
			case 0:	LCD_DisplayStringLine(Line3,(unsigned char *)text);break;
			case 1:	LCD_DisplayStringLineHight(Line3,(unsigned char *)text,5);break;
			case 2:	LCD_DisplayStringLineHight(Line3,(unsigned char *)text,8);break;
			case 3:	LCD_DisplayStringLineHight(Line3,(unsigned char *)text,11);break;
			default:break;
		}
	}
}

实际效果:

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

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

相关文章

1995-2021年各省分品种能源产量和消费量数据

1995-2021年各省分品种能源产量和消费量数据 1、时间&#xff1a;1995-2021年 2、来源&#xff1a;能源统计年鉴、各省年鉴 3、指标&#xff1a;能源消费总量、煤炭消费量、焦炭消费量、原油消费量、汽油消费量、煤油消费量、柴油消费量、燃料油消费量、天然气消费量、电力消…

让智能体像孩子一样观察别人学习动作,跨视角技能学习数据集EgoExoLearn来了

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 在探索人工智能边界时&#xff0c;我们时常惊叹于人类孩童的学习能力 —— 可以轻易地将他人…

Unity学习笔记 - 第一个Hello World都算不上的项目

一、Unity安装 这里不细说安装了&#xff0c;首先需要Visual Studio&#xff0c;然后要安装Unity Hub&#xff0c;Unity Hub就像一个管理平台&#xff0c;安装完它之后&#xff0c;可以在它的界面上选择安装各个版本的编辑器。 开始您的创意项目并下载 Unity Hub | Unity通过 …

【Qt 学习笔记】Qt 中出现乱码的解释及讨论

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt 中出现乱码的解释及讨论 文章编号&#xff1a;Qt 学习笔记 / 06 文…

Nginx配置之localhost和反向代理

文章目录 第一步、查看安装位置和配置文件第二步、web服务器设置第三步、localhost 指令第四步、设置反向代理 清明假期&#xff0c;在家练习Nginx配置&#xff0c;在前期【 linux环境下安装配置nginx代理服务器】已经完成nginx环境搭建&#xff0c;本期主要实践web服务器&…

副业选择攻略:如何找到最适合自己的那一个?

大家好&#xff0c;我是木薯。今天有个新人伙伴来咨询客服&#xff1a;新手适不适合在水牛社上做副业&#xff1f;什么样的副业适合自己&#xff1f; 这种问题其实对我们来说已经见得太多太多了&#xff0c;归其原因是因为自己对副业没有一个清晰的自我认知&#xff0c;从而感觉…

阿里千问大模型 Qwen1.5 开源 32B 模型,将开源进行到底!!!

阿里开源的千问系列模型&#xff0c;一直受到业界好评&#xff0c;之前版本有0.5B、1.8B、7B、14B、72B&#xff0c;但一直缺少的30B级别开源模型&#xff0c;这也一直是一个遗憾。 怎么说呢&#xff1f;72B模型太大&#xff0c;很多人用不起来&#xff0c;无论是微调&#xf…

基于JAVA+SSM+微信小程序+MySql+前后端分离的图书捐赠管理系统设计与实现

一、项目背景介绍&#xff1a; 在当今社会&#xff0c;图书捐赠是一种普遍而有益的行为&#xff0c;旨在促进阅读、教育和知识传播。图书捐赠可以帮助改善教育资源不足的地区、学校和社区的阅读环境&#xff0c;提供更多的学习机会和知识获取途径。随着互联网和移动技术的发展&…

pytorch交叉熵

目录 1. Entropy2. 交叉熵3. 二分类4. 为什么分类问题使用交叉熵5. 代码示例 1. Entropy Entropy中文是熵的意思&#xff0c;它代表一种不确定性&#xff0c;不确定性越高惊喜度也就越高。 如上图&#xff0c;假设熵代表中奖概率&#xff0c;当熵为2 的中奖概率为1/4没什么惊…

sharding‐jdbc之分库分表(mysql主从同步的数据库安装和使用)

水平分表 创建基础工程.. 引入sharding‐jdbc的maven依赖包 注意需要数据库连接池等依赖 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1&l…

1.0-spring入门

文章目录 前言一、版本要求二、第一个spring程序1.引入pom2.代码部分2.1 spring bean2.2 springContext.xml2.3 测试2.4 执行结果 总结 前言 最近想要系统的学习下spring相关的框架,于是乎,来到了B站(真是个好地方),spring会专门开一个专栏出来,记录学习心得,与大家共勉。 Spri…

51-37 由浅入深理解 Stable Diffusion 3

2024年3月5日&#xff0c;Stability AI公开Stable Diffusion 3论文&#xff0c;Scaling Rectified Flow Transformers for High-Resolution Image Synthesis。公司像往常一样承诺后续将开源代码&#xff0c;开源之光&#xff01;&#xff01;&#xff01; 在LDW潜在扩散模型论文…

缓存击穿以及解决方案

1.定义 缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 问题描述&#xff1a;假设线程1在查询缓存之后&#xff0c;本来应该去查询数据库&#xff0c;然后把…

8、滑动窗口-无重复字符的最长子串

解析&#xff1a; 遍历 判断map是否包含当前字符&#xff0c;如果包含&#xff1a; 获取重复的index下标在哪里获取len长度重新设置L指针,其中L指针不回退&#xff0c;也就是如果这个重复值在L前面那就忽略&#xff0c;如果是在后面那就设置为index1。 代码如下&#xff1a; …

Java初始——IDEA-web的启动

Tomcat 文件夹作用 bin 启动 关闭的脚本文件 conf 配置 lib 依赖的jar包 logs 日志 temp 临时文件 webapps 存放的网站 Maven 1.在javaweb中&#xff0c;需要使用大量的jar包&#xff0c;手动导入 2.Maven 架构管理工具 核心&#xff1a;约定大于配置 必须按照规则 web idea-we…

Day16_IDEAJavaWeb项目下在WEB-INF添加jar包导致Tomcat无法启动的问题解决记录

0 起因 自己用的是Tomcat 9.0.69&#xff0c;老师用的是Tomcat 9.0.87。本以为都是9.0.x&#xff0c;差别不会很大&#xff0c;但是老师演示的时候他没导入mysql包查询数据库的servlet就不能运行&#xff0c;而我的却可以&#xff0c;于是问了GPT&#xff0c;得到以下答复。 …

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 限幅和滤波&#xff08;Clipping and Filtering&#xff09; 原理简介 限幅和滤波是一种基础且直观的方法&#xff0c;用于降低OFDM信号的PAPR。在限幅阶段&#xff0c;信号的幅度在达到设定阈值时会被削减&#xff0c;…

开发项目接单报价快速计算,报价量化程序

定制化开发&#xff0c;如何计算项目预算&#xff0c;是程序开发者头疼的一个问题。 项目费用谈得过低&#xff0c;就天天加班累死赚不到钱&#xff1b;谈得过高&#xff0c;会导致顾客流失&#xff0c;信誉受损。 项目费用量化可见是多么重要。 下面是一段量化的程序&#…

item_search-按关键字搜索淘宝商品:如何通过获取以下关键字、搜索类型、排序方式参数提升用户体验、优化营销策略、提高转化率

在淘宝购物的过程中&#xff0c;搜索功能无疑是用户与商品之间的重要桥梁。通过输入关键字&#xff0c;用户可以迅速找到所需的商品&#xff0c;而搜索结果的准确性和相关性则直接关系到用户的购物体验和满意度。因此&#xff0c;如何通过优化关键字、搜索类型和排序方式参数&a…

鸿蒙内核源码分析 (内存管理篇) | 虚拟内存全景图是怎样的

初始化整个内存 OsSysMemInitOsMainmain从 main() 跟踪可看内存部分初始化是在 OsSysMemInit() 中完成的。 UINT32 OsSysMemInit(VOID) {STATUS_T ret;OsKSpaceInit();//内核空间初始化ret OsKHeapInit(OS_KHEAP_BLOCK_SIZE);// 内核动态内存初始化 512K if (ret ! LOS_OK…