【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解

news2025/1/12 12:20:17

原题展示 📄

    本试题目的是制作一个商品管理系统,其主要功能为:购买商品、增加商品储量、调节商品价格、查询商品价格,并且能够保存改变后的商品数量与商品价格,总体上看跟第一场的试题差不多,下面就让我们一起去看看题目吧!😃😃😃
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    通过阅读上述原题,我们可以知道本试题涉及到的模块有串口LCD按键LEDEEPROMPWM六大部分,其中串口、按键、LCD、LED、PWM五个部分都是试题的常客,而EEPROM相比出场率就非常惨淡了,因此,本次题解需要关注的就是:如何完成EEPROM连续读取


题解 🔑

    在正式题解前,大家需要注意以下几点:

  • 由于LCD与LED有部分引脚是共用的,因此初始化完成LCD后最好手动关闭LED;
  • 使用CubeMX配置完成串口USART1后需要更改默认引脚为PA9PA10
  • EEPROM不能够连续读取,两次相邻的读取一定要有时间间隔;
  • EEPROM存储的数据不能是小数;

LED模块

    通过查询产品手册知,LED的引脚为PC8~PC15,外加锁存器74HC573需要用到的引脚PD2。(由于题目要求除LED1、LED2外的其他LED都处于熄灭状态,此处特意将所有的LED都初始化)

CubeMX配置:

代码样例

    由于G431的所有LED都跟锁存器74HC573连接,因此每次更改LED状态时都需要先打开锁存器,写入数据后再关闭锁存器。

/*****************************************************
* 函数功能:改变所有LED的状态
* 函数参数:
*			char LEDSTATE: 0-表示关闭 1-表示打开
* 函数返回值:无
******************************************************/
void changeAllLedByStateNumber(char LEDSTATE)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
					|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,(LEDSTATE==1?GPIO_PIN_RESET:GPIO_PIN_SET));
	//打开锁存器    准备写入数据
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	//关闭锁存器 锁存器的作用为 使得锁存器输出端的电平一直维持在一个固定的状态
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

/*****************************************************
* 函数功能:根据LED的位置打开或者是关闭LED
* 函数参数:
*			uint16_t LEDLOCATION:需要操作LED的位置
*			char LEDSTATE: 0-表示关闭 1-表示打开
* 函数返回值:无
******************************************************/
void changeLedStateByLocation(uint16_t LEDLOCATION,char LEDSTATE)
{
	HAL_GPIO_WritePin(GPIOC,LEDLOCATION,(LEDSTATE==1?GPIO_PIN_RESET:GPIO_PIN_SET));
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

    为了提高系统的实时性并且完成试题要求的LED1亮5秒及LED2以0.1s时间闪烁的要求,此处的LED工作计算时间特意借助了定时器7来完成(定时器7每中断一次代表时间0.1s):

/*************************************
* 函数功能:按键工作函数
* 函数参数:无
* 函数返回值:无
*************************************/
void LedDisplay(void)
{
	//关闭所有LED
	changeAllLedByStateNumber(0);
	//确认购买商品
	if(checkFlag)
	{
		uiTime7CountFlag[0] = 1;
	}
	//判断LED时长是否符合条件
	if(uiTime7CountFlag[0] &&  uiTime7Count[0]%50<50)
		changeLedStateByLocation(LED1,1);
	if(uiTime7Count[0]%55>51)
	{
		changeLedStateByLocation(LED1,0);
		uiTime7CountFlag[0] = 0;
		uiTime7Count[0] = 0;
	}
	
	//商品数量都为0
	if(!goods[0]->iGoodsCount && !goods[1]->iGoodsCount)
		uiTime7CountFlag[1] = 1;
	else
	{
		uiTime7CountFlag[1] = 0;
		uiTime7Count[1] = 0;
	}
	//判断时间是否间隔0.1秒 
	if(uiTime7Count[1]%2 == 1)
		rollbackLedByLocation(LED2);
}

LCD模块

    LCD模块官方会提供源码,内含初始化,大家会用即可。如下面是一段将LCD初始化成——文字颜色为白色、背景为蓝色的LCD屏:

/******************************************************************************
* 函数功能:LCD初始化
* 函数参数:无
* 函数返回值:无
*******************************************************************************/
void lcdInit(void)
{
	//HAL库的初始化
	LCD_Init();
	//设置LCD的背景色
	LCD_Clear(Blue);
	//设置LCD字体颜色
	LCD_SetTextColor(White);
	//设置LCD字体的背景色
	LCD_SetBackColor(Blue);
}

    系统的LCD显示界面的设计函数,displayMode为全局变量,每次按下B1其值都会加1:

/*************************************
* 函数功能:界面显示
* 函数参数:无
* 函数返回值:无
*************************************/
void display(void)
{
	char temp[20]  = {0};
	
	//购买界面显示
	if(displayMode == 0)
	{
		LCD_DisplayStringLine(Line1,(uint8_t*)"        SHOP ");
		sprintf(temp,"     X:%d       ",goods[0]->iGoodsBuyCount);
		LCD_DisplayStringLine(Line3,(uint8_t*)temp);
		sprintf(temp,"     Y:%d       ",goods[1]->iGoodsBuyCount);
		LCD_DisplayStringLine(Line4,(uint8_t*)temp);
	}
	//商品价格界面显示
	else if(displayMode == 1)	
	{
		LCD_DisplayStringLine(Line1,(uint8_t*)"        PRICE   ");
		sprintf(temp,"     X:%.1f    ",goods[0]->dGoodsPrice);
		LCD_DisplayStringLine(Line3,(uint8_t*)temp);
		sprintf(temp,"     Y:%.1f    ",goods[1]->dGoodsPrice);
		LCD_DisplayStringLine(Line4,(uint8_t*)temp);
	}
	//库存信息界面显示
	else if(displayMode == 2)
	{
		LCD_DisplayStringLine(Line1,(uint8_t*)"        REP   ");
		sprintf(temp,"     X:%d      ",goods[0]->iGoodsCount);
		LCD_DisplayStringLine(Line3,(uint8_t*)temp);
		sprintf(temp,"     Y:%d       ",goods[1]->iGoodsCount);
		LCD_DisplayStringLine(Line4,(uint8_t*)temp);
	}
}

按键模块

    通过查询产品手册知,开发板上的四个按键引脚为PB0~PB2、PA0

CubeMX配置

代码样例

    由于G431开发板上按键数量较少以及本次按键不涉及长短按、单击双击等复杂按键的设计,因此,我们直接使用含锁机制的if判断即可。

  • 第一步,判断按键是否按键以及锁是否处于打开状态,如果两者有一个不满足函数直接返回;否则,进入下一步;
  • 第二步,上锁,延时消抖;
  • 第三步,再次读取各个按键,判断具体是哪个按键按下;
  • 第四步,判断按键是否松开,如果松开,则开锁;否则函数直接返回。
/*********************************************
 * 函数功能:按键扫描 含按键消抖 无长按短按设计
 * 函数参数:无
 * 函数返回值:按键的位置
 *            返回值说明:B1-1 B2-2 B3-3 B4-4
*********************************************/
unsigned char scanKey(void)
{
	//按键锁
	static unsigned char keyLock = 1;
    //记录按键消抖时间
    // static uint16_t keyCount = 0;

	//按键按下
    if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET || HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == RESET
      || HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == RESET || HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET) 
      && keyLock == 1){
        //给按键上锁 避免多次触发按键
        keyLock = 0;
        
        //按键消抖 这里最好不要使用延时函数进行消抖 会影响系统的实时性
        // if(++keyCount % 10 < 5) return 0;
        // if(HAL_GetTick()%15 < 10) return 0;
        HAL_Delay(10);

        //按键B1
        if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET){
            return 1;
        }
        //按键B2
        if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == RESET){
            return 2;
        }
        //按键B3
        if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == RESET){
            return 3;
        }
        //按键B4
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET){
            return 4;
        }
    }
    //按键松开
    if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == SET && HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == SET
      && HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == SET && HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == SET) 
      && keyLock == 0){
        //开锁
        keyLock = 1;
    }
    return 0;
}

    按键按下后的题目要求的逻辑函数:

/*************************************
* 函数功能:按键工作函数
* 函数参数:无
* 函数返回值:无
*************************************/
void keyPro(void)
{
	//按键扫描
	keyValue = scanKey();
	switch(keyValue)
	{
		//按键B1
		case 1:
			//切换LCD显示界面
			if(++displayMode == 3) displayMode = 0;
			break;
		//按键B2
		case 2:
			//购买界面  购买数量加1
			if(displayMode == 0)
				if(++goods[0]->iGoodsBuyCount == goods[0]->iGoodsCount+1)
					goods[0]->iGoodsBuyCount = 0;
			//商品价格界面  单价加0.1
			if(displayMode == 1)
				goods[0]->dGoodsPrice += 0.1;	
			//库存界面  库存加1
			if(displayMode == 2)
				goods[0]->iGoodsCount++;
			break;
		//按键B3
		case 3:
			//购买界面  购买数量加1
			if(displayMode == 0)
				if(++goods[1]->iGoodsBuyCount == goods[1]->iGoodsCount+1)
					goods[1]->iGoodsBuyCount = 0;
			//商品价格界面  单价加0.1
			if(displayMode == 1)
				goods[1]->dGoodsPrice += 0.1;	
			//库存界面  库存加1
			if(displayMode == 2)
				goods[1]->iGoodsCount++;
			break;
		//按键B4
		case 4:
			if(displayMode == 0)
				checkFlag = 1;
			break;
		//其他
		default : break;
	}	
	keyValue = 0;
}

串口模块

    试题中要求串口具备接收与发送两个功能,接收采用中断接收的方式发送则需要发送时直接发送

CubeMX配置
    配置时一定一定记得改引脚!!!
在这里插入图片描述
代码样例

    HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)函数解析:

  • UART_HandleTypeDef *huart:串口通道;
  • uint8_t *pData:存放数据的buff;
  • uint16_t Size:一次接收数据的长度
        不过使用时还需要初始化,否则不能够进入中断接收数据;
/***使用HAL_UART_Receive_IT中断接收数据 每次接收完成数据后就会执行该函数***/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1){
		// 重新使能中断
		HAL_UART_Receive_IT(huart,(uint8_t *)&cRxBuff,sizeof(cRxBuff)); 
	}
}

    串口工作处理函数,这里主要包含串口数据接受收的处理以及串口数据发送的条件:

/*************************************
* 函数功能:串口数据处理函数
* 函数参数:无
* 函数返回值:无
*************************************/
void usartProcess(void)
{
	char temp[20] = {0};
	
	//确认购买后发送商品信息
	if(checkFlag)
	{
		sprintf(temp,"X:%d,Y:%d,Z:%.1f\r\n",goods[0]->iGoodsBuyCount,goods[1]->iGoodsBuyCount,
				(goods[0]->dGoodsPrice*goods[0]->iGoodsBuyCount+goods[1]->dGoodsPrice*goods[1]->iGoodsBuyCount));
		HAL_UART_Transmit(&huart1,(uint8_t*)temp,sizeof(temp),50);
	}
	
	//查询商品 发送目前的商品信息
	if(iRxFlag==1 && strcmp((char*)cRxBuff,(char*)"?") == 0)
	{
		sprintf(temp,"X:%.1f,Y:%.1f\r\n",goods[0]->dGoodsPrice,goods[1]->dGoodsPrice);
		HAL_UART_Transmit(&huart1,(uint8_t*)temp,sizeof(temp),50);
	}
	//清空串口接收到的数据以及打开串口锁
	memset(cRxBuff,'\0',sizeof(cRxBuff));
	iRxFlag = 0;	
}

PWM模块

CubeMX配置
在这里插入图片描述
修改PWM的占空比样例代码(可直接调用)

/*************************************
* 函数功能:PWM输出切换函数
* 函数参数:无
* 函数返回值:无
*************************************/
void pwmWorkState(void)
{	
	//输出占空比为30%  这里的判断条件是借用LED1的判断条件 因为他们的时长需求是一样的
	if(uiTime7CountFlag[0] &&  uiTime7Count[0]%50<50)
		__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,30);
	//输出占空比为5%
	if(uiTime7Count[0]%55>51)
		__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,5);
}

EEPROM模块

EEPROM初始化

    有两种方法,一种是使用CubeMx配置引脚,另一种是使用官方给的可直接使用的IIC初始化代码。

方法一:CubeMx配置

    使用CubeMx配置后,就可直接使用EEPROM的读取函数,不用在执行其他操作。

在这里插入图片描述

方法一:官方提供代码初始化

    官方提供的代码中含有基于HAL库写的IIC初始化函数,即EEPROM的初始化函数,直接使用其初始化就可,其函数名称为I2CInit()

在这里插入图片描述

EEPROM操作的时序

    由于官方提供的库函数是基于软件实现的,在不使用硬件llC外设的微处理器中,需要根据总线时序设计lIC接口的驱动程序,其包括:起始信号停止信号产生应答等待应答发送数据接收数据6个函数。

EEPROM读取函数

  • 时序图
    在这里插入图片描述
  • 读取时源码
/***************************************
* 函数功能:读取eeprom相应位置的值
* 函数参数:
*			unsigned char ucAddr:读取的地址
* 函数返回值:
*			ucRes:读取到的值
***************************************/
unsigned char readEepromByBit(unsigned char ucAddr)
{
	unsigned char ucRes = 0;
	
	//发送起始信号
	I2CStart();
	//发送设备地址
	I2CSendByte(0xa0);
	//等待应答
	I2CWaitAck();
	//发送读取地址
	I2CSendByte(ucAddr);
	//等待应答
	I2CWaitAck();
	//发送停止信号
	I2CStop();
	
	//发送起始信号
	I2CStart();
	//发送读取数据命令
	I2CSendByte(0xa1);
	//等待应答
	I2CWaitAck();
	//接收数据
	ucRes = I2CReceiveByte();
	//发送应答
	I2CSendNotAck();
	//发送停止信号
	I2CStop();
	
	return ucRes;
}

EEPROM写入函数

  • 时序图
    在这里插入图片描述
  • 写入时源码
/***************************************
* 函数功能:向eeprom对应地址写入数据
* 函数参数:
*			unsigned char ucAddr:写入的地址
*			unsigned char ucData:写入的数据
* 函数返回值:无
***************************************/
void writeEepromByBit(unsigned char ucAddr,unsigned char ucData)
{
	//发送起始信号
	I2CStart();
	//发送设备地址
	I2CSendByte(0xa0);
	//等待应答
	I2CWaitAck();
	
	//发送写入地址
	I2CSendByte(ucAddr);
	//发送应答
	I2CSendAck();
	//发送写入数据
	I2CSendByte(ucData);
	//等待应答
	I2CWaitAck();
	//发送停止信号
	I2CStop();
}

    由于题中要求E2PROM内部地址0-3要存储两个商品的数量及价格信息,这就标志着该试题题解一定存在连续存取。
    试题中还要求在设备第一次读取时使用代码中的初始化,后续启动使用EEPROM中存储值作为商品信息的初值,那么如何判断设备是否第一次启动就成了商品信息初始化的关键点。这里采用的方法是:使用EEPROM中的两个地址存储特定的值,每次启动时都读取这两个地址,一旦读取出的数值不是设定的特定值就判断是第一次启动设备,再将特定值写入;否则,就不是第一次启动,那么就使用EEPROM中的值作为初值

	//软件初始化商品信息以及EEPROM的值
	for(i=0;i<2;i++)
	{
		//初始化商品信息
		goods[i] = goodsInit(10,1.0,0);
		//EEPROM结构体初始化
		eepromMsg[i] = eepromInit(0,0);
	}
	
	//读取EEPROM特定位置查看该设备是否启动过
	ucEdata[0] = readEepromByBit(0xa4);
	HAL_Delay(10);
	ucEdata[1] = readEepromByBit(0xa5);
	
	//判断固定位置是否存储过信息  其表示的是该设备是否第一次烧入代码
	if(ucEdata[0]==55 && ucEdata[1]==66) 
	{
		//加载EEPROM中商品的数量、价格信息
		for(i=0;i<2;i++)
		{
			eepromMsg[i]->count = readEepromByBit(0xa0+ucEepromLocation[i]);
			goods[i]->iGoodsCount = eepromMsg[i]->count;
			HAL_Delay(10);//由于此处是初始化,使用HAL库提供的延时函数效果最佳,且不会影响系统的任何工作
			
			eepromMsg[i]->price = readEepromByBit(0xa1+ucEepromLocation[i])*1.0/10;
			goods[i]->dGoodsPrice = eepromMsg[i]->price;
			HAL_Delay(10);	
		}	
	}
	else
	{
		//向EEPROM写入数据表明该设备已经启动过
		for(i=0;i<2;i++)
		{
			writeEepromByBit(0xa4+i,55+11*i);
			HAL_Delay(10);
		}
	}

    由于EEPROM连续存取需要一定的时间间隔,那么意味着必须得使用延时/计时函数。HAL库提供了延时函数HAL_Delay(),但是我们一旦使用它,LED跟EEPROM写入条件同时满足时,就会在EEPROM写入后产生阻塞,就会导致LED工作时间不准确,因此,最好使用定时器来完成计时功能
    数组中uiTime7Count[2]的值记录定时器7中断次数,定时器7中断一次就意味着经过了0.1s时间。将uiTime7Count[2]的计数值分成5部分,前面0-3表示可以写入,第4部分时EEPROM就休息,这样可以避免第0、3部分时间都写入导致产生错误数据。

	//判断库存数量是否跟EEPROM存储是否相同 不同就写入
	for(i=0;i<2;i++)
	{
		//判断数值是否相同并且时间间隔是否合理
		if(goods[i]->iGoodsCount!=eepromMsg[i]->count && uiTime7Count[2]%5==(0+ucEepromLocation[i]))
		{
			writeEepromByBit(0xa0+ucEepromLocation[i],(unsigned char)goods[i]->iGoodsCount);
			eepromMsg[i]->count = goods[i]->iGoodsCount;
		}
		if(goods[i]->dGoodsPrice!=eepromMsg[i]->price && uiTime7Count[2]%5==(1+ucEepromLocation[i]))
		{
			writeEepromByBit(0xa1+ucEepromLocation[i],(unsigned char)(goods[i]->dGoodsPrice*10));
			eepromMsg[i]->price = goods[i]->dGoodsPrice;
		}
	}

小结 📝

    试题中比较难受的部分是如何判定设备是否是第一次启动以及EEPROM连续读取需要一定的时间间隔,再解决完这些问题,总的来说,该试题还是比较简单的,就剩一些常见的解题模式框架,直接🚀🚀🚀!!!

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

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

相关文章

Python Selenium 获取动态网页指定元素的超链接

Python Selenium 获取动态网页指定元素的超链接前言前提条件相关介绍实验环境获取动态网页指定元素的超链接目标网址代码实现前言 本文是个人使用Python Selenium 获取动态网页指定元素的超链接的电子笔记&#xff0c;由于水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评…

详解浮点数在内存中的存储

目录 前言 一、 32 位单精度浮点数在内存中的存储 1.1 - 符号位 sign 1.2 - 偏移后的指数位 biased exponent 1.3 - 尾数位 fraction&#xff08;mantissa&#xff09; 二、64 位双精度浮点数在内存中的存储 三、浮点数的比较 前言 计算机内部实际上只能存储和识别二进制…

IPV6相关

目录 一、IPV6地址组成与专业术语 1.基础分类 2.本地链路地址范围区域概念 3.本地环回地址 二、centos配置IPV6地址 1.终端命令配置IPV6地址和网关 2.文件中配置IPV6地址 三、IPV6连通测试 1.全局单播地址进行ping 一、IPV6地址组成与专业术语 1.基础分类 IPv6基础知…

对话开发者:Serverless 落地的困境与破局

作者 | 阿里云开发者社区、InfoQ 从 2012 年提出 Serverless 到今年 2022 年刚好十年。 过去十年&#xff0c;上云是确定性趋势&#xff0c;在这个阶段企业一开始的关注点在于如何实现平滑上云。随着越来越多的企业上云&#xff0c;甚至很多企业系统第一天就是在云上构建&…

7-2 出生年

以上是新浪微博中一奇葩贴&#xff1a;“我出生于1988年&#xff0c;直到25岁才遇到4个数字都不相同的年份。”也就是说&#xff0c;直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求&#xff0c;自动填充“我出生于y年&#xff0c;直到x岁才遇到n个数字都不相同的…

【数据结构与算法——C语言版】5. 排序算法(1)——冒泡排序

前言 上篇文章【数据结构与算法——C语言版】4. 排序算法&#xff08;1&#xff09;——选择排序我们介绍了排序算法中的选择排序&#xff0c;其时间复杂度是O(n2)&#xff0c;本篇文章我们将介绍另一种同样时间复杂度是O(n2)的排序算法——冒牌排序&#xff0c;这两种算法思路…

面向对象编程看这一篇文章就够了

第一章 面向对象和面向过程 面向对象(OOP[Object Oriented Programming])和面向过程(POP[procedure oriented programming])都是一种软件编程设计思想 1. 面向过程强调功能行为 2. 面向对象是将功能封装进对象,强调具备了功能的对象 3. 面向对象强调运用人类在日常的思维逻辑中…

Java 程序员都该懂的 HashMap

HashMap 一直是非常常用的数据结构&#xff0c;也是面试中十分常问到的集合类型&#xff0c;今天就来说说 HashMap。 但是为什么要专门说明是 Java8 的 HashMap 呢&#xff1f;我们都知道&#xff0c;Java8 有很多大的变化和改动&#xff0c;如函数式编程等&#xff0c;而 Hash…

SpringBoot 请求参数处理详解

目录 请求参数处理 0、请求映射 1、rest使用与原理 1、普通参数与基本注解 1.1、注解&#xff1a; 1.2、Servlet API&#xff1a; 1.3、复杂参数&#xff1a; 1.4、自定义对象参数&#xff1a; 2、POJO封装过程 3、参数处理原理 1、HandlerAdapter 2、执行目标方法…

maplab2.0安装

项目链接: GitHub - ethz-asl/maplab: An open visual-inertial mapping framework. 安装流程很简单.按照github流程安装就行,建议使用脚本自动安装, 安装指南: https://maplab.asl.ethz.ch/docs/master/pages/installation/A_Installation-Ubuntu.html 值得注意的点包括: 1…

【阶段二】Python数据分析数据可视化工具使用03篇:词云图与相关性热力图

本篇的思维导图: 词云图 词云图(word cloud chart)是通过使每个字的大小与其出现频率成正比,显示不同单词在给定文本中的出现频率,然后将所有的字词排在一起,形成云状图案,也可以任何格式排列:水平线、垂直列或其他形状,也可用于显示获分配元数据的单词。在词云…

2022 OpenMLDB 硕果累累,颁奖台上荣耀连连

岁末年初&#xff0c; 既是回望过去和规划未来的日子&#xff0c; 也是总结成长与收获成果的时间。 2022 年即将结束之际&#xff0c; OpenMLDB 在颁奖台上惊喜连连&#xff0c; 获得了 IT168 和 中国开源云联盟 的认可。 技术改变世界&#xff0c;创新引领未来。业界知名 IT…

Redis缓存穿透、缓存击穿、缓存雪崩详解

缓存处理流程接收到查询数据请求时&#xff0c;优先从缓存中查询&#xff0c;若缓存中有数据&#xff0c;则直接返回&#xff0c;若缓存中查不到则从DB中查询&#xff0c;将查询的结果更新到缓存中&#xff0c;并返回查询结果&#xff0c;若DB中查不到&#xff0c;则返回空数据…

PSR规范

PSR规范 PSR 不是PHP官方标准&#xff0c;而是从如Zend、Symfony2等知名PHP项目中提炼出来的一系列标准&#xff0c;目前有越来越多的社区项目加入并遵循该标准。 PSR-0 自动加载 X已废弃 PSR-1 基本代码规范 PSR-2 代码样式 PSR-3 日志接口 PSR-4 如何指定文件路径从而自动加载…

怎么搭建自己的网站赚钱,个人网站怎么操作

大家好&#xff0c;我是蝶衣王的小编接触过互联网的应该很多都想过能不能搭建自己的网站赚钱&#xff0c;无论是用来带货&#xff0c;引流&#xff0c;还是做广告都会是一笔不错的收入&#xff0c;而且网站做好之后打理起来简单&#xff0c;后期工作量也是比较小的&#xff0c;…

【论文简述】Vis-MVSNet: Visibility-Aware Multi-view Stereo Network(IJCV 2022)

一、论文简述 1. 第一作者&#xff1a;Jingyang Zhang 2. 发表年份&#xff1a;2022 3. 发表期刊&#xff1a;IJCV、BMVC 4. 关键词&#xff1a;MVS、可见性、MVSNet 5. 探索动机&#xff1a;MVS的可见性 One critical factor in MVS is the pixel-wise visibility: whet…

Clion配置导致中文乱码问题 char长度限制导致中文乱码问题

&#x1f370; 个人主页:__Aurora__ &#x1f35e;如果文章有什么需要改进的地方还请各位大佬指正。 &#x1f349;如果我的文章对你有帮助➡️ 关注&#x1f64f;&#x1f3fb; 点赞&#x1f44d; 收藏⭐️ 问题1&#xff1a;中文乱码问题&#xff08;配置原因&#xff09; #…

【Linux】复制进程、了解逻辑地址以及写实拷贝

目录 fork()方法原型 父子进程 父子进程的pid 物理地址和逻辑地址 写实拷贝 fork()方法原型 pid_t fork(void); pid_t是int类型代表进程的pid号 Linux内核2.4.0定义&#xff1a; typedef int __kernel_pid_t; typedef __kernel_pid_t pid_t; 每一个进程的pid都是唯一…

MySQL多实例管理(mysqld_multi)

定义&#xff1a;就是在一台mysql机器上开启多个不同的服务端口&#xff08;如&#xff1a;3306,3307&#xff09;&#xff0c;运行多个MySQL服务进程&#xff0c;通过不同的socket监听不同的服务端口来提供各自的服务 1.MySQL多实例介绍 1.1.什么是MySQL多实例 MySQL多实例就…

移动智能终端安全技术要求及测试评价方法

声明 本文是学习移动智能终端安全技术要求及测试评价方法. 下载地址 http://github5.com/view/627而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 移动智能终端测试评价方法 硬件安全 硬件安全的测试方法、预期结果和结果判定如下&#xff1a; a&am…