W25Q128存储器详解
可能有很多小伙伴对 W25Q128 感到陌生,说白了它就是一个存储芯片。它是一款高性能、容量较大的闪存存储器芯片,通过 SPI 接口进行通信,适用于各种需要高速、大容量数据存储的场合。常用于嵌入式系统中,作为程序代码存储器或配置数据存储器,如微控制器、单板计算机等。
SPI 是一种通信协议,今天学习 W25Q128 的同时会讲解一下 SPI 通信协议,不懂 SPI 的小伙伴也可以接着看。
1. 源码下载及前置阅读
本文首发良许嵌入式网,https://www.lxlinux.net/e/ ,欢迎关注!
本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):
https://www.lxlinux.net/e/stm32/w25q128-tutorial.html
如果你是嵌入式开发小白,那么建议你先读读下面几篇文章。
- 通俗易懂的 GPIO 介绍与实践:如何快速成为点灯大师?
- 从零开始轻松掌握STM32开发的必备指南:零基础快速上手STM32开发(手把手保姆级教程)
- 使用接收中断+超时判断完成不定长数据的接收:STM32串口接收不定长数据(空闲中断+DMA)
往期教程,有兴趣的小伙伴可以看看。
- ESP8266详解,助你成为物联网应用的专家:手把手教你玩转ESP8266(原理+驱动)
- 实现物联网数据采集与远程监控:小项目:使用MQTT上传温湿度到Onenet服务器
- 深入浅出,帮助您理解和应用MQTT协议:万字猛文:MQTT原理及案例
作者简介 |
---|
大家好,我是良许,博客里所有的文章皆为我的原创。 下面是我的一些个人介绍,欢迎交个朋友: · 211工科硕士,国家奖学金获得者; · 深耕嵌入式11年,前世界500强外企高级嵌入式工程师; · 书籍《速学Linux作者》,机械工业出版社专家委员会成员; · 全网60W粉丝,博客分享大量原创成体系文章,全网阅读量累计超4000万; · 靠自媒体连续年入百万,靠自己买房买车。 |
我本科及硕士都是学机械,通过自学成功进入世界500强外企。我已经将自己的学习经验写成了一本电子书,超千人通过此书学习并转行成功。现在将这本电子书免费分享给大家,希望对你们有帮助:
电子书链接:https://www.lxlinux.net/1024.html
2. W25Q128介绍
2.1 W25Q128型号介绍
W25Q128是华邦公司推出的一款容量为 128M-bit(相当于 16M-byte)的 SPI 接口的 NOR Flash 芯片。
给大家解释一下新单词:
- NOR Flash:一种非易失性存储器,它可以在断电或掉电后仍然保持存储的数据,因此被广泛应用于长期数据存储。它具有容量大,可重复擦写、按“扇区/块”擦除的特性。Flash 是有一个物理特性:只能写 0 ,不能写 1 ,写 1 靠擦除。
它还有很多不同容量的好兄弟:
型号 | 容量 |
---|---|
W25Q256 | 256M bits = 32M bytes |
W25Q128 | 128M bits = 16M bytes |
W25Q64 | 64M bits = 8M bytes |
W25Q32 | 32M bits = 4M bytes |
W25Q16 | 16M bits = 2M bytes |
W25Q80 | 8M bits = 1M bytes |
2.2 W25Q128模块参数及引脚介绍
W25Q128 的模块各个厂家做的各有不同,只是长得不一样而已,使用方式、引脚都是一样的。下面我介绍的是我们自绘的 W25Q128 模块。
W25Q128参数:
- 产品容量:128M-bit(16M-byte)
- 时钟频率:<=104MHz
- 工作电压:2.7V ~ 3.6V
- 工作温度:-40℃ ~ +85℃
- 支持 SPI 接口
参考接线如下:
W25Q128 | STM32 | 备注 |
---|---|---|
VCC | 3.3 | 电源正极 |
CS | A4/B12 | 片选信号 |
DO | A6/B14 | 输出 |
GND | G | 电源负极 |
CLK | A5/B13 | 时钟信号 |
DI | A7/B15 | 输入 |
如果你对引脚介绍有点懵,没关系,看看下面的 SPI 介绍你就明白了。
2.3 W25Q128存储架构
W25Q128 将 16M 的容量分为 256 个块(block),每块 64K 字节;每块分为 16 个扇区(sector),一扇区 4K 字节;每扇区分为 16 个页(page),一页 256 字节。
W25Q128 的最小擦除单位为一个扇区,也就是每次必须擦除 4K 个字节。这样我们需要给 W25Q128 开辟一个至少 4K 的缓存区。
2.4 W25Q128常用指令
W25Q128 有非常多的指令,这里我们只介绍几个指令。
指令(HEX) | 名称 | 作用 |
---|---|---|
0x06 | 写使能 | 写入数据/擦除之前,必须先发送该指令 |
0x05 | 读 SR1 | 判定 FLASH 是否处于空闲状态,擦除用 |
0x03 | 读数据 | 读取数据 |
0x02 | 页写 | 写入数据,最多写256字节 |
0x20 | 扇区擦除 | 扇区擦除指令,最小擦除单位 |
具体工作时序如下:
写使能 (06H)
执行页写,扇区擦除,块擦除,片擦除,写状态寄存器等指令前,需要写使能。
拉低 CS 片选 → 发送 06H → 拉高 CS 片选
读SR1(05H)
拉低 CS 片选 → 发送 05H → 返回SR1的值 → 拉高 CS 片选
读数据(03H)
拉低 CS 片选 → 发送 03H → 发送24位地址 → 读取数据(1~n)→ 拉高 CS 片选
页写 (02H)
页写命令最多可以向FLASH传输256个字节的数据。
拉低 CS 片选 → 发送 02H → 发送24位地址 → 发送数据(1~n)→ 拉高 CS 片选
扇区擦除(20H)
写入数据前,检查内存空间是否全部都是 0xFF ,不满足需擦除。
拉低 CS 片选 → 发送 20H→ 发送24位地址 → 拉高 CS 片选
2.5 W25Q128状态寄存器
W25Q128 一共有 3 个状态寄存器,它们的作用是跟踪芯片的状态。
这里我们只介绍常用的状态寄存器 1:
我不过多介绍了,感兴趣的小伙伴可以去看芯片手册。
我们需要记住的是在状态寄存器 1 中:
BUSY:指示当前的状态,0 表示空闲;1 表示忙碌。
WEL:写使能锁定,为 1 时,可以操作页/扇区/块;为 0 时,写禁止。
3. SPI介绍
SPI(Serial Peripheral Interface)串行外设接口,是一种高速、全双工、同步的通信总线,仅使用四根线来连接芯片的管脚,节省了管脚和PCB布局空间。由于其简单易用的特性,越来越多的芯片集成了SPI通信协议。
3.1 SPI物理架构
SPI 工作模式:
SPI 通信分为主设备(Master)和从设备(Slave)。一个完整的 SPI 通信系统需要包含一个主设备和一个或多个从设备。主设备提供时钟信号,从设备接收时钟信号。所有的读写操作都由主设备发起。当存在多个从设备时,通过各自的片选信号进行管理。
SPI 是全双工,并且没有定义速度限制,一般的实现通常能达到甚至超过 10Mbps。
SPI 信号线:
SPI 一般使用四条信号线通信:
- SCLK(Serial Clock):时钟信号线,由主设备提供并驱动整个通信过程。
- MOSI(Master Output,Slave Input):主设备输出、从设备输入线,主设备向从设备发送数据。
- MISO(Master Input,Slave Output):主设备输入、从设备输出线,从设备向主设备发送数据。
- SS/CS(Slave Select / Chip Select):片选信号线,由主设备控制从设备的选中状态。拉低表示选中。
示意图如下:
3.2 SPI工作原理
SPI 通信中,主机和从机都有一个串行移位寄存器。主机通过向自己的 SPI 串行寄存器写入一个字节来发起传输。
- 首先,拉低相应的 SS 信号线,表示与特定的从机进行通信。
- 主机通过发送 SCLK 时钟信号告诉从机进行数据的读写操作。
- 注意,SCLK 时钟信号可以是低电平有效或高电平有效,因为SPI有不同的模式(下文将介绍)。
- 主机将要发送的数据写入发送数据缓冲区,然后通过移位寄存器逐位地将数据传输给从机的串行移位寄存器,使用 MOSI 信号线进行传输。同时,从机的 MISO 接口接收到的数据也经过移位寄存器一位一位地移到接收缓冲区。
- 从机也通过 MISO 信号线将自己串行移位寄存器中的内容返回给主机。同时,从机通过 MOSI 信号线接收主机发送的数据。这样,两个移位寄存器中的内容就被交换。
SPI通信只有主模式和从模式,没有明确的读和写操作之分。实际上,外设的写操作和读操作是同步完成的。在SPI通信中,发送一个数据必然会收到一个数据;如果要接收一个数据,就必须先发送一个数据。
如果只进行写操作,主机可以忽略从设备传输过来的字节,因为主机不需要接收数据。
如果主机要读取从设备的一个字节,那么主机必须发送一个空字节来引发从设备的传输。
3.3 SPI工作模式
SPI 有4种不同的工作模式。
从设备的 SPI 模式是厂家设定的,不可变。但主从设备必须在同一工作模式下才能正常工作。所以我们可以设置主设备的 SPI 模式。
那怎么设置呢?通过 CPOL(时钟极性)和 CPHA(时钟相位)来控制,具体如下:
CPOL(时钟极性)定义了时钟空闲状态电平:
- CPOL=0,表示当 SCLK=0 时处于空闲态,所以有效状态就是 SCLK 处于高电平时。
- CPOL=1,表示当 SCLK=1 时处于空闲态,所以有效状态就是 SCLK 处于低电平时。
CPHA(时钟相位)定义数据的采集时间:
- CPHA=0,SCLK 的第一个(奇数)边沿进行数据位采样。数据在第一个时钟边沿被锁存,在第二个边沿发送数据。
- CPHA=1,SCLK 的第二个(偶数)边沿进行数据位采样。数据在第二个时钟边沿被锁存,在第一个边沿发送数据。
总结如下表:
SPI 模式 | CPOL | CPHA | 空闲时 SCK 时钟 | 采样边沿 | 采样时刻 |
---|---|---|---|---|---|
0 | 0 | 0 | 低电平 | 上升沿 | 奇数边沿 |
1 | 0 | 1 | 低电平 | 下降沿 | 偶数边沿 |
2 | 1 | 0 | 高电平 | 下降沿 | 奇数边沿 |
3 | 1 | 1 | 高电平 | 上升沿 | 偶数边沿 |
四个模式的时序图如下,方便大家理解。绿线表示开始与结束,黄线表示数据采样,蓝线表示数据发送。
1.模式0(常用)CPOL = 0,CPHA = 0。
空闲时 SCLK 为低电平,采样时刻为第一个边沿,即上升沿。
2.模式1CPOL = 0,CPHA = 1。
空闲时 SCLK 为低电平,采样时刻为第二个边沿,即下降沿。
3.模式2,CPOL = 1,CPHA = 0。
空闲时 SCLK 为高电平,采样时刻为第一个边沿,即上升沿。
4.模式3(常用),CPOL = 1,CPHA = 1。
空闲时 SCLK 为高电平,采样时刻为第二个边沿,即上升沿。
4. 编程实战
实战目标:使用 SPI 通讯读写 W25Q128 模块。
4.1 硬件接线
本教程使用的硬件如下:
- W25Q128 模块
- 单片机:STM32F103C8T6
- 串口:USB 转 TTL
- 烧录器:ST-LINK V2
W25Q128 | STM32 | USB 转 TTL |
---|---|---|
VCC | 3.3 | |
CS | A4 | |
CLK | A5 | |
DO | A6 | |
DI | A7 | |
A10 | TX | |
A9 | RX | |
G | GND |
烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。
ST-Link V2 | STM32 |
---|---|
SWCLK | SWCLK |
SWDIO | SWDIO |
GND | GND |
3.3V | 3V3 |
接好如下图。开发板使用的是我们自绘的板子。大家也可以用自己的板子,只要是 STM32F103C8T6 主控芯片就行。
4.2 SPI初始化
SPI 的工作模式我们配置为 0,即 CPOL = 0,CPHA = 0。
STM32F1系列的 SPI 接口有两个,SPI1 和 SPI2,这里我们选择 SPI1,引脚对应关系如下:
void SPI1_Init(void)
{hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; /* CPOL = 0 */hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; /* CPHA = 0 */hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;HAL_SPI_Init(&hspi1);
}void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct;if(spiHandle->Instance==SPI1){__HAL_RCC_SPI1_CLK_ENABLE(); /* SPI1时钟使能 */__HAL_RCC_GPIOA_CLK_ENABLE();/*PA4 ------> SPI1_CSPA5 ------> SPI1_SCKPA6 ------> SPI1_MISOPA7 ------> SPI1_MOSI*/GPIO_InitStruct.Pin = W25Q128_CS_GPIO_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(W25Q128_CS_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}
}
4.3 SPI读写一个字节
我们利用 HAL 库的 SPI 数据发送和接收函数 HAL_SPI_TransmitReceive
来读写一个字节。
函数原型:HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
。
参数说明:
- hspi:指向SPI外设的句柄(handle)。
- pTxData:要发送的数据缓冲区指针。
- pRxData:接收数据的缓冲区指针。
- Size:要发送/接收的数据字节数。
- Timeout:超时时间,以毫秒为单位。
根据 SPI 的工作原理,我们发送一个字节的 data
,得到一个字节的 rec_data
。后续如果我们只需要读取一个字节,就发送一个无意义的 0xFF。
uint8_t read_write_one_byte(uint8_t data)
{uint8_t rec_data = 0;HAL_SPI_TransmitReceive(&hspi1, &data, &rec_data, 1, 1000);return rec_data;
}
4.4 W25Q128初始化
初始化我们做个小检测,确保这个芯片是 W25Q128,而不是 W25Q64 或者 W25Q32。W25Q128 的芯片号是 0XEF17,从哪来的呢,当然是芯片手册啦。
void w25q128_init(void)
{uint16_t flash_type;read_write_one_byte(0xFF); /* 清除DR的作用 */W25Q128_CS(1); /* 拉高片选 */flash_type = w25q128_read_id(); /* 读取FLASH ID. */if (flash_type == 0XEF17) /* FLASH芯片号0XEF17 */printf("检测到W25Q128芯片\r\n");
}uint16_t w25q128_read_id(void)
{uint16_t deviceid;W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_ManufactDeviceID); /* 发送读 ID 命令 0x90 */read_write_one_byte(0); /* 写入三个0 */read_write_one_byte(0);read_write_one_byte(0);deviceid = read_write_one_byte(0xFF) << 8; /* 读取高8位字节 */deviceid |= read_write_one_byte(0xFF); /* 读取低8位字节 */W25Q128_CS(1); /* 拉高片选 */return deviceid;
}
4.5 W25Q128等待空闲
前面我们提到状态寄存器 1 中 BUSY 是指示当前的状态,0 表示空闲;1 表示忙碌。
所以我们读取 W25Q128 的状态寄存器 1 的值,
static void w25q128_wait_busy(void)
{while ((w25q128_rd_sr1() & 0x01) == 0x01); /* 等待BUSY位为0 */
}uint8_t w25q128_rd_sr1(void)
{uint8_t rec_data = 0;W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_ReadStatusReg1); /* 读状态寄存器1 0x05 */rec_data = read_write_one_byte(0xFF);W25Q128_CS(1); /* 拉高片选 */return rec_data;
}
4.6 W25Q128写使能
写入数据/擦除之前必须写使能。
按照 W25Q128 写使能的工作时序:拉低 CS 片选 → 发送 06H → 拉高 CS 片选,编写代码。
void w25q128_write_enable(void)
{W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_WriteEnable); /* 发送写使能 0x06 */W25Q128_CS(1); /* 拉高片选 */
}
4.7 W25Q128发送地址
read_write_one_byte
一次发送一字节数据,而 W25Q128 的地址有三字节,所以我们分三次发送。
static void w25q128_send_address(uint32_t address)
{read_write_one_byte((uint8_t)((address)>>16)); /* 发送 bit23 ~ bit16 地址 */read_write_one_byte((uint8_t)((address)>>8)); /* 发送 bit15 ~ bit8 地址 */read_write_one_byte((uint8_t)address); /* 发送 bit7 ~ bit0 地址 */
}
4.8 W25Q128擦除一个扇区
传参 saddr
表示要擦除第几扇区,注意我们计算机是从0开始数数哦。剩下就是按工作时序写理论,注释写的很清楚啦,不多讲。
void w25q128_erase_sector(uint32_t saddr)
{saddr *= 4096; /* 一扇区4096字节 */w25q128_write_enable(); /* 写使能 */w25q128_wait_busy(); /* 等待空闲 */W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_SectorErase); /* 发送扇区擦除命令 0x20 */w25q128_send_address(saddr); /* 发送地址 */W25Q128_CS(1); /* 拉高片选 */w25q128_wait_busy(); /* 等待扇区擦除完成 */
}
4.9 W25Q128页写和读数据
传参 pbuf
:要写入/读取的数据,addr
:开始写入的地址,datalen
:字节数。剩下就是按工作时序写理论,注释写的很清楚啦,不多讲。
void w25q128_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{uint16_t i;w25q128_write_enable(); /* 写使能 */W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_PageProgram); /* 发送页写命令 0x02*/w25q128_send_address(addr); /* 发送地址 */for(i=0;i<datalen;i++){read_write_one_byte(pbuf[i]); /* 循环写入 */}W25Q128_CS(1); /* 拉高片选 */w25q128_wait_busy(); /* 等待写入结束 */
}void w25q128_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{uint16_t i;W25Q128_CS(0); /* 拉低片选 */read_write_one_byte(FLASH_ReadData); /* 发送读取命令 0x03 */w25q128_send_address(addr); /* 发送地址 */for(i=0;i<datalen;i++){pbuf[i] = read_write_one_byte(0XFF); /* 循环读取 */}W25Q128_CS(1); /* 拉高片选 */
}
4.10 主函数
我们向 W25Q128 写入一句“良许 嵌入式”,然后读出。
int main(void)
{uint8_t datatemp[TEXT_SIZE];HAL_Init(); /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */uart1_init(115200); /* 串口初始化,波特率115200 */printf("SPI通讯读写W25Q128模块...\r\n");SPI1_Init();w25q128_init();/* 写入数据 */sprintf((char *)datatemp, "良许 嵌入式");w25q128_erase_sector(0); /* 擦除第一个扇区 */w25q128_write_page(datatemp, 0x00000, TEXT_SIZE); /* 从第0位开始写 */printf("数据写入完成!\r\n");/* 读出数据 */memset(datatemp, 0, TEXT_SIZE);w25q128_read(datatemp, 0x00000, TEXT_SIZE); /* 从第0位开始读 */printf("读出数据:%s\r\n", datatemp);while(1){}
}
4.11 最终效果
串口输出如下:
5. 小结
细心的小伙伴会发现我只是简单的写页、读数据、擦扇区。一页有256字节,那如果我第一页只写了50字节,又去第二页写100字节,这不是很浪费存储空间吗。不是我不会更完善的代码,源码我都藏着呢,只是作为入门教程这样的程度刚刚好,剩下的进阶优化就留作课后作业吧。
感谢各位看官,peace and love!
另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。
刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!
有收获?希望老铁们来个三连击,给更多的人看到这篇文章
推荐阅读:
- 程序员必备编程资料大全
- 程序员必备软件资源
欢迎关注我的博客:良许嵌入式教程网,满满都是干货!
相关文章:

W25Q128存储器详解
可能有很多小伙伴对 W25Q128 感到陌生,说白了它就是一个存储芯片。它是一款高性能、容量较大的闪存存储器芯片,通过 SPI 接口进行通信,适用于各种需要高速、大容量数据存储的场合。常用于嵌入式系统中,作为程序代码存储器或配置数…...

Vite系列课程 | 11. Vite 配置文件中 CSS 配置(Modules 模块化篇)
11. Vite 配置文件中 CSS 配置(Modules 模块化篇) 由于课程讲的是 vite2 版本,所以我阅读了 vite6 中的文档,下面将结合 css.modules 的接口进行讲解 CSSModulesOptions 接口文档 interface CSSModulesOptions {/*** 用户可以自…...

Everspin代理MR25H10CDFR存储MRAM
RAMSUN提供的MR25H10CDFR是一款具备1,048,576位存储容量的磁阻随机存取存储器(MRAM)设备,由131,072个8位字构成。该设备提供与串行EEPROM和串行闪存兼容的读/写时序,无写延迟,并且其读/写寿命是不受限制的。 与其它串…...

cesium小知识:使用 EntityCollection的方法
EntityCollection 是 Cesium 中用于管理一组 Entity 的集合对象。它提供了一种高效的方式来批量添加、移除和操作多个实体,同时支持事件监听,以便在集合中的实体发生变化时执行特定的逻辑。 下面是如何使用 EntityCollection 的一些基本指导: 创建 EntityCollection 当你…...

Java 日志类库
Java 日志库是最能体现 Java 库在进化中的渊源关系的,在理解时重点理解日志框架本身和日志门面,以及比较好的时间等。要关注其历史渊源和设计(比如桥接),而具体在使用时查询接口即可,否则会陷入 JUL&#x…...

【Unity3D】Particle粒子特效或3D物体显示在UGUI上的方案
目录 一、RawImage Camera RenderTexture方式 (1)扩展知识:实现射线检测RawImage内的3D物体 (2)扩展知识:实现粒子特效显示RawImage上 二、UI摄像机 Canvas(Screen Space - Camera模式)方式 &#…...

有没有检测吸烟的软件 ai视频检测分析厂区抽烟报警#Python
在现代厂区管理中,安全与规范是重中之重,而吸烟行为的管控则是其中关键一环。传统的禁烟管理方式往往依赖人工巡逻,效率低且存在监管死角,难以满足当下复杂多变的厂区环境需求。此时,AI视频检测技术应运而生࿰…...

《鸣潮》游戏运行时弹出“xinput1_3.dll文件缺失”错误的处理方法,“xinput1_3.dll文件缺失”详解!
一、xinput1_3.dll文件的重要性 xinput1_3.dll是DirectX组件中的一个重要文件,它负责处理与Xbox 360控制器相关的输入功能。尽管《鸣潮》可能并不直接依赖于Xbox控制器,但许多现代游戏和应用程序都会调用这个DLL文件来处理各种输入设备的功能。因此&…...

大模型应用—HivisionIDPhotos 证件照在线制作!支持离线、换装、美颜等
HivisionIDPhotos 证件照在线制作!支持离线、换装、美颜等 ivisionIDPhotos 是一款功能强大的开源证件照生成工具。用户只需上传一张人像照片,它就能智能裁剪为一寸、两寸等标准尺寸,同时自动去除背景并渲染新的背景颜色,例如蓝色、白色、红色,还支持渐变色和自定义颜色。…...

解决Ubuntu下无法装载 Windows D盘的问题
电脑安装了 Windows 和 Ubuntu 24.04 后,在Ubuntu系统上装载 D盘,发现无法装载错误如下: Error mounting /dev/nvme0n1p4 at /media/jackeysong/Data: wrong fs type, bad option, bad superblock on /dev/nvme0n1p4, missing codepage or h…...

一体成型电感
一体成型电感是通过铁粉模压成型而成的同封装条件下实现更大的额定电流,且更适合批量自动化生产,较传统绕线电感有成本优势。同时,一体成型电感与磁封胶结构电感相比具有更好的磁屏蔽效果,适合EMI无法调试通过的项目使用。 但一体…...

Reed-Muller(RM)码之编码
点个关注吧! 看了一些中文的博客,RM码没有很详细的资料,所以本文尝试给出推导原理。 推导 RM码由 ( r , m ) ( r , m ) (r,m...

【蓝桥杯——物联网设计与开发】基础模块8 - RTC
目录 一、RTC (1)资源介绍 🔅简介 🔅时钟与分频(十分重要‼️) (2)STM32CubeMX 软件配置 (3)代码编写 (4)实验现象 二、RTC接口…...

聚类算法DBSCAN 改进总结
目录 DBSCAN(Density-Based Spatial Clustering of Applications with Noise) 1. HDBSCAN (Hierarchical DBSCAN) 优点: 安装: 使用实例1 效果失败 使用实例2 3. DBSCAN++ (DBSCAN with Preprocessing) 4. DBSCAN with k-distance 5. Density Peaks Clustering (DP…...

uniapp开发微信小程序实现获取“我的位置”
1. 创建GetLocation项目 使用HBuilder X创建一个项目GetLocation,使用Vue3。 2. 在腾讯地图开放平台中创建应用 要获取位置,在小程序中需要使用腾讯地图或是高德地图。下面以腾讯地图为例。 (1)打开腾讯地图开放平台官方网址:腾讯位置服务 - 立足生态,连接未来 (2)注册…...

java中两个系统进行非对称加密,两个系统的公私钥可以用一套吗?
在非对称加密中,每个参与方应该拥有自己独立的一套公钥和私钥。非对称加密的基础在于公钥和私钥的配对使用:一个密钥用于加密信息,则另一个对应的密钥用于解密信息。具体来说: 如果A要发送一条保密消息给B,那么A会使用…...

无人设备遥控器之定向天线篇
一、定义与功能 定向天线,顾名思义,是通过改变天线的辐射方向,实现信号发射、接收和增强的天线。它可以让信号以更高的功率、更远的距离传输到指定区域,同时也能够降低与周围天线之间的干扰。在无人设备遥控器中,定向天…...

【电路笔记 信号】Metastability 平均故障间隔时间(MTBF)公式推导:进入亚稳态+退出亚稳态+同步器的可靠性计算
这是一个简化的电路分析模型。图2中的典型触发器包括主锁存器、从锁存器和去耦反相器(这个结构类似 主从边沿触发器)。 在亚稳态中,主锁存器的节点A、B的电压电平大致在逻辑“1”(VDD)和“0”(GND)之间。确切的电压电平…...

计算机视觉:原理、分类与应用
计算机视觉是当今科技领域中一个至关重要的分支,它赋予了计算机通过视觉感知和理解世界的能力。简单来说,计算机视觉实现了对图像、视频等视觉数据的分析、处理、识别和理解。这是一个跨学科的研究领域,涉及计算机科学、信息工程、数学、物理…...

Vue.js组件开发-使用watch进行深度观察
在Vue.js中,watch选项允许观察和响应Vue实例上数据的变化。当需要对某个数据属性进行深度观察,即在其内部嵌套的对象或数组发生变化时也能触发回调时,可以使用deep选项。 示例: new Vue({el: #app,data: {user: {name: John,age…...

明厨亮灶系统
校园食堂明厨亮灶AI分析系统通过yolov5网络模型技术,校园食堂明厨亮灶监控分析系统针对校园餐厅后厨不按要求戴口罩、不穿厨师帽、陌生人员进入后厨、厨师不穿厨师服、上班时间玩手机、老鼠识别等行为校园食堂明厨亮灶监控分析系统自动识别抓拍告警。Yolo算法&#…...

虚幻引擎结构之AActor
在虚幻引擎中,AActor 是一个核心类,作为游戏世界内所有可交互对象的基础。任何可以在关卡中放置或动态生成的对象,几乎都是从 AActor 类派生而来。这包括但不限于角色、道具、特效、静态和动态物体等。 1. AActor 的基本概念 AActor 作为基类…...

基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
基于JAVASpringBootVue的制造装备物联及生产管理ERP系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接&am…...

JAVA HTTP压缩数据
/*** 压缩数据包** param code* param data* param resp* throws IOException*/protected void writeZipResult(int code, Object data, HttpServletResponse resp) throws IOException {resp.setHeader("Content-Encoding", "gzip");// write到客户端resp…...

VSCode 配置远程连接免密登录 插件
自我存档 远程连接免密登录 远程连接 在扩展界面搜remote ssh 安装完成后可以在侧边栏找到远程资源管理器 通过来添加或者点击打开ssh配置文件 点击的话以这种方式, 手动添加则按照相同格式输入即可 格式如下所示, Host后添加IP, User是登录ssh的用户, hostname是显示在…...

VIVO C++开发面试题及参考答案
面向过程与面向对象的区别,面向对象后的好处 面向过程编程主要关注的是程序的流程,它将一个问题分解为一系列的步骤,通过函数来实现这些步骤,数据和操作这些数据的函数是分离的。例如,在一个简单的计算学生成绩平均值的程序中,我们可能会有一些函数来输入成绩、计算总和、…...

Unity3D用正则判断身份证号或邮箱
系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、正则判断邮箱格式👉二、正则判断身份证号👉壁纸分享👉总结👉前言 C#正则表达式(Regex)是一种用来匹配字符串模式的强大工具。在C#中,可以使用System.Text.RegularExpressions命名空间下的Regex类来处…...

【终端工具】FinalShell v4.5.12 官方版
1.下载地址 【终端工具】FinalShell v4.5.12 官方版 2.简介 FinalShell是一款免费的跨平台远程管理工具,专为开发者和运维人员设计。它支持通过 SSH、SFTP 等方式连接到 Linux 和 Windows 服务器,提供类似于终端的操作界面。除了常规的远程登录功能&a…...

【阅读记录-章节6】Build a Large Language Model (From Scratch)
系列文章目录 【阅读记录-章节1】Build a Large Language Model (From Scratch) 【阅读记录-章节2】Build a Large Language Model (From Scratch) 【阅读记录-章节3】Build a Large Language Model (From Scratch) 【阅读记录-章节4】Build a Large Language Model (From Scr…...

面向未来的教育技术:智能成绩管理系统的开发
3.1 可行性研究 成绩管理系统开发实现分析需要从不同的角度来进行分析可行性,比如从时间角度,经济角度,甚至操作角度。从不同的角度分析可行性会让成绩管理系统开发具体化,进而达到辩证开发的正确性。 3.1.1 经济可行性 从经济方面…...