HAL库 STM32驱动W25QXX驱动例程
HAL库 STM32驱动W25QXX驱动例程
- 📍驱动程序参考:《STM32CubeMX | 基于STM32使用HAL库W25Q128驱动程序》
- 🔑 驱动方式:硬件SPI方式和SPI DMA方式。
- 🔖适用于:W25X系列/Q系列芯片:W25Q80、W25Q16、W25Q32、 W25Q64、 W25Q128、
- 📌W25Q256可以参考《stm32 W25QXX系列驱动 W25Q80 W25Q16 W25Q32 W25Q64 W25Q128 W25Q256》
-
- 📘相关应用篇内容《STM32 STD/HAL库驱动W25Q64模块读写字库数据+OLED0.96显示例程》
- 🍁W25Q64原理图:

🔨spi方式配置

🛠SPI DMA配置

- 🌿自定义CS引脚:

🔰SPI方式和SPI DMA方式软件驱动代码不同之处
//SPI读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
static uint8_t W25QXX_SPI_ReadWriteByte(uint8_t TxData)
{uint8_t RxData = 0X00;// if(HAL_SPI_TransmitReceive(W25QXX_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK)//普通方式if(HAL_SPI_TransmitReceive_DMA(W25QXX_SPI_Handle, &TxData, &RxData, 1) != HAL_OK) { //DMA接收和发送RxData = 0XFF;}return RxData;
}
W25QXX驱动代码
- W25QXX.h
#ifndef __W25QXX_H
#define __W25QXX_H
/*
W25QXX ID信息
读取命令(0x90)
W25Q80的芯片ID为:0XEF13
W25Q16 的芯片ID为:0XEF14
W25Q32 的芯片ID为:0XEF15
W25Q64 的芯片ID为:0XEF16
W25Q128的芯片ID为:0XEF17
W25Q256的芯片ID为:0XEF18
W25Q512的芯片ID为:0XEF19*/
#include <main.h>
//可以根据个人需求配置对应的硬件SPIx
#define W25QXX_SPI_Handle (&hspi2) //使用SPI2//W25X系列/Q系列芯片列表
//W25Q80 ID 0XEF13
//W25Q16 ID 0XEF14
//W25Q32 ID 0XEF15
//W25Q64 ID 0XEF16
//W25Q128 ID 0XEF17
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17#define W25QXX_CS_L() HAL_GPIO_WritePin(W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_RESET)
#define W25QXX_CS_H() HAL_GPIO_WritePin(W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_SET)extern uint16_t W25QXX_TYPE;
extern uint32_t W25QXX_SIZE;
extern uint8_t W25QXX_UID[8];//
//指令表
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg 0x05
#define W25X_WriteStatusReg 0x01
#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 0x9Fint W25QXX_Init(void);
void W25QXX_ReadUniqueID(uint8_t UID[8]);
uint16_t W25QXX_ReadID(void); //读取FLASH ID
uint8_t W25QXX_ReadSR(void); //读取状态寄存器
void W25QXX_Write_SR(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);
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); //唤醒
uint32_t W25QXX_ReadCapacity(void);#endif
- W25Qxx.c
/*** @file w25Qxx.c** @brief Create by AnKun on 2020/6/18**/#include "W25QXX.h"
#include "spi.h"uint16_t W25QXX_TYPE = 0;
uint32_t W25QXX_SIZE = 0;
uint8_t W25QXX_UID[8];static void delay_us(uint32_t us)
{uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);while(delay--) {;}
}//SPI读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
static uint8_t W25QXX_SPI_ReadWriteByte(uint8_t TxData)
{uint8_t RxData = 0X00;// if(HAL_SPI_TransmitReceive(W25QXX_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK)//普通方式if(HAL_SPI_TransmitReceive_DMA(W25QXX_SPI_Handle, &TxData, &RxData, 1) != HAL_OK) { //DMA接收和发送RxData = 0XFF;}return RxData;
}//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q128
//容量为16M字节,共有128个Block,4096个Sector//初始化SPI FLASH的IO口
int W25QXX_Init(void)
{MX_SPI2_Init();//SPI2初始化W25QXX_CS_L(); /* 拉低选中 */W25QXX_SPI_ReadWriteByte(0XFF);W25QXX_CS_H(); /* 拉高取消 */W25QXX_TYPE = W25QXX_ReadID(); // 读取FLASH ID.W25QXX_SIZE = W25QXX_ReadCapacity(); // 读取容量W25QXX_ReadUniqueID(W25QXX_UID); // 读取唯一IDif((W25QXX_TYPE & 0XEF00) != 0XEF00) {return -1;}return 0;
}//读取W25QXX的状态寄存器
//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
uint8_t W25QXX_ReadSR(void)
{uint8_t byte = 0;W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令byte = W25QXX_SPI_ReadWriteByte(0Xff); //读取一个字节W25QXX_CS_H(); //取消片选return byte;
}
//写W25QXX状态寄存器
//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!
void W25QXX_Write_SR(uint8_t sr)
{W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_WriteStatusReg); //发送写取状态寄存器命令W25QXX_SPI_ReadWriteByte(sr); //写入一个字节W25QXX_CS_H(); //取消片选
}
//W25QXX写使能
//将WEL置位
void W25QXX_Write_Enable(void)
{W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_WriteEnable); //发送写使能W25QXX_CS_H(); //取消片选
}
//W25QXX写禁止
//将WEL清零
void W25QXX_Write_Disable(void)
{W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令W25QXX_CS_H(); //取消片选
}
//读取芯片ID
//返回值如下:
//0XEF13,表示芯片型号为W25Q80
//0XEF14,表示芯片型号为W25Q16
//0XEF15,表示芯片型号为W25Q32
//0XEF16,表示芯片型号为W25Q64
//0XEF17,表示芯片型号为W25Q128
uint16_t W25QXX_ReadID(void)
{uint16_t Temp = 0;W25QXX_CS_L();W25QXX_SPI_ReadWriteByte(0x90); //发送读取ID命令W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);Temp |= W25QXX_SPI_ReadWriteByte(0xFF) << 8;Temp |= W25QXX_SPI_ReadWriteByte(0xFF);W25QXX_CS_H();return Temp;
}uint32_t W25QXX_ReadCapacity(void)
{int i = 0;uint8_t arr[4] = {0, 0, 0, 0};W25QXX_CS_L();W25QXX_SPI_ReadWriteByte(0x5A);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x84);W25QXX_SPI_ReadWriteByte(0x00);for(i = 0; i < sizeof(arr); i++) {arr[i] = W25QXX_SPI_ReadWriteByte(0xFF);}W25QXX_CS_H();return ((((*(uint32_t *)arr)) + 1) >> 3);
}void W25QXX_ReadUniqueID(uint8_t UID[8])
{int i = 0;W25QXX_CS_L();W25QXX_SPI_ReadWriteByte(0x4B);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);W25QXX_SPI_ReadWriteByte(0x00);for(i = 0; i < 8; i++) {UID[i] = W25QXX_SPI_ReadWriteByte(0xFF);}W25QXX_CS_H();
}//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{uint16_t i;W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_ReadData); //发送读取命令W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 16)); //发送24bit地址W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 8));W25QXX_SPI_ReadWriteByte((uint8_t)ReadAddr);for(i = 0; i < NumByteToRead; i++) {pBuffer[i] = W25QXX_SPI_ReadWriteByte(0XFF); //循环读数}W25QXX_CS_H();
}
//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_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_PageProgram); //发送写页命令W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 16)); //发送24bit地址W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 8));W25QXX_SPI_ReadWriteByte((uint8_t)WriteAddr);for(i = 0; i < NumByteToWrite; i++)W25QXX_SPI_ReadWriteByte(pBuffer[i]); //循环写数W25QXX_CS_H(); //取消片选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>pageremainpBuffer += pageremain;WriteAddr += pageremain;NumByteToWrite -= pageremain; //减去已经写入了的字节数if(NumByteToWrite > 256)pageremain = 256; //一次可以写入256个字节elsepageremain = 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; //扇区剩余空间大小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); //写入整个扇区} elseW25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间.if(NumByteToWrite == secremain)break; //写入结束了else { //写入未结束secpos++; //扇区地址增1secoff = 0; //偏移位置为0pBuffer += secremain; //指针偏移WriteAddr += secremain; //写地址偏移NumByteToWrite -= secremain; //字节数递减if(NumByteToWrite > 4096)secremain = 4096; //下一个扇区还是写不完elsesecremain = NumByteToWrite; //下一个扇区可以写完了}};
}//擦除整个芯片
//等待时间超长...
void W25QXX_Erase_Chip(void)
{W25QXX_Write_Enable(); //SET WELW25QXX_Wait_Busy();W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_ChipErase); //发送片擦除命令W25QXX_CS_H(); //取消片选W25QXX_Wait_Busy(); //等待芯片擦除结束
}
//擦除一个扇区
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个山区的最少时间:150ms
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{//监视falsh擦除情况,测试用Dst_Addr *= 4096;W25QXX_Write_Enable(); //SET WELW25QXX_Wait_Busy();W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 16)); //发送24bit地址W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 8));W25QXX_SPI_ReadWriteByte((uint8_t)Dst_Addr);W25QXX_CS_H(); //取消片选W25QXX_Wait_Busy(); //等待擦除完成
}
//等待空闲
void W25QXX_Wait_Busy(void)
{while((W25QXX_ReadSR() & 0x01) == 0x01); // 等待BUSY位清空
}
//进入掉电模式
void W25QXX_PowerDown(void)
{W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_PowerDown); //发送掉电命令W25QXX_CS_H(); //取消片选delay_us(3); //等待TPD
}
//唤醒
void W25QXX_WAKEUP(void)
{W25QXX_CS_L(); //使能器件W25QXX_SPI_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xABW25QXX_CS_H(); //取消片选delay_us(3); //等待TRES1
}
- 📝测试代码
int main(void)
{/* USER CODE BEGIN 1 */uint32_t USART_TIMER ;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_SPI2_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */USART_TIMER = HAL_GetTick();printf("SYSCLOCK:%d\r\n", HAL_RCC_GetSysClockFreq()); //HAL_RCC_GetHCLKFreqW25QXX_Init();printf("FLASH ID=%X\r\n", W25QXX_ReadID());HAL_Delay(1000);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(HAL_GetTick() - USART_TIMER > 1000) {USART_TIMER = HAL_GetTick();HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);printf("FLASH ID=%X HCLKFreq:%d\r\n", W25QXX_ReadID(),(uint32_t)HAL_RCC_GetHCLKFreq());}}/* USER CODE END 3 */
}
- 串口打印:

📚程序源码
- 🌿SPI方式:
链接:https://pan.baidu.com/s/1nNLn-v1OdynznLA2m6hDxg?pwd=ilml
提取码:ilml
- 🌿SPI DMA方式
链接:https://pan.baidu.com/s/1acqzZIN4ZNv4DQm7kcVu1w?pwd=ircb
提取码:ircb
相关文章:
HAL库 STM32驱动W25QXX驱动例程
HAL库 STM32驱动W25QXX驱动例程 📍驱动程序参考:《STM32CubeMX | 基于STM32使用HAL库W25Q128驱动程序》🔑 驱动方式:硬件SPI方式和SPI DMA方式。🔖适用于:W25X系列/Q系列芯片:W25Q80、W25Q16、W25Q32、 W25…...
C#入门及进阶|数组和集合(九):Stack类
在C#中,通过类Stack来封装对栈的操作,使得对栈的操作变得非常简单和容易理解。 栈是按照“后进先出”的原则来操作元素。 栈集合常用的属性和方法: 属性说明Count获取 Stack 中包含的元素数。方法说明Peek返回位于栈顶部的对象但不将其移除。Po…...
算法训练day31贪心算法理论基础Leetcode455分发饼干376摆动序列53最大子序和
贪心算法理论基础 文章链接 代码随想录 (programmercarl.com) 说实话贪心算法并没有固定的套路。最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。 面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可&…...
Java与JavaScript同源不同性
Java是目前编程领域使用非常广泛的编程语言,相较于JavaScript,Java更被人们熟知。很多Java程序员想学门脚本语言,一看JavaScript和Java这么像,很有亲切感,那干脆就学它了,这也间接的帮助了JavaScript的发展…...
【JavaEE】spring boot快速上手
SpringBoot快速上手 文章目录 SpringBoot快速上手Maven会出现的一个官方bug创建完项目之后常用的的三个功能依赖管理Maven仓库中央仓库本地仓库国内源配置私服 springboot项目创建什么是springspring boot项目的创建Hello Worldweb服务器 SpringMVC什么是SpringWebMVC什么是MVC…...
【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)
二叉树 一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 性质 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2i−1, i ≥ 1 i \geq 1 i≥1 每层最大结点可以对应完美二叉树(…...
GPT SOVITS项目 一分钟克隆 (文字输出)
步骤流程:(首先使用UVR 提取人声文件,然后按下面步骤进行) 注意这里提交的音频是参考的音频...
python34-Python列表和元组之加法
列表和元组支持加法运算,加法的和就是两个列表或元组所包含的元素的总和。 需要指出的是,列表只能和列表相加;元组只能和元组相加;元组不能直接和列表相加。 如下代码示范了元组和列表的加法运算。 # !/usr/bin/env python# -*- coding: utf-8 -*-# T…...
不做程序员了(转岗半年后对程序员岗位的思考)
不做程序员了(转岗半年后对程序员岗位的思考) 前言 好久没有更新了,已经久到CSDN的小编来问我为什么不更了。原因是我半年前转岗了,不再做程序员了,由程序员变为了产品经理。废话不多说,换个视角来给大家…...
DS:八大排序之直接插入排序、希尔排序和选择排序
创作不易,感谢三连支持!! 一、排序的概念及运用 1.1 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起 来的操作。稳定性&…...
【MySQL】-21 MySQL综合-8(MySQL默认值+MySQL非空约束+MySQL查看表中的约束)
MySQL默认值MySQL非空约束MySQL查看表中的约束 MySQL默认值在创建表时设置默认值约束在修改表MySQL默认值在创建表时设置默认值约束在修改表时添加默认值约束删除默认值约束删除默认值约束 MySQL非空约束在创建表时设置非空约束在修改表时添加非空约束删除非空约束 MySQL查看表…...
力扣hot3--并查集+哈希
第一想法是排个序然后遍历一遍,but时间复杂度就超啦 并查集居然与哈希结合了() 已经好久没用过并查集了,,,我们用哈希表f_node中来记录原结点的父节点,其中key是原结点,value是父节点…...
微信网页版能够使用(会顶掉微信app的登陆)
一、文件结构 新建目录chrome新建icons,其中图片你自己找吧新建文件manifest.json新建文件wx-rules.json 二、文件内容 对应的png你们自己改下 1、manifest.json {"manifest_version": 3,"name": "wechat-need-web","author…...
word软件中硬件图像加速有什么用处?禁用硬件图形加速(G)会影响word文档中插入图片的分辨率吗?
问题描述:word软件中硬件图像加速有什么用处?禁用硬件图形加速(G)会影响word文档中插入图片的分辨率吗? 问题解答: 在 Microsoft Word 中,硬件图形加速主要用于提高图形元素的渲染速度和性能,特别是处理大…...
.NET Core MongoDB数据仓储和工作单元模式封装
前言 上一章我们把系统所需要的MongoDB集合设计好了,这一章我们的主要任务是使用.NET Core应用程序连接MongoDB并且封装MongoDB数据仓储和工作单元模式,因为本章内容涵盖的有点多关于仓储和工作单元的使用就放到下一章节中讲解了。仓储模式(R…...
lua:有关表访问的metamethod
针对在两种正常状态:表的不存在的域的查询和修改,Lua也提供了改变 tables的行为的方法。 index metamethod 我们可以通过index元方法来实现访问table内部不存在的域时人为操控返回数据。 比如以下测试代码: local set {1,2,3} setmetata…...
【MySQL】索引事务
MySQL索引事务 1. 索引1.1 概念1.2 作用1.3 使用场景1.4 使用1.5 案例 2. 事务2.2 事物的概念2.3 使用 3. 内容重点总结 1. 索引 1.1 概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引, 并指定索引的类…...
ChatGPT重大升级:能自动记住用户的习惯和喜好,用户有权决定是否共享数据给OpenAI
OpenAI刚刚宣布了ChatGPT的一项激动人心的更新! OpenAI在ChatGPT中新加了记忆功能和用户控制选项,这意味着GPT能够在与用户的互动中记住之前的对话内容,并利用这些信息在后续的交谈中提供更加相关和定制化的回答。 这一功能目前正处于测试阶…...
CSS设置盒子阴影
语法 box-shadow: *h-shadow v-shadow blur spread color* inset; 注释: box-shadow向框添加一个或多个阴影. 该属性是由逗号分隔的阴影列表,每个阴影由2-4个长度值、可选的颜色值及可选的inset关键词来规定。省略长度的值是0。 外阴影 a、给元素右边框和下边框加外阴影——把…...
文件夹删不掉,显示在另一个文件中打开怎么办
问题: 一、想要删掉这个文件夹,却因为文件夹中的文件打开了删不掉,这里我因为做的测试,所以是知道打开了什么 二、一般情况下文件比较多时,是不知道打开了什么的,长这个样子 解决: 一、打开任…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
