当前位置: 首页 > news >正文

STM32CUBUMX配置FLASH(W25Q128)--保姆级教程

————————————————————————————————————
⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。
⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动,包括ADC、UART、RS485、EEPROM(IIC)、FLASH(SPI)等等。
⏩本篇文章对STM32CUBEMX配置RS485做一个详细的使用教程。
⏩感谢你的阅读,不对的地方欢迎指正。
————————————————————————————————————

FLASH

  • W25Q128简介
  • 实验环境
  • MX配置
  • 驱动代码
  • 测试结果

W25Q128简介

W25Q128是华邦公司推出的一款SPI接口的NOR Flash芯片,其存储空间为128Mbit,相当于16M字节。W25Q128V芯片是串行闪存,可以通过标准/两线/四线SPI控制。
W25Q128JV阵列被组织成65536个可编程页面,每个页面256字节。一次最多可编程256个字节。页面可以按16组(4KB扇区擦除)、128组(32KB块擦除)、256组(64KB块擦除或整个芯片(芯片擦除)擦除。W25Q128JV分别具有4096个可擦除扇区和256个可擦除块。小4KB扇区允许在需要数据和参数存储的应用中具有更大的灵活性。
在这里插入图片描述
在这里插入图片描述
具体可以看这个:通过数据手册带你全面解析闪存芯片W25Q128

实验环境

  • STM32H723ZGT6开发板
  • USB转串口
  • W25Q128

硬件连接:
在这里插入图片描述

MX配置

板子、时钟、调试之类的配置就不说了,具体可以看看这篇:
STM32CUBEMX配置ADC(多通道轮询)(STM32H7)–保姆级教程
下面是SPI的具体配置
在这里插入图片描述
CS引脚配置
在这里插入图片描述
在这里插入图片描述

驱动代码

w25qxx.h

#ifndef W25Q128_W25QXX_H_
#define W25Q128_W25QXX_H_#include "stm32H7xx_hal.h" //HAL库文件声明//FLASH_CS 片选引脚定义
#define W25Q128_CS_GPIO_Port GPIOB
#define W25Q128_CS_Pin GPIO_PIN_12//25系列FLASH芯片厂商与容量代号(厂商代号EF)
#define W25Q80    0XEF13
#define W25Q16    0XEF14
#define W25Q32    0XEF15
#define W25Q64    0XEF16
#define W25Q128   0XEF17
#define W25Q256 0XEF18
#define EX_FLASH_ADD 0x000000 //W25Q128的地址是24位宽
extern uint16_t W25QXX_TYPE;//定义W25QXX芯片型号
extern SPI_HandleTypeDef hspi2;
//
//指令表
#define W25X_WriteEnable             0x06
#define W25X_WriteDisable            0x04
#define W25X_ReadStatusReg1      0x05
#define W25X_ReadStatusReg2      0x35
#define W25X_ReadStatusReg3      0x15
#define W25X_WriteStatusReg1         0x01
#define W25X_WriteStatusReg2         0x31
#define W25X_WriteStatusReg3     0x11
#define W25X_ReadData             0x03
#define W25X_FastReadData         0x0B
#define W25X_FastReadDual         0x3B
#define W25X_PageProgram          0x02
#define W25X_BlockErase              0xD8
#define W25X_SectorErase          0x20
#define W25X_ChipErase            0xC7
#define W25X_PowerDown            0xB9
#define W25X_ReleasePowerDown    0xAB
#define W25X_DeviceID             0xAB
#define W25X_ManufactDeviceID    0x90
#define W25X_JedecDeviceID           0x9F
#define W25X_Enable4ByteAddr         0xB7
#define W25X_Exit4ByteAddr        0xE9
uint8_t SPI2_ReadWriteByte(uint8_t  TxData);//SPI2总线底层读写
void W25QXX_CS(uint8_t a);//W25QXX片选引脚控制
uint8_t W25QXX_Init(void);//初始化W25QXX函数
uint16_t  W25QXX_ReadID(void);//读取FLASH ID
uint8_t W25QXX_ReadSR(uint8_t regno);//读取状态寄存器
void W25QXX_4ByteAddr_Enable(void);//使能4字节地址模式
void W25QXX_Write_SR(uint8_t regno,uint8_t  sr);//写状态寄存器
void W25QXX_Write_Enable(void);//写使能
void W25QXX_Write_Disable(void);//写保护
void W25QXX_Write_NoCheck(uint8_t*  pBuffer,uint32_t WriteAddr,uint16_t  NumByteToWrite);//无检验写SPI FLASH
void W25QXX_Read(uint8_t* pBuffer,uint32_t  ReadAddr,uint16_t NumByteToRead);//读取flash
void W25QXX_Write(uint8_t* pBuffer,uint32_t  WriteAddr,uint16_t NumByteToWrite);//写入flash
void W25QXX_Erase_Chip(void);//整片擦除
void W25QXX_Erase_Sector(uint32_t  Dst_Addr);//扇区擦除
void W25QXX_Wait_Busy(void);//等待空闲
void W25QXX_PowerDown(void);//进入掉电模式
void W25QXX_WAKEUP(void);//唤醒
void W25QXX_Write_Page(uint8_t*  pBuffer,uint32_t WriteAddr,uint16_t  NumByteToWrite);
void delay_us(uint32_t us); //C文件中的函数声明#endif /* W25Q128_W25QXX_H_ */

w25qxx.c

#include "w25qxx.h"
#include "main.h"
uint16_t W25QXX_TYPE=W25Q128;//默认是W25Q128
//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q128
//容量为16M字节,共有128个Block,4096个Sector
//SPI2总线读写一个字节
//参数是写入的字节,返回值是读出的字节
uint8_t SPI2_ReadWriteByte(uint8_t TxData)
{uint8_t Rxdata;//定义一个变量RxdataHAL_SPI_TransmitReceive(&hspi2,&TxData,&Rxdata,1,1000);//调用固件库函数收发数据return Rxdata;//返回收到的数据
}
void W25QXX_CS(uint8_t a)//软件控制函数(0为低电平,其他值为高电平)
{if(a==0)HAL_GPIO_WritePin(W25Q128_CS_GPIO_Port, W25Q128_CS_Pin, GPIO_PIN_RESET);else  HAL_GPIO_WritePin(W25Q128_CS_GPIO_Port,  W25Q128_CS_Pin, GPIO_PIN_SET);
}
//初始化SPI FLASH的IO口
uint8_t W25QXX_Init(void)
{uint8_t temp;//定义一个变量tempW25QXX_CS(1);//0片选开启,1片选关闭W25QXX_TYPE = W25QXX_ReadID();//读取FLASH  ID.if(W25QXX_TYPE == W25Q256)//SPI FLASH为W25Q256时才用设置为4字节地址模式{temp = W25QXX_ReadSR(3);//读取状态寄存器3,判断地址模式if((temp&0x01)==0)//如果不是4字节地址模式,则进入4字节地址模式{W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_Enable4ByteAddr);//发送进入4字节地址模式指令W25QXX_CS(1);//0片选开启,1片选关闭}}if(W25QXX_TYPE==W25Q256||W25QXX_TYPE==W25Q128||W25QXX_TYPE==W25Q64||W25QXX_TYPE==W25Q32||W25QXX_TYPE==W25Q16||W25QXX_TYPE==W25Q80)return 0; else return 1;//如果读出ID是现有型号列表中的一个,则识别芯片成功!
}
//读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器
//状态寄存器1:
//BIT7  6   5   4   3   2   1   0
//SPR   RV  TB BP2 BP1 BP0 WEL BUSY
//SPR:默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:FLASH区域写保护设置
//WEL:写使能锁定
//BUSY:忙标记位(1,忙;0,空闲)
//默认:0x00
//状态寄存器2:
//BIT7  6   5   4   3   2   1   0
//SUS   CMP LB3 LB2 LB1 (R) QE  SRP1
//状态寄存器3:
//BIT7      6    5    4   3   2   1   0
//HOLD/RST  DRV1 DRV0 (R) (R) WPS (R) (R)
//regno:状态寄存器号,范:1~3
//返回值:状态寄存器值
uint8_t W25QXX_ReadSR(uint8_t regno)
{uint8_t byte=0,command=0;switch(regno){case 1:command=W25X_ReadStatusReg1;//读状态寄存器1指令break;case 2:command=W25X_ReadStatusReg2;//读状态寄存器2指令break;case 3:command=W25X_ReadStatusReg3;//读状态寄存器3指令break;default:command=W25X_ReadStatusReg1;//读状态寄存器1指令break;}W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(command);//发送读取状态寄存器命令byte=SPI2_ReadWriteByte(0Xff);//读取一个字节W25QXX_CS(1);//0片选开启,1片选关闭return byte;//返回变量byte
}
//写W25QXX状态寄存器
void W25QXX_Write_SR(uint8_t regno,uint8_t  sr)
{uint8_t command=0;switch(regno){case 1:command=W25X_WriteStatusReg1;//写状态寄存器1指令break;case 2:command=W25X_WriteStatusReg2;//写状态寄存器2指令break;case 3:command=W25X_WriteStatusReg3;//写状态寄存器3指令break;default:command=W25X_WriteStatusReg1;break;}W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(command);//发送写取状态寄存器命令SPI2_ReadWriteByte(sr);//写入一个字节W25QXX_CS(1);//0片选开启,1片选关闭
}
//W25QXX写使能
//将WEL置位
void W25QXX_Write_Enable(void)
{W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_WriteEnable);//发送写使能W25QXX_CS(1);//0片选开启,1片选关闭
}
//W25QXX写禁止
//将WEL清零
void W25QXX_Write_Disable(void)
{W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_WriteDisable);//发送写禁止指令W25QXX_CS(1);//0片选开启,1片选关闭
}
//读取芯片ID
//高8位是厂商代号(本程序不判断厂商代号)
//低8位是容量大小
//0XEF13型号为W25Q80
//0XEF14型号为W25Q16
//0XEF15型号为W25Q32
//0XEF16型号为W25Q64
//0XEF17型号为W25Q128(目前洋桃2号开发板使用128容量芯片)
//0XEF18型号为W25Q256
uint16_t W25QXX_ReadID(void)
{uint16_t Temp = 0;W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(0x90);//发送读取ID命令SPI2_ReadWriteByte(0x00);SPI2_ReadWriteByte(0x00);SPI2_ReadWriteByte(0x00);Temp|=SPI2_ReadWriteByte(0xFF)<<8;Temp|=SPI2_ReadWriteByte(0xFF);W25QXX_CS(1);//0片选开启,1片选关闭return Temp;
}
//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(uint8_t* pBuffer,uint32_t  ReadAddr,uint16_t NumByteToRead)
{uint16_t i;W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_ReadData);//发送读取命令if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位{SPI2_ReadWriteByte((uint8_t)((ReadAddr)>>24));}SPI2_ReadWriteByte((uint8_t)((ReadAddr)>>16));//发送24bit地址SPI2_ReadWriteByte((uint8_t)((ReadAddr)>>8));SPI2_ReadWriteByte((uint8_t)ReadAddr);for(i=0;i<NumByteToRead;i++){pBuffer[i]=SPI2_ReadWriteByte(0XFF);//循环读数}W25QXX_CS(1);//0片选开启,1片选关闭
}
//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
void W25QXX_Write_Page(uint8_t*  pBuffer,uint32_t WriteAddr,uint16_t  NumByteToWrite)
{uint16_t i;W25QXX_Write_Enable();//SET WELW25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_PageProgram);//发送写页命令if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位{SPI2_ReadWriteByte((uint8_t)((WriteAddr)>>24));}SPI2_ReadWriteByte((uint8_t)((WriteAddr)>>16));//发送24bit地址SPI2_ReadWriteByte((uint8_t)((WriteAddr)>>8));SPI2_ReadWriteByte((uint8_t)WriteAddr);for(i=0;i<NumByteToWrite;i++)SPI2_ReadWriteByte(pBuffer[i]);//循环写数W25QXX_CS(1);//0片选开启,1片选关闭W25QXX_Wait_Busy();//等待写入结束
}
//无检验写SPI FLASH
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK
void W25QXX_Write_NoCheck(uint8_t*  pBuffer,uint32_t WriteAddr,uint16_t  NumByteToWrite)
{uint16_t pageremain;pageremain=256-WriteAddr%256; //单页剩余的字节数if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节while(1){W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);if(NumByteToWrite==pageremain)break;//写入结束了else //NumByteToWrite>pageremain{pBuffer+=pageremain;WriteAddr+=pageremain;NumByteToWrite-=pageremain;            //减去已经写入了的字节数if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节else pageremain=NumByteToWrite;     //不够256个字节了}};
}
//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
uint8_t W25QXX_BUFFER[4096];
void W25QXX_Write(uint8_t* pBuffer,uint32_t  WriteAddr,uint16_t NumByteToWrite)
{uint32_t secpos;uint16_t secoff;uint16_t secremain;uint16_t i;uint8_t* W25QXX_BUF;W25QXX_BUF=W25QXX_BUFFER;secpos=WriteAddr/4096;//扇区地址secoff=WriteAddr%4096;//在扇区内的偏移secremain=4096-secoff;//扇区剩余空间大小//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节while(1){W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容for(i=0;i<secremain;i++)//校验数据{if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除}if(i<secremain)//需要擦除{W25QXX_Erase_Sector(secpos);//擦除这个扇区for(i=0;i<secremain;i++)//复制{W25QXX_BUF[i+secoff]=pBuffer[i];}W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区}else  W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.if(NumByteToWrite==secremain)break;//写入结束了else//写入未结束{secpos++;//扇区地址增1secoff=0;//偏移位置为0pBuffer+=secremain;  //指针偏移WriteAddr+=secremain;//写地址偏移NumByteToWrite-=secremain;//字节数递减if(NumByteToWrite>4096)secremain=4096;//下一个扇区还是写不完else  secremain=NumByteToWrite;//下一个扇区可以写完了}};
}
//擦除整个芯片
//等待时间超长...
void W25QXX_Erase_Chip(void)
{W25QXX_Write_Enable();//SET WELW25QXX_Wait_Busy();//等待忙状态W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_ChipErase);//发送片擦除命令W25QXX_CS(1);//0片选开启,1片选关闭W25QXX_Wait_Busy();//等待芯片擦除结束
}
//擦除一个扇区
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个扇区的最少时间:150ms
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{Dst_Addr*=4096;W25QXX_Write_Enable();//SET WELW25QXX_Wait_Busy();W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_SectorErase);//发送扇区擦除指令if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位{SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>24));}SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>16));//发送24bit地址SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>8));SPI2_ReadWriteByte((uint8_t)Dst_Addr);W25QXX_CS(1);//0片选开启,1片选关闭W25QXX_Wait_Busy();//等待擦除完成
}
//等待空闲
void W25QXX_Wait_Busy(void)
{while((W25QXX_ReadSR(1)&0x01)==0x01);//等待BUSY位清空
}
//进入掉电模式
void W25QXX_PowerDown(void)
{W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_PowerDown);//发送掉电命令 0xB9W25QXX_CS(1);//0片选开启,1片选关闭delay_us(3);//等待TPD
}
//唤醒
void W25QXX_WAKEUP(void)
{W25QXX_CS(0);//0片选开启,1片选关闭SPI2_ReadWriteByte(W25X_ReleasePowerDown);//发送电源唤醒指令 0xABW25QXX_CS(1);//0片选开启,1片选关闭delay_us(3);//等待TRES1
}
//延时
void delay_us(uint32_t us) //利用CPU循环实现的非精准应用的微秒延时函数
{uint32_t delay = (HAL_RCC_GetHCLKFreq() / 8000000 * us); //使用HAL_RCC_GetHCLKFreq()函数获取主频值,经算法得到1微秒的循环次数while (delay--); //循环delay次,达到1微秒延时
}

main.c

		//W25Q128测试程序device_id = W25QXX_ReadID();printf("\r\nW25Q64 Device ID is 0x%04x\r\n", device_id);/* 为了验证,首先读取要写入地址处的数据 */printf("-------- read data before write -----------\r\n");W25QXX_Read(read_buf, 0, 10);for(i = 0; i < 10; i++) {printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));}/* 擦除该扇区 */printf("-------- erase sector 0 -----------\r\n");W25QXX_Erase_Sector(0);HAL_Delay(50);/* 再次读数据 */printf("-------- read data after erase -----------\r\n");W25QXX_Read(read_buf, 0, 10);for(i = 0; i < 10; i++) {printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));}/* 写数据 */printf("-------- write data -----------\r\n");for(i = 0; i < 10; i++) {write_buf[i] = i;}W25QXX_Write(write_buf, 0, 10);HAL_Delay(50);/* 再次读数据 */printf("-------- read data after write -----------\r\n");W25QXX_Read(read_buf, 0, 10);for(i = 0; i < 10; i++) {printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));}

测试结果

在这里插入图片描述
注意:在FLASH写数据之前一定要进行擦除。

相关文章:

STM32CUBUMX配置FLASH(W25Q128)--保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…...

【Golang 接口自动化04】 解析接口返回JSON串

目录 前言 解析到结构体 json数据与struct字段是如何相匹配的呢&#xff1f; 解析到interface Go类型和JSON类型 实例代码 simpleJson 总结 资料获取方法 前言 上一次我们一起学习了如何解析接口返回的XML数据&#xff0c;这一次我们一起来学习JSON的解析方法。 JSO…...

EPPlus与Microsoft.Office.Interop.Excel的使用区别

文章目录 代码的使用区别EPPlus的工作原理Microsoft.Office.Interop.Excel的使用原理代码的使用区别 static void ExportToExcel(List<(string, double, double)> list, string outputFilePath){//Microsoft.Office.Interop.Excel的使用 /* Excel.Application excelAp…...

ncrack工具使用说明

介绍 网络认证破解工具。 Ncrack是用于网络身份验证破解的开源工具。 它设计为使用可适应不同网络情况的动态引擎进行高速并行破解。 Ncrack还可以针对特殊情况进行广泛的微调,尽管默认参数的通用性足以覆盖几乎所有情况。 它建立在模块化架构上,可以轻松扩展以支持其他协议…...

第二章:进程管理(处理机/CPU管理)

文章目录 2.1 进程与线程1.进程(1)进程的概念、进程的组成、进程的组织(2)进程控制块PCB(3)进程的状态与转换:五状态模型(4)进程控制(5)进程间的通信①共享存储②消息传递③管道通信(6)父进程与子进程(7)进程的内存空间2.线程 Thread(1)线程的概念(2)线程的实现方式:用户级线…...

MySQL中锁的简介——表级锁-元数据锁、意向锁

1.元数据锁 查看元数据锁 select object_type,object_scheme,object_name,lock_type,lock_duration from perfomance_scheme.metadata_locks;2.意向锁 线程A开启事务后在执行update更新语句时候&#xff0c;会给数据加上行锁&#xff0c;加上行锁以后&#xff0c;会对整张表加…...

React几种避免子组件无效刷新的方案

您好&#xff0c;如果喜欢我的文章&#xff0c;可以关注我的公众号「量子前端」&#xff0c;将不定期关注推送前端好文~ 前言 一个很常见的场景&#xff0c;React中父组件和子组件在一起&#xff0c;子组件不依赖于父组件任何数据&#xff0c;但是会一起发生变化。 在探究原…...

分享亿款好用的PDF编辑工具

所周知&#xff0c;PDF文件是不能够像word/excel/ppt等文件一样&#xff0c;可以被随意编辑的&#xff0c;PDF文件往往只能够被查看&#xff0c;我们无法对它进行编辑&#xff0c;或者对上面的文字进行复制&#xff0c;也不能任意删除上面的页面。但是很多时候&#xff0c;我们…...

AI生成式视频技术来临:Runway Gen-2文本生成视频

Runway Gen-2的官方网站提供了一种文本生成视频的工具。以下是对该工具的介绍&#xff1a; 文本生成视频&#xff1a;Runway Gen-2是一个创新的在线工具&#xff0c;可以将文本转化为视频。用户只需输入文本描述或句子&#xff0c;Runway Gen-2就能自动生成相应的视频内容。这…...

react钩子函数

React组件的生命周期包括多个阶段和方法&#xff0c;用于在组件不同的生命周期时执行特定的操作。以下是React类组件中常见的生命周期方法&#xff1a; 挂载阶段&#xff08;Mounting Phase&#xff09;&#xff1a; constructor&#xff1a;组件实例化时调用&#xff0c;用于初…...

RISC-V公测平台发布 · 如何在SG2042上玩转k3s

前言 Kubernetes是一个开源的容器管理平台&#xff0c;通过Kubernetes的跨集群管理功能&#xff0c;用户可以方便地进行应用程序的复制、迁移和跨云平台的部署。 而k3s作为Kubernetes的轻量级发行版&#xff0c;相比传统的Kubernetes具有更小的二进制文件大小和更低的资源消耗…...

Linux系统常见小问题

1、新系统在输入命令时&#xff0c;不会自动提示&#xff0c;按上箭头&#xff08;↑&#xff09;和下向下箭头&#xff08;↓&#xff09;不会匹配之前的输入 以CentOS 为例&#xff0c;可以通过配置 ~/.bashrc 文件来实现按向上箭头显示最相近的命令。以下是具体的实现步骤 …...

WEB:mfw

背景知识 Git泄露 Githack使用 命令执行漏洞 题目 这里页面里有Git&#xff0c;猜测是Git泄露 先用dirsearch扫一下 确实存在.git目录&#xff0c;可以尝试访问一下 使用Githack来下载并恢复.git文件 这里记得使用的时候关闭杀毒软件 结果会自动保存 点进去先看一下flag这个…...

2.4 传统经验光照模型详解

一、光照模型 光照模型&#xff08;illumination model&#xff09;&#xff0c;也称为明暗模型&#xff0c;用于计算物体某点处的光强&#xff08;颜色值&#xff09;。从算法理论基础而言&#xff0c;光照模型分为两类&#xff1a;一种是基于物理理论的&#xff0c;另一种是…...

基于高通QCC5171的对讲机音频数据传输系统设计

一 研发资料准备 二 设计方法 蓝牙连接与配对&#xff1a;使用QCC5171的蓝牙功能&#xff0c;实现设备之间的蓝牙连接和配对。确保设备能够相互识别并建立起稳定的蓝牙连接。 音频采集与处理&#xff1a;将麦克风采集到的音频数据通过QCC5171的ADC&#xff08;模数转换器&…...

【题解】判断链表中是否有环、链表中环的入口结点

文章目录 判断链表中是否有环链表中环的入口结点 判断链表中是否有环 题目链接&#xff1a;判断链表中是否有环 解题思路1&#xff1a;快慢指针 代码如下&#xff1a; bool hasCycle(ListNode *head) {if(head nullptr) return false;ListNode* fast head;ListNode* slow …...

Pytorch 最全入门介绍,Pytorch入门看这一篇就够了

本文通过详细且实践性的方式介绍了 PyTorch 的使用&#xff0c;包括环境安装、基础知识、张量操作、自动求导机制、神经网络创建、数据处理、模型训练、测试以及模型的保存和加载。 1. Pytorch简介 在这一部分&#xff0c;我们将会对Pytorch做一个简单的介绍&#xff0c;包括它…...

Lambda 表达式的作用域

在Lambda表达式中访问外层作用域和旧版本的匿名对象中的方式类似。你可以直接访问标记了final的外层局部变量&#xff0c;或者实例的字段以及静态变量。 Lambda表达式不会从超类&#xff08;supertype&#xff09;中继承任何变量名&#xff0c;也不会引入一个新的作用域。Lambd…...

【portswigger】第二专题-XSS(二)

portswigger 靶场&#xff08;第二章节&#xff09;XSS 视频同步更新至bilibili bibi地址 【【portswigger】第二专题-XSS&#xff08;一前置知识&#xff09;】 https://www.bilibili.com/video/BV1mp4y157xA/?share_sourcecopy_web 【【portswigger】第二专题-XSS&#xff…...

【计算机视觉|人脸建模】3D人脸重建基础知识(入门)

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 一、三维重建基础 三维重建&#xff08;3D Reconstruction&#xff09;是指根据单视图或者多视图的图像重建三维信息的过程。 1. 常见三维重建技术 人工几何模型仪器采集基于图像的建模描述基于几何建模…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...