在了解完I2C通信后,不免会接触到到SPI通信。而一开始,可能会觉得两者好似没什么区别。为什么要学SPI呢,I2C和SPI有什么区别呢。为此我详细展开说说。

1.什么是 SPI?

SPI,全称 Serial Peripheral Interface,中文翻译为串行外设接口,是一种 主从式、同步、全双工 的串行通信协议。

三个关键词:
主从式:一个主机控制多个从设备(主发起,从响应)

同步式:数据传输由时钟信号(SCK)控制同步

全双工:可以边发送边接收,MOSI/MISO 两条独立数据线

2.SPI 的 4 根基本信号线结构

名称主机作用方向描述
SCK主机 → 从机同步时钟线,主机输出时钟,控制数据采样节奏
MOSI主机 → 从机主机输出、从机输入,主机发数据给从机
MISO从机 → 主机从机输出、主机输入,从机回传数据给主机
CS主机 → 从机片选信号(Chip Select),低电平有效,用来告诉从机“你被选中通信了”

注意:

SCK、MOSI、CS 都是主机控制输出;

MISO 是主机读取输入;

SPI 是一种基于边沿的协议 —— 数据变化和数据采样都是“在时钟跳变沿发生”。

3.SPI 是怎么工作的?(核心机制)

接下来我来对比 SPI 四种模式(Mode 0~3)的行为差异,包括:

CPOL(时钟空闲电平)

CPHA(数据采样边沿)

MOSI 数据什么时候改变

从机什么时候采样数据

这四种模式是 SPI 协议中最核心也最容易混淆的部分。我现在彻底讲明白它们的逻辑区别、时序差异、电平行为和通信节奏。

CPOL 与 CPHA 是什么含义?

CPOL:决定 SCK 在“空闲状态”的电平(即不传数据时 SCK 是高还是低)

CPOL = 0 → 空闲时 SCK = 低电平

CPOL = 1 → 空闲时 SCK = 高电平

CPHA:决定 在哪一个边沿采样数据

CPHA = 0 → 第一个边沿采样

CPHA = 1 → 第二个边沿采样

注意:这里是边沿,不是具体到上升沿还是下降沿,第一个边沿可能是上升沿也可能是下降沿。

第一个边沿 = 从空闲态开始的第一个跳变(比如 CPOL=0,SCK 从 0→1 是第一个边沿)

模式CPOLCPHASCK 空闲状态采样边沿传输边沿(MOSI 改变时刻)
Mode 000低电平上升沿下降沿
Mode 101低电平下降沿上升沿
Mode 210高电平下降沿上升沿
Mode 311高电平上升沿下降沿

我以发送一个字节数据(0xA5 = 10100101)为例,分析 SPI 每一位是如何传输的。

Step by Step 时序过程( SPI Mode 0 )

通信准备阶段:
主机将 CS 拉低,激活目标从机(W25Q64)

数据准备完毕,等待时钟同步

第一位传输(发送 bit 7:1)

主机将 MOSI 设置为 1

主机将 SCK 从低拉高(上升沿)

从机在上升沿采样 MOSI 上的值(记录 bit7=1)

主机将 SCK 拉低,完成本位传输

第二位传输(bit6 = 0)

主机将 MOSI=0

SCK 上升沿

从机采样 0

SCK 下降沿结束

重复 8 次后,完整发送 1 字节

发送完后,主机将 CS 拉高,表示结束通信

若是读取数据,主机会在每一位 SCK 上升沿读 MISO 上的电平

SPI Mode 1(CPOL = 0,CPHA = 1)

空闲时 SCK 为低,采样在下降沿,数据改变在上升沿

通信准备阶段:
主机将 CS 拉低,激活目标从机(W25Q64)

SCK 处于空闲低电平(CPOL = 0)

数据准备完毕,等待时钟同步

第一位传输(发送 bit7 = 1)

主机将 SCK 拉高(上升沿)

主机将 MOSI 设置为 1

主机将 SCK 拉低(下降沿)

从机在 下降沿采样 MOSI 上的值(记录 bit7 = 1)

第二位传输(bit6 = 0)

主机将 SCK 拉高

主机将 MOSI 设置为 0

主机将 SCK 拉低

从机在下降沿采样 0

重复 8 次后,完整发送 1 字节

主机将 CS 拉高,表示通信结束

若是读取数据:
主机会在 每一位的 SCK 下降沿 读取 MISO 上的电平

 SPI Mode 2(CPOL = 1,CPHA = 0)

空闲时 SCK 为高,采样在下降沿,数据改变在上升沿

通信准备阶段:
主机将 CS 拉低,激活目标从机

SCK 初始为高电平(CPOL = 1)

数据准备完毕,等待同步

第一位传输(bit7 = 1)

主机将 MOSI 设置为 1

主机将 SCK 从高拉低(下降沿)

从机在 下降沿采样 MOSI = 1

主机将 SCK 拉高(恢复空闲)

第二位传输(bit6 = 0)

主机将 MOSI = 0

主机将 SCK 拉低

从机采样 0

主机将 SCK 拉高

重复 8 次后,完整发送 1 字节

主机将 CS 拉高,结束通信

若是读取数据:
主机会在 每一位 SCK 下降沿 读取 MISO 电平

SPI Mode 3(CPOL = 1,CPHA = 1)

空闲时 SCK 为高,采样在上升沿**,数据改变在下降沿

通信准备阶段:
主机将 CS 拉低,激活从机

SCK 初始为高电平(CPOL = 1)

数据准备完毕,等待同步

第一位传输(bit7 = 1)

主机将 SCK 拉低

主机将 MOSI 设置为 1

主机将 SCK 从低拉高(上升沿)

从机在 上升沿采样 MOSI = 1

第二位传输(bit6 = 0)

主机将 SCK 拉低

主机将 MOSI 设置为 0

主机将 SCK 拉高

从机采样 0

重复 8 次后,完整发送 1 字节

主机将 CS 拉高,结束通信

若是读取数据:
主机会在 每一位 SCK 上升沿 读取 MISO 电平

W25Q64 是什么?

W25Q64 是一款 64M-bit(8MB)SPI NOR Flash 存储芯片,常用于存储配置文件、图片、数据日志等。它支持:

SPI Mode 0/3 接口

支持标准读、页写、扇区擦除等

支持写保护、掉电保护

多种容量(如 Q32、Q64、Q128)

W25Q64 内部结构概览

参数数值
总容量64Mbit = 8MB
页大小(Page)256 字节
扇区大小(Sector)4KB(16 页)
块大小(Block)64KB
地址范围0x000000 ~ 0x7FFFFF

写数据前必须先擦除所在页或扇区!否则写入无效。写数据前必须先擦除所在页或扇区!否则写入无效。

W25Q64 使用的 SPI 协议模式

默认使用 SPI Mode 0(CPOL = 0,CPHA = 0)

通信速率支持高达 80MHz(我们软件模拟约几十 KHz)

通信格式:主机发送 命令 + 地址 + 数据,从机响应结果或接收写入

4.举一个SPI读写W25Q64(软件)例子

从 STM32F103 使用 GPIO 模拟 SPI 信号,实现:

初始化 GPIO

与 W25Q64 通信(读ID、擦除扇区、写数据、读数据)

OLED 显示验证数据读写是否成功

通信的整体逻辑步骤(功能流程)

初始化 SPI 引脚(MySPI_Init)

启动 SPI 通信(CS 拉低,MySPI_Start)

发送命令(如读 ID,擦除、写数据)

可选:写入地址或数据内容

读取或写入数据

结束通信(CS 拉高,MySPI_Stop)

在 OLED 上显示通信结果

第一阶段:软件 SPI 的本质与引脚配置

SPI 是什么?
SPI 是一种同步串行通信协议,使用 4 根信号线:

CS:片选(低电平有效)

SCK:时钟,由主机控制

MOSI:主出从入,主机发给从机

MISO:主入从出,从机回应主机

在 Mode 0 模式下(CPOL=0,CPHA=0):

SCK 空闲为低电平

在 SCK 上升沿采样输入数据(MISO)

MOSI 数据必须在 SCK 上升沿前准备好

软件模拟 SPI 的基本操作函数
模拟 SPI 片选信号 CS(/SS)
void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}

使用 PA4 模拟 SPI 的 CS(Chip Select)信号线

BitValue = 0 表示选中从机(W25Q64)

BitValue = 1 表示释放从机

W25Q64 是在 CS 低电平有效 时才响应 SPI 命令。这个函数用于 SPI 通信的开始与结束。

模拟时钟线 SCK
void MySPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}

使用 PA5 模拟 SPI 的时钟线 SCK(Serial Clock)

SPI 模式 0 规定:空闲时为低电平,在 上升沿采样

 模拟 MOSI 输出
uint8_t MySPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}

使用 PA7 作为 MOSI(主出从入)

STM32 控制这根线向 W25Q64 发送数据位(高位先发)

 引脚初始化:MySPI_Init引脚初始化: 

模拟读取 MISO(主入从出)
void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}

使用 PA6 作为 MISO,从 W25Q64 读取回来的每一位数据就在这里被读取。

读取的是从机在时钟上升沿送出的位电平。

// 1. 打开 GPIOA 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 2. 配置 MOSI(PA7)、SCK(PA5)、CS(PA4)为推挽输出
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);// 3. 配置 MISO(PA6)为上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);// 4. 初始状态:SS = 1 表示未选中,SCK = 0 表示时钟空闲
MySPI_W_SS(1);
MySPI_W_SCK(0);

推挽能拉高/拉低,速度快,适合 SPI 

SPI 通信控制函数
void MySPI_Start(void)
{MySPI_W_SS(0);   // 选中从机(CS 拉低)
}
void MySPI_Stop(void)
{MySPI_W_SS(1);   // 释放从机(CS 拉高)
}

第二阶段:模拟传输一个字节的过程(MySPI_SwapByte)

实现原理
SPI 每传输 1 个字节(8 位):

每一位数据在 MOSI 上输出(主机发)

在 SCK 上升沿让从机采样(主出)

同时主机也在上升沿读取 MISO(主入)

uint8_t MySPI_SwapByte(uint8_t ByteSend)
{uint8_t i, ByteReceive = 0x00;for (i = 0; i < 8; i++){// 第 i 位:先将 MOSI 输出(最高位先)MySPI_W_MOSI(ByteSend & (0x80 >> i));  // 将第 i 位送到 MOSIMySPI_W_SCK(1); // SCK 拉高(上升沿)// 在上升沿采样 MISO 线,主机读取从机的回应位if (MySPI_R_MISO() == 1) ByteReceive |= (0x80 >> i);MySPI_W_SCK(0); // SCK 拉低,准备下一位}return ByteReceive;
}

初始化变量:i 为循环索引;ByteReceive 用来存储收到的数据。 

例如 ByteSend = 0b10100001

第一次发送 bit7:ByteSend & 0x80 = 0x80

输出对应位电平到 MOSI

SPI Mode 0:从机在 SCK 上升沿采样数据

主机此时也应从 MISO 线上采样数据

若当前位为高电平,则置 ByteReceive 的对应位为 1

第三阶段:JEDEC ID 的读取过程(读取芯片型号)

第三阶段:JEDEC ID 的读取过程(读取芯片型号)

void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{MySPI_Start();                  // CS = 0,激活 FlashMySPI_SwapByte(0x9F);           // 发送 JEDEC ID 指令*MID = MySPI_SwapByte(0x00);    // 接收厂商 ID(通常为 0xEF)*DID = MySPI_SwapByte(0x00);    // 高位 Device ID(如 0x40)*DID <<= 8;*DID |= MySPI_SwapByte(0x00);   // 低位 Device ID(如 0x17)MySPI_Stop();                   // CS = 1,结束通信}

 每个字节都通过 MySPI_SwapByte() 传输,从机 MISO 返回对应 ID 信息。

第四阶段:擦除操作(扇区擦除)

写使能
void W25Q64_WriteEnable(void)
{MySPI_Start();MySPI_SwapByte(W25Q64_WRITE_ENABLE); // 0x06MySPI_Stop();
}

 所有写操作前必须执行该命令。否则写入失败。

等待芯片空闲
void W25Q64_WaitBusy(void)
{uint32_t Timeout;MySPI_Start();MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1); // 0x05,读取状态寄存器Timeout = 100000;while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01) // bit0=WIP=1表示忙{Timeout --;if (Timeout == 0) break;}MySPI_Stop();
}

为什么要擦除?
W25Q64 的 NOR Flash 写入特性:

不能直接改写为 0 → 1

必须先将 1 全部清零(擦除为 0xFF),才能写入

void W25Q64_SectorErase(uint32_t Address)
{W25Q64_WriteEnable();          // 必须先写使能(WEL=1)MySPI_Start();                 // CS = 0MySPI_SwapByte(0x20);          // 发送擦除指令:Sector EraseMySPI_SwapByte(addr >> 16);    // 地址高8位MySPI_SwapByte(addr >> 8);     // 地址中8位MySPI_SwapByte(addr);          // 地址低8位MySPI_Stop();                  // CS = 1W25Q64_WaitBusy();             // 等待擦除完成(最多100ms)}

地址不需要对齐 0x000;芯片内部按地址所在扇区处理(每 4KB 为一个)

第五阶段:写入数据(页写)

写前必须:
写使能(0x06)

地址不要跨页(每页 256 字节)

void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{W25Q64_WriteEnable();               // 打开写使能(WEL=1)MySPI_Start();                      // 开始通信MySPI_SwapByte(0x02);               // Page Program 指令MySPI_SwapByte(addr >> 16);         // 地址高8位MySPI_SwapByte(addr >> 8);          // 地址中8位MySPI_SwapByte(addr);               // 地址低8位for (i = 0; i < Count; i++){MySPI_SwapByte(DataArray[i]);   // 发送要写入的数据(MOSI)}MySPI_Stop();                       // 结束通信W25Q64_WaitBusy();                  // 等待写入完成}

第六阶段:读取数据(Read Data)

void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{MySPI_Start();MySPI_SwapByte(0x03);                // Read Data 指令MySPI_SwapByte(addr >> 16);          // 地址高8位MySPI_SwapByte(addr >> 8);           // 中8位MySPI_SwapByte(addr);                // 低8位for (i = 0; i < Count; i++){DataArray[i] = MySPI_SwapByte(0x00); // 每读取一个字节,发一个 dummy byte}MySPI_Stop();}

 主机在 每个 SCK 上升沿读取 MISO,从机按地址返回数据。

 5.指令函数

#ifndef __W25Q64_INS_H
#define __W25Q64_INS_H#define W25Q64_WRITE_ENABLE							0x06
#define W25Q64_WRITE_DISABLE						0x04
#define W25Q64_READ_STATUS_REGISTER_1				0x05
#define W25Q64_READ_STATUS_REGISTER_2				0x35
#define W25Q64_WRITE_STATUS_REGISTER				0x01
#define W25Q64_PAGE_PROGRAM							0x02
#define W25Q64_QUAD_PAGE_PROGRAM					0x32
#define W25Q64_BLOCK_ERASE_64KB						0xD8
#define W25Q64_BLOCK_ERASE_32KB						0x52
#define W25Q64_SECTOR_ERASE_4KB						0x20
#define W25Q64_CHIP_ERASE							0xC7
#define W25Q64_ERASE_SUSPEND						0x75
#define W25Q64_ERASE_RESUME							0x7A
#define W25Q64_POWER_DOWN							0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE				0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET			0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID		0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID				0x90
#define W25Q64_READ_UNIQUE_ID						0x4B
#define W25Q64_JEDEC_ID								0x9F
#define W25Q64_READ_DATA							0x03
#define W25Q64_FAST_READ							0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT				0x3B
#define W25Q64_FAST_READ_DUAL_IO					0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT				0x6B
#define W25Q64_FAST_READ_QUAD_IO					0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO				0xE3#define W25Q64_DUMMY_BYTE							0xFF#endif
类别宏定义指令码用途说明
 写控制W25Q64_WRITE_ENABLE0x06使能写操作(写/擦前必须执行)
W25Q64_WRITE_DISABLE0x04禁止写操作,防止误写
 状态寄存器W25Q64_READ_STATUS_REGISTER_10x05读取状态寄存器1(BUSY/写使能位)
W25Q64_READ_STATUS_REGISTER_20x35读取状态寄存器2(包含QE位)
W25Q64_WRITE_STATUS_REGISTER0x01同时写SR1 和 SR2(共2字节)
写入操作W25Q64_PAGE_PROGRAM0x02页编程(最多256字节)
W25Q64_QUAD_PAGE_PROGRAM0x32四线页编程(用于Quad SPI)
 擦除操作W25Q64_SECTOR_ERASE_4KB0x20擦除一个 4KB 扇区
W25Q64_BLOCK_ERASE_32KB0x52擦除一个 32KB 块
W25Q64_BLOCK_ERASE_64KB0xD8擦除一个 64KB 块
W25Q64_CHIP_ERASE0xC7整片擦除(耗时较久)
W25Q64_ERASE_SUSPEND0x75暂停擦除操作(用于多任务)
W25Q64_ERASE_RESUME0x7A恢复擦除操作
电源管理W25Q64_POWER_DOWN0xB9进入低功耗待机模式
W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID0xAB唤醒 + 读取设备ID
模式控制W25Q64_HIGH_PERFORMANCE_MODE0xA3启用高性能模式(某些版本支持)
W25Q64_CONTINUOUS_READ_MODE_RESET0xFF重置连续读模式
识别IDW25Q64_MANUFACTURER_DEVICE_ID0x90读取制造商 + 设备ID(需发送地址)
W25Q64_READ_UNIQUE_ID0x4B读取唯一芯片ID(64-bit)
W25Q64_JEDEC_ID0x9FJEDEC 标准ID(1字节厂商 + 2字节设备)
读取数据W25Q64_READ_DATA0x03标准读取(低速,最兼容)
W25Q64_FAST_READ0x0B快速读取(需发送 Dummy Byte)
W25Q64_FAST_READ_DUAL_OUTPUT0x3B双线输出快速读
W25Q64_FAST_READ_DUAL_IO0xBB双线输入输出快速读
W25Q64_FAST_READ_QUAD_OUTPUT0x6B四线输出快速读
W25Q64_FAST_READ_QUAD_IO0xEB四线输入输出快速读
W25Q64_OCTAL_WORD_READ_QUAD_IO0xE3八线 32-bit 快速读取(部分芯片支持)
占位字节W25Q64_DUMMY_BYTE0xFF常用于读取时“填充”MOSI

6.main函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.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();W25Q64_Init();OLED_ShowString(1, 1, "MID:   DID:");OLED_ShowString(2, 1, "W:");OLED_ShowString(3, 1, "R:");W25Q64_ReadID(&MID, &DID);OLED_ShowHexNum(1, 5, MID, 2);OLED_ShowHexNum(1, 12, DID, 4);W25Q64_SectorErase(0x000000);W25Q64_PageProgram(0x000000, ArrayWrite, 4);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){}
}

擦除第一个扇区(地址 0x000000 起始的 4KB)

NOR Flash 写入前必须擦除,否则无法从 0 改写为 1!(擦除后,所有数据位变为1)

7.SPI通信与I2C区别

对比项SPI(Serial Peripheral Interface)I²C(Inter-Integrated Circuit)
通信方式全双工,主从同步通信半双工,主从同步通信
信号线数量通常需要 4 根线:MISO, MOSI, SCLK, CS(每个从机单独 CS)只需 2 根线:SCL(时钟), SDA(数据)
通信速率较高,可达几十 Mbps较低,一般为 100kHz、400kHz,最多几 Mbps
引脚数量多(每个从机需独立 CS 引脚)少(多个从机共用总线)
总线架构一主多从,但每个从机需要独立片选一主多从,多个从机可共享 2 根线
地址机制无地址,主机用 CS 选中具体从机有 7 位或 10 位设备地址
传输控制主机控制时钟(SCLK)与片选主机控制时钟(SCL),通过地址访问从机
数据方向MOSI、MISO 分别用于写入和读取(全双工SDA 单线收发数据(半双工
硬件成本较高(线多,占用 GPIO 多)较低(线少,占用 GPIO 少)
软件协议复杂度简单,无握手或仲裁较复杂,有起始/停止位、ACK/NACK、仲裁机制等
常见应用场景Flash、SD 卡、屏幕、W25Q64 等高速外设EEPROM、RTC、传感器、OLED、MPU6050 等低速外设

具体外设举例 

外设使用通信协议原因简述
W25Q64SPI高速读写需求,SPI 支持页写、块擦除等
MPU6050I²C内置 I²C 接口,低速传感器,节省引脚
OLED (SSD1306)I²C 或 SPI小数据量,I²C 节省引脚,SPI 提高速度
SD 卡SPI大容量文件操作,SPI 高速全双工性能优越

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

子词分词器(Byte Pair Encoding + WordPiece)

参考文章&#xff1a;子词分词器BPE和WordPiece理解_wordpeice-CSDN博客 子词分词器BPE和WordPiece理解_wordpeice-CSDN博客 WordPiece 和 BPE 的区别-CSDN博客 点互信息&#xff08;PMI&#xff09;和正点互信息&#xff08;PPMI&#xff09;-CSDN博客 https://zhuanlan.z…

阿里招AI产品运营

AI产品运营&#xff08;岗位信息已经过jobleap.cn授权&#xff0c;可在csdn发布&#xff09;灵犀互娱 广州收录时间&#xff1a; 2025年08月05日职位描述负责AI技术在游戏行业的应用与落地&#xff0c;专注于海外市场的运营中台建设&#xff1b; 将结合AI技术与游戏行业特点&a…

Git 分支迁移完整指南(结合分支图分析)

基于分支图的当前状态分析 分支图关键信息解读​分支结构​&#xff1a; #mermaid-svg-gc9SPnwlbrM2FzHf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-gc9SPnwlbrM2FzHf .error-icon{fill:#552222;}#mermaid-svg-…

小程序省市级联组件使用

背景。uni-data-picker组件用起来不方便。调整后级联效果欠佳&#xff0c;会关闭弹窗需要重新选择。解决方案。让cursor使用uniapp 原生组件生成懒加载省市级联 <template><view class"picker-cascader"><view class"cascader-label">&l…

Java技术栈/面试题合集(8)-Redis篇

场景 Java入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/140870227 通过对面试题进行系统的复习可以对Java体系的知识点进行查漏补缺。 注: 博客: 霸道流氓气质-CSDN博…

川翔云电脑:引领开启算力无边界时代

一、何为云电脑&#xff1f;重新定义“主机”概念 云电脑将传统本地计算机的核心硬件资源&#xff08;CPU、GPU、内存、硬盘等&#xff09;集中部署于远程高性能数据中心&#xff0c;通过网络技术将虚拟桌面实时传输到您的任意访问设备上。 ​​如同将高配主机装入云端&#…

tc 介绍

目录 1.背景 2. tc介绍 3. tc 丢包 1.背景 需要使用tc 构造丢包场景&#xff0c;注意tc 丢包不能确定丢弃的是否是payload 数据包&#xff0c;有可能丢弃 ack 包。 2. tc介绍 1. 无法正常使用 [rootpool-100-1-1-18 /]# [rootpool-100-1-1-18 /]# tc qdisc add dev swif…

LabVIEW注册表操作

​本文围绕LabVIEW中操作Windows 注册表的 4 个 VI 展开&#xff0c;介绍其功能、使用场景等并对比&#xff0c;助力工程师高效运用注册表交互功能。各 VI 功能说明&#xff08;一&#xff09;Write the Key功能&#xff1a;创建新注册表键&#xff0c;设置其值&#xff0c;随后…

阿里云部署若依后,浏览器能正常访问,但是apifox和小程序访问后报错链接被重置

项目场景&#xff1a;阿里云部署若依后浏览器能正常通过https访问,但是在apifox和小程序调用接口的时候生报错E问题描述apifox报错&#xff1a;curl报错&#xff1a;通过curl可以清楚的看到通过域名是能准确的访问到IP地址的&#xff0c;说明这个DNS是没有问题的&#xff0c;但…

升级 Elasticsearch 到新的 AWS Java SDK

作者&#xff1a;来自 Elastic David Turner, Dianna Hohensee Elasticsearch 使用官方的 AWS Java SDK 集成了某些 Amazon Web Services (AWS) 功能。这些集成最早在近 10 年前发布的 Elasticsearch 2.0 版本中引入。 最近&#xff0c;AWS 宣布 Elasticsearch 过去十年使用的…

从0到1学习微服务项目黑马头条day01-《APP端登录功能实现》

个人主页&#xff1a;VON文章所属专栏&#xff1a;黑马头条个人唯一微信&#xff1a;微信 有一起学习微服务的小伙伴可以加作者微信&#xff1a;单击即可添加 目录 一、前言 二、项目概述 1、技术栈 2、项目引入 三、改造项目 1、创建heima-leadnews-user 2、创建实体…

Renesas Electronics RZ/V2N 评估套件

简介Renesas Electronics RZ/V2N评估套件采用RZ/V2N中档嵌入式AI微处理器 (MPU) 为嵌入式人工智能 (AI) 应用提供全面的开发平台。该评估套件包括两块板&#xff1a;主板 (RTK0EF0186C02000BJ)&#xff0c;紧凑的153mm x 100mm外形尺寸和RTK0EF0168B00000BJ扩展板。其核心是RZ/…

使用PHP与Apache实现服务器端文件管理

引言 作为前端开发者&#xff0c;你可能经常需要与服务器文件系统交互。本文将详细介绍如何通过PHP配合Apache实现服务器端文件管理功能。即使你没有任何PHP经验&#xff0c;也能按照本教程实现完整解决方案&#xff01; 系统准备 PHP下载与安装 访问PHP官网下载页面 选择与…

在Word和WPS文字中如何输入汉字的偏旁部首

如何在Word和WPS文字中输入偏旁部首&#xff1f;许多输入法会把常见的偏旁部首直接放到词库&#xff0c;对于词库中没有的可以试试这个方法&#xff1a;先输入一个有这个偏旁部首的字&#xff0c;尽量简单一点的&#xff0c;然后选中这个字插入-符号-其他符号。滚动到这个偏旁部…

day44 力扣1143.最长公共子序列 力扣1035.不相交的线 力扣53. 最大子序和 力扣392.判断子序列

最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&…

应用7:用小白量化智能体金融模块做一个股票选股工具

应用7&#xff1a;用小白量化智能体金融模块做一个股票选股工具 【小白量化智能体】包含有丰富的金融模块。可以让智能体写各种金融量化工具。 我用让小白量化智能体写一个股票选股工具。 我们给【小白量化智能体】一个程序生成话术。 帮我写一个 选股 的应用程序&#xff0c;要…

Qt Frameless Widget跨平台无边框窗口

Qt开发的窗口程序&#xff0c;它的标题栏样式是无法修改的&#xff0c;这个是系统来控制&#xff0c;程序可以调整标题&#xff0c;图标等&#xff0c;但是各个系统可能表现不一致&#xff0c;比如说标题&#xff0c;window10下在标题栏最左边&#xff0c;而UOS则在中间&#x…

使用 IntelliJ IDEA + Spring JdbcTemplate 操作 MySQL 指南

使用 IntelliJ IDEA Spring JdbcTemplate 操作 MySQL 完全指南 一、开发环境搭建&#xff08;基于 IDEA&#xff09; 1. 创建 Spring Boot 项目 打开 IDEA → New Project → Spring Initializr选择&#xff1a; Project SDK: Java 17依赖项&#xff1a;Spring Web, Spring…

从愤怒的小鸟来看Unity武器拖尾的特效优化

目录 前言 素材下载 介绍 官方文档 不添加拖尾的效果 添加拖尾 代码控制拖尾生成 拖尾排序问题 效果 修改拖尾高度和存活时间 效果 待机时无拖尾 效果 参考 前言 在游戏开发过程中&#xff0c;我们经常需要为武器添加拖尾特效&#xff0c;效果如下所示 Unity 自…

Web开发模式 前端渲染 后端渲染 身份认证

Web 开发模式 # 目前主流的Web 开发模式 两种 一、基于 服务器端渲染 的传统 Web开发模式 二、基于 前后端分离 的新型 Web开发模式# 服务端渲染的优缺点# 优点&#xff1a;1. 前端耗时少因为服务端负责动态生成 HTML内容&#xff0c;浏览器&#xff08;包括手…