SPI通信协议(软件SPI读取W25Q64)

news2025/7/22 22:45:15

SPI通信协议

文章目录

  • SPI通信协议
    • 1.SPI通信
    • 2.SPI硬件和软件规定
      • 2.1SPI硬件电路
      • 2.2移位示意图
      • 2.3SPI基本时序单元
        • 2.3.1起始和终止条件
        • 2.3.2交换一个字节(模式1)
      • 2.4SPI波形分析(辅助理解)
        • 2.4.1发送指令
        • 2.4.2指定地址写
        • 2.4.3指定地址读
    • 3.W25Q64
      • 3.1简介
      • 3.2硬件电路(引脚说明)
      • 3.3框图
        • 3.4手册重要点
    • 4.Flash操作注意事项
    • 5.软件SPI读取W25Q64(实操)
      • 5.1接线图
      • 5.2程序整体框架
      • 5.3代部分
      • 5.4总结
        • 5.4.1核心步骤
        • 5.4.2重点总结
        • 5.4.3手写部分
        • 5.4.2重点总结
        • 5.4.3手写部分

SPI的传输速度比较快,SPI没有规定传输速度,最大传输速度取决于芯片产商的设计需求。

SPI的实现功能没有I2C多

SPI硬件开销比较大,通信线个数比较多,通信过程中,经常有资源浪费的现象

1.SPI通信

  • SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
  • 四根通信线:SCK(Serial Clock)串行时钟线、MOSI(Master Output Slave Input)主机输出从机输入、MISO(Master Input Slave Output)主机输入从技术出、SS(Slave Select)从机选择
  • 同步,全双工
  • 支持总线挂载多设备(一主多从)

SCK引脚就是用来提供时钟信号的,数据位的输出和输入都是在SCK的上升或下降沿进行的,这样数据位的手法时刻就可以明确的确定,并且同步时序

一主多从,不支持多主机。

相关器件图

2.SPI硬件和软件规定

2.1SPI硬件电路

SS线都是低电平有效,所以需要哪条线,哪条置低电平就好了

如果三个送机始终都是推挽输出,会导致冲突,所以协议规定当从机的SS引脚为高电平,也就从机未被选中时,MISO引脚必须切换为高阻态(相当于引脚断开,不输出任何电平),切换是在从机中进行,所以主机不用关系这些问题。

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起
  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚
  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

SPI硬件电路

一主三从(本图)

2.2移位示意图

SPI基本的收发电路就是使用了这样一个移位的模型。

移位示意图

左边为SPI主机有一个8位的移位寄存器;右边位SPI从机也有一个8位的移位寄存器。

由主机产生时钟(这里为波特率发生器),它产生的时钟驱动主机的移位寄存器进行移位,同时通过SCK输出到从机。

数据是往左移动的,通过MOSI引脚,输入到从机移位寄存器的右边。从机移位寄存器的数据,通过MISO引脚,输入到主机移位寄存器的右边。

工作流程:波特率发生器时钟的上升沿,所有移位寄存器向左移动一位,移出去的位放到引脚上,波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位。

如果只想单方面的发送或接收数据,只需随意发送数据将另一边的数据置换过来就好了。

2.3SPI基本时序单元

2.3.1起始和终止条件
  • 起始条件:SS从高电平切换到低电平
  • 终止条件:SS从低电平切换到高电平

起始和终止条件

通信过程种SS保持低电平

2.3.2交换一个字节(模式1)

(Clock polarity)时钟极性和(Clock Phase)时钟相位,每一位都可以配置为1和0,所以有4种模式,功能一样,所以实际学习其中一种就好了

  • 交换一个字节(模式1)
  • CPOL=0:空闲状态时,SCK为低电平
  • CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据

模式一

MISO介于高电平和低电平之间表示高阻态。

模式0与模式1的区别就是模式0把这个数据变化的时机给提前了。开始就要移出数据,模式0用的最多。

模式2和模式2,分别是模式0和模式1的SCK取反,了解0/1就理解2/3.

2.4SPI波形分析(辅助理解)

SPI没有应答位

2.4.1发送指令
  • 发送指令
  • 向SS指定的设备,发送指令(0x06)

发送波形图

2.4.2指定地址写
  • 指定地址写
  • 向SS指定的设备,发送写指令(0x02), 随后在指定地址(Address[23:0])下,写入指定数据(Data)

指定地址写

2.4.3指定地址读
  • 指定地址读
  • 向SS指定的设备,发送读指令(0x03), 随后在指定地址(Address[23:0])下,读取从机数据(Data)

指定地址读

3.W25Q64

3.1简介

  • W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景
  • 存储介质:Nor Flash(闪存)
  • 时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)
  • 存储容量(24位地址):
    • W25Q40: 4Mbit / 512KByte
    • W25Q80: 8Mbit / 1MByte
    • W25Q16: 16Mbit / 2MByte
    • W25Q32: 32Mbit / 4MByte
    • W25Q64: 64Mbit / 8MByte
    • W25Q128: 128Mbit / 16MByte
    • W25Q256: 256Mbit / 32MByte

字库存储:如果是少量的可以使用库函数导入使用,如果需要大量的可以添加点阵进行显示。

固件程序:使用外挂设备进行

时钟频率:160/320MHz,本质上都是80MHz,只是一次性发送/接收一个字节和

一次性发送/接收两个字节/四个字节的区别。效率高了频率也高了,但本质还是80MHz。

W25Q256:24位地址最多可存储16MHz(2^24/1024/1024)的数据,32MHz的存不下。

分为3字节地址模式和4字节地址模式,3字节模式下,只能读写前16MB的数据。要想读取到所有的存储单元,可以进入4字节地址的模式 。

W25Q64实物图

3.2硬件电路(引脚说明)

硬件电路(引脚说明)

1号引脚/CS:有个斜杆表示低电平有效

3号引脚WP(write rotect):写保护,配合内部的寄存器配置。写保护低电平有效,高电平无效

7号引脚HOLED:数据保持,低电平有效。

I O 0 / 1 / 2 / 3 IO_{0/1/2/3} IO0/1/2/3: 普通的SPI模式不用关注括号里的数据,使用双重SPI,DI和DO变成IO0/1,使用四重SPI,WP和HOLED为IO2/3。

3.3框图

W25Q64框图

可读取状态寄存器的busy位置是否为1,判断是否在搬砖(工作)

重点部分:

  1. flash的空间划分,划分为块、扇区和页
  2. SPI控制逻辑,就是整个芯片的管理员,执行指令、读取数据都靠它
  3. 状态寄存器,忙状态,写使能、写保护等功能和它有关
  4. 256字节的页缓存,它会对一次性写入的数据量,产生限制
3.4手册重要点

状态寄存器1:

  1. BUSY:当设备正在执行页编程。页编程就是写入数据,扇区擦除、块擦除、整片擦除、或者写状态寄存器指令时,BUGY位置1.在这期间,设备会忽略进一步的指令,除了读状态寄存器和擦除挂起指令。当编程、擦除、写状态寄存器指令结束后,BUGY清零来指示设备准备好了。
  2. Write Enable Latch(WEL):使能锁存位WEL,在执行完写使能指令后,WLE置1,代表芯片可以进行写入操作,当设备写失能时,WL位清0。一是,上电后芯片默认写失能;二是,在执行完这些指令之后(包括,我们发送了失能指令,页编程、扇区擦除等等,WEL会=0),表明,当我们先写使能,再执行写入数据操作后,不需要再手动写入失能,也说明每个操作前都需要手动使能。

4.Flash操作注意事项

写入操作时:

  • 写入操作时:写入操作前,必须先进行写使能
  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除,擦除后,所有数据位变为1
  • 擦除必须按最小擦除单元进行
  • 连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖
  • 写入写入操作结束后,芯片进入忙状态,不响应新的读写操作

读取操作时:

  • 直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

5.软件SPI读取W25Q64(实操)

5.1接线图

软件SPI读取W25Q64

5.2程序整体框架

  1. 建立一个MySPI模块,包含通信引脚封装,初始化,以及SPI通信的3个拼图(起始、终止和交换一个字节),通信层内容
  2. 建立一个W25Q64的硬件驱动层,基于SPI层建立一个W25Q64模块,在这个模块里,调用底层SPI的拼图来拼接各种指令和功能的完整时序,比如写失能、擦除、页编程、读数据等等
  3. 主函数,调用驱动层的函数完成想要实现的功能

5.3代部分

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
#include "OLED.h"
//#include "OLED_Font.h"
#include "W25Q64.h"


uint8_t MID;
uint16_t DID;

uint8_t ArrayWrite[] = {0x01, 0x02, 0x03, 0x04};	//定义要写入数据的测试数组
uint8_t ArrayRead[4];								//定义要读取数据的测试数组

int main(void){
	
		/*模块初始化*/
	OLED_Init();						//OLED初始化
	W25Q64_Init();						//W25Q64初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "MID:   DID:");
	OLED_ShowString(2, 1, "W:");
	OLED_ShowString(3, 1, "R:");

	/*显示ID号*/
	W25Q64_ReadID(&MID, &DID);			//获取W25Q64的ID号
	OLED_ShowHexNum(1, 5, MID, 2);		//显示MID
	OLED_ShowHexNum(1, 12, DID, 4);		//显示DID	
	
	W25Q64_SectorErase(0x000000);		//扇区擦除
	W25Q64_PageProgram(0x000000,ArrayWrite,4);//将写入数据的测试数组写入到W25Q64中
	
	W25Q64_ReadData(0x000000, ArrayRead, 4);		//读取刚写入的测试数据到读取数据的测试数组中
	
	/*显示数据*/
	OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);		//显示写入数据的测试数组
	OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);
	OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);
	OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);
	
	OLED_ShowHexNum(3, 3, ArrayRead[0], 2);			//显示读取数据的测试数组
	OLED_ShowHexNum(3, 6, ArrayRead[1], 2);
	OLED_ShowHexNum(3, 9, ArrayRead[2], 2);
	OLED_ShowHexNum(3, 12, ArrayRead[3], 2);
	while(1){
		
	}
}

MySPI.c

#include "stm32f10x.h"                  // Device header

//引脚配置层

//配置SS电平,PA4设置
void MySPI_W_SS(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}

//写SCK电平,PA5设置
void MySPI_W_SCK(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}

//MOSI电平,PA7设置
void MySPI_W_MOSI(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}

//MISO电平,PA6接收
uint8_t MySPI_R_MISO()
{
	return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}

//SPI初始化
void MySPI_Init()
{	
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//GPIO初始化
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//设置默认电平
	MySPI_W_SS(1);
	MySPI_W_SCK(0);
}

//SPI起始
void MySPI_Start(void)
{
	MySPI_W_SS(0);
}

//SPI终止
void MySPI_Stop(void)
{
	MySPI_W_SS(1);
}

//SPI交换传输一个字节,使用SPI模式0
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
	uint8_t i,ByteReceive = 0x00;
	
	for(i = 0;i<8;i++)
	{
		MySPI_W_MOSI(!!(ByteSend & (0x80 >> i)));
		MySPI_W_SCK(1);
		if(MySPI_R_MISO()){
			ByteReceive |= (0x80 >> i);
		}
		MySPI_W_SCK(0);
	}
	return ByteReceive;
}

W25Q64.c

#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
#include "W25Q64_lns.h"

//初始化W25Q64

void W25Q64_Init(void)
{
	MySPI_Init();
}

//MPU6050读取ID号
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID)
{
	MySPI_Start();
	MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	*MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	*DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	*DID <<= 8;
	*DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	MySPI_Stop();
}

//写使能
void W25Q64_WriteEnable(void)
{
	MySPI_Start();								//SPI起始
	MySPI_SwapByte(W25Q64_WRITE_ENABLE);		//交换发送写使能的指令
	MySPI_Stop();								//SPI终止
}


//等待忙
void W25Q64_WaitBusy(void)
{
	uint32_t Timerout;
	MySPI_Start();
	MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);
	Timerout = 100000;
	while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01)==0x01)
	{
		Timerout --;
		if(Timerout == 0)
		{
			break;		//超时跳出等待
		}
	}
	MySPI_Stop();
}

//W25Q64页编程
void W25Q64_PageProgram(uint32_t Address,uint8_t *DataArray,uint16_t Count)
{
	uint16_t i;
	
	W25Q64_WriteEnable();					//写使能
	
	MySPI_Start();
	MySPI_SwapByte(W25Q64_PAGE_PROGRAM);	//交换发送页编程的指令
	MySPI_SwapByte(Address >> 16);			//交换发送地址23~16位
	MySPI_SwapByte(Address >> 8);			//交换发送地址
	MySPI_SwapByte(Address);				//交换发送地址7~0位
	for(i = 0;i<Count;i++)					//循环Count
	{
		MySPI_SwapByte(DataArray[i]);
	}
	MySPI_Stop();							//SPI停止
	
	W25Q64_WaitBusy();
	
}

//扇区擦除
void W25Q64_SectorErase(uint32_t Address)
{
	W25Q64_WriteEnable();						//写使能
	
	MySPI_Start();								//SPI起始
	MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);	//交换发送扇区擦除的指令
	MySPI_SwapByte(Address >> 16);				//交换发送地址23~16位
	MySPI_SwapByte(Address >> 8);				//交换发送地址15~8位
	MySPI_SwapByte(Address);					//交换发送地址7~0位
	MySPI_Stop();								//SPI终止
	
	W25Q64_WaitBusy();							//等待忙
}

5.4总结

5.4.1核心步骤

软件 SPI 实现 W25Q64 读写的核心步骤

  1. SPI 协议初始化
    • 配置 GPIO(SCK、MOSI、MISO、CS)
    • 设置 SPI 模式(W25Q64 常用模式 0模式 3
    • 定义位操作函数(如SCK_HIGH()MOSI_WRITE(bit)
  2. W25Q64 操作流程
    • 片选使能(CS 拉低)
    • 发送命令(如0x03= 读数据、0x20= 扇区擦除)
    • 发送 24 位地址(按高、中、低字节顺序)
    • 数据传输(读 / 写数据)
    • 片选失能(CS 拉高)
  3. 关键注意事项
    • 写操作前必须使能:每次写 / 擦除前需发送WRITE_ENABLE(0x06)命令
    • 擦除单位:最小擦除单位为4KB 扇区(SECTOR_ERASE),地址需按 4KB 对齐
    • 状态检查:写 / 擦除操作后需读取状态寄存器(READ_STATUS_REG1(0x05)),等待BUSY=0
5.4.2重点总结

关键总结

  1. 通信流程:CS 拉低 → 发命令 → 发地址 → 读写数据 → CS 拉高
  2. 时序严格:软件 SPI 需精确控制 SCK 高低电平延时(根据 MCU 速度调整)
  3. 擦除限制:擦除前需确保地址对齐(如 4KB 倍数),且每次擦除耗时约 40ms
  4. 状态检测:所有写 / 擦除操作后必须等待BUSY=0才能继续后续操作
5.4.3手写部分

在获取完芯片ID之后测试一下

地址自动自增到,上一位地址的后面

项**

  • 写操作前必须使能:每次写 / 擦除前需发送WRITE_ENABLE(0x06)命令
  • 擦除单位:最小擦除单位为4KB 扇区(SECTOR_ERASE),地址需按 4KB 对齐
  • 状态检查:写 / 擦除操作后需读取状态寄存器(READ_STATUS_REG1(0x05)),等待BUSY=0
5.4.2重点总结

关键总结

  1. 通信流程:CS 拉低 → 发命令 → 发地址 → 读写数据 → CS 拉高
  2. 时序严格:软件 SPI 需精确控制 SCK 高低电平延时(根据 MCU 速度调整)
  3. 擦除限制:擦除前需确保地址对齐(如 4KB 倍数),且每次擦除耗时约 40ms
  4. 状态检测:所有写 / 擦除操作后必须等待BUSY=0才能继续后续操作
5.4.3手写部分

在获取完芯片ID之后测试一下

地址自动自增到,上一位地址的后面

不擦除的话:读出的数据 = 原始数据&写入的数据

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

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

相关文章

JavaWeb:前后端分离开发-部门管理

今日内容 前后端分离开发 准备工作 页面布局 整体布局-头部布局 Container 布局容器 左侧布局 资料\04. 基础文件\layout/index.vue <script setup lang"ts"></script><template><div class"common-layout"><el-containe…

字节开源FlowGram:AI时代可视化工作流新利器

字节终于开源“扣子”同款引擎了&#xff01;FlowGram&#xff1a;AI 时代的可视化工作流利器 字节FlowGram创新性地融合图神经网络与多模态交互技术&#xff0c;构建了支持动态拓扑重构的可视化流程引擎。该系统通过引入 f ( G ) ( V ′ &#xff0c; E ′ ) f(\mathcal{G})…

(LeetCode 每日一题)3403. 从盒子中找出字典序最大的字符串 I (贪心+枚举)

题目&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 题目&#xff1a;贪心枚举字符串&#xff0c;时间复杂度0(n)。 最优解的长度一定是在[1,n-numFriends]之间。 字符串在前缀都相同的情况下&#xff0c;长度越长越大。 C版本&#xff1a; class Solution { public:st…

GPIO的内部结构与功能解析

一、GPIO总体结构 总体构成 1.APB2(外设总线) APB2总线是微控制器内部连接CPU与外设&#xff08;如GPIO&#xff09;的总线&#xff0c;负责CPU对GPIO寄存器的读写访问&#xff0c;支持低速外设通信 2.寄存器 控制GPIO的配置&#xff08;输入/输出模式、上拉/下拉等&#x…

php7+mysql5.6单用户中医处方管理系统V1.0

php7mysql5.6中医处方管理系统说明文档 一、系统简介 ----------- 本系统是一款专为中医诊所设计的处方管理系统&#xff0c;基于PHPMySQL开发&#xff0c;不依赖第三方框架&#xff0c;采用原生HTML5CSS3AJAX技术&#xff0c;适配手机和电脑访问。 系统支持药品管理、处方开…

智慧物流园区整体解决方案

该智慧物流园区整体解决方案借助云计算、物联网、ICT 等技术,从咨询规划阶段介入,整合供应链上下游资源,实现物流自动化、信息化与智能化。方案涵盖智慧仓储管理(如自动化立体仓储系统、温湿度监控)、智慧物流(运输管理系统 TMS、GPS 监控)、智慧车辆管理(定位、调度、…

【会员专享数据】1960—2023年我国省市县三级逐年降水量数据(Shp/Excel格式)

之前我们分享过1960-2023年我国0.1分辨率的逐日、逐月、逐年降水栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;是研究者Jinlong Hu与Chiyuan Miao分享在Zenodo平台上的数据&#xff0c;很多小伙伴拿到数据后反馈栅格数据不太方便使用&#xff0c;问我…

OpenCV C++ 心形雨动画

❤️ OpenCV C 心形雨动画 ❤️ 本文将引导你使用 C 和 OpenCV 库创建一个可爱的心形雨动画。在这个动画中&#xff0c;心形会从屏幕顶部的随机位置落下&#xff0c;模拟下雨的效果。使用opencv定制自己的专属背景 目录 简介先决条件核心概念实现步骤 创建项目定义心形结构…

Fullstack 面试复习笔记:Java 基础语法 / 核心特性体系化总结

Fullstack 面试复习笔记&#xff1a;Java 基础语法 / 核心特性体系化总结 上一篇笔记&#xff1a;Fullstack 面试复习笔记&#xff1a;操作系统 / 网络 / HTTP / 设计模式梳理 目前上来说&#xff0c;这个系列的笔记本质上来说&#xff0c;是对不理解的知识点进行的一个梳理&…

安卓Compose实现鱼骨加载中效果

安卓Compose实现鱼骨加载中效果 文章目录 安卓Compose实现鱼骨加载中效果背景与简介适用场景Compose骨架屏与传统View实现对比Shimmer动画原理简介常见问题与优化建议参考资料 本文首发地址 https://h89.cn/archives/404.html 背景与简介 在移动应用开发中&#xff0c;加载中占…

【使用JAVA调用deepseek】实现自能回复

在Spring Boot系统中接入DeepSeek服务&#xff0c;并将其提供给用户使用&#xff0c;通常需要以下步骤&#xff1a; 一、准备工作 &#xff08;1&#xff09;注册DeepSeek开发者账号 访问DeepSeek官网&#xff0c;注册并创建应用&#xff0c;获取API Key。 API文档&#xff1…

【Linux系列】rsync命令详解与实践

博客目录 高效文件同步的艺术&#xff1a;rsync 命令详解与实践rsync 命令解析rsync 的核心优势1. 增量传输&#xff1a;效率的革命2. 归档模式(-a)&#xff1a;保留文件所有属性3. 人性化输出(-h)与进度显示(--progress) 实际应用场景1. 文件备份与版本管理2. 跨设备同步3. 大…

Windows系统工具:WinToolsPlus 之 SQL Server Suspect/质疑/置疑/可疑/单用户等 修复

数据库在数据库列表状态是 Suspect/质疑/置疑/可疑/单用户等 非正常状态时&#xff0c; 使用WinToolsPlus 数据库页签 先设置 数据源 &#xff0c; 选择 需要清理日志的数据库&#xff0c; 点击 Suspect/质疑/置疑/可疑/单用户 按钮即可进修复。 修复过程会有数据库服务停止和启…

C++——智能指针 unique_ptr

unique_ptr的实现原理&#xff1a;简单粗暴的防拷贝 目录 一、使用C11中的新用法unique_ptr 二、使用c11模拟实现 三、使用c98特性实现 四、模拟实现unique_ptr 五、发现问题 一、使用C11中的新用法unique_ptr 由于限制了拷贝以及赋值 导致缺陷&#xff1a;unique_ptr管理…

【Python训练营打卡】day43 @浙大疏锦行

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 我选择的是music_instruments 链接&#xff1a;Musical Instruments (kaggle.com) #导包 import torch import torch.nn as…

1-【源码剖析】kafka核心概念

从今天开始开始在csdn上记录学习的笔记&#xff0c;主要包括以下几个方面&#xff1a; kafkaflinkdoris 本系列笔记主要记录Kafka学习相关的内容。在进行kafka源码学习之前&#xff0c;先介绍一下Kafka的核心概念。 消息 消息是kafka中最基本的数据单元&#xff0c;由key和…

思科设备网络实验

一、 总体拓扑图 图 1 总体拓扑图 二、 IP地址规划 表格 1 接口地址规划 设备名称 接口/VLAN IP 功能 PC0 VLAN580 10.80.1.1 访问外网 PC1 VLAN581 10.80.2.1 访问外网 PC2 Fa0 20.80.1.100 端口镜像监控流量 PC3 VLAN585 10.80.6.1 远程登陆多层交换机0…

AWS之数据分析

目录 数据分析产品对比 1. Amazon Athena 3. AWS Lake Formation 4. AWS Glue 5. Amazon OpenSearch Service 6. Amazon Kinesis Data Analytics 7. Amazon Redshift 8.Amazon Redshift Spectrum 搜索服务对比 核心功能与定位对比 适用场景 关键差异总结 注意事项 …

C# Onnx 动漫人物头部检测

目录 效果 模型信息 项目 代码 下载 参考 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-10-19T12:32:20.920471 description&#xff1a;Ultralytics best model trained on /root/datasets/yolo/anime_head_detection/data.yaml au…

【Ragflow】24.Ragflow-plus开发日志:增加分词逻辑,修复关键词检索失效问题

概述 在RagflowPlus v0.3.0 版本推出之后&#xff0c;反馈比较多的问题是&#xff1a;检索时&#xff0c;召回块显著变少了。 如上图所示&#xff0c;进行检索测试时&#xff0c;关键词相似度得分为0&#xff0c;导致混合相似度(加权相加得到)也被大幅拉低&#xff0c;低于设定…