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

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路

需要系统性的看一下W25Q256芯片手册 

2、设置RCC,选择高速外部时钟HSE,时钟设置为180MHz

3、配置SPI

 

4、生成工程配置

 

5、相关代码

#define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256#define W25Q256_WriteEnable 0x06    // 写使能指令
#define W25Q256_WriteDisable 0x04   // 写屏蔽指令
#define W25Q256_ReadStatusReg 0x05  // 读取状态寄存器1
#define W25Q256_WriteStatusReg 0x01 // 写入状态寄存器1
//#define W25Q256_ReadData 0x03       // 3字节模式读取数据指令
#define W25Q256_ReadData 0x13       // 4字节模式读取数据指令
#define W25Q256_FastReadData 0x0B   //
#define W25Q256_FastReadDual 0x3B
#define W25Q256_PageProgram 0x02 // 页写入指令
#define W25Q256_BlockErase 0xD8
#define W25Q256_SectorErase 0x20
#define W25Q256_ChipErase 0xC7
#define W25Q256_PowerDown 0xB9
#define W25Q256_ReleasePowerDown 0xAB
#define W25Q256_DeviceID 0xAB
#define W25Q256_ManufactDeviceID 0x90
#define W25Q256_JedecDeviceID 0x9F
#define W25Q256_Enter4ByteMode 0xB7 // 4字节地址模式指令
#define W25Q256_ReadStatusRegister3 0x15
#define W25Q256_WriteStatusRegister3 0x11   //写状态寄存器3指令
#define WIP_Flag 0x01
#define Dummy_Byte 0xFF#define FLASH_WriteAddress 0x00000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorToErase FLASH_WriteAddress/* 获取缓冲区的长度 */
#define TxBufferSize1 (countof(TxBuffer1) - 1)
#define RxBufferSize1 (countof(TxBuffer1) - 1)
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize (countof(Tx_Buffer) - 1)#define FLASH_WriteAddress 0x00000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorToErase FLASH_WriteAddress/* 发送缓冲区初始化 */
extern uint8_t ReadBuff[4096];
extern uint8_t WriteBuff[4096];

/*** @brief   拉低片选线* @param   无* @retval  无*/
void SPI_FLASH_NSS_LOW(void)
{HAL_GPIO_WritePin(SPI5_NSS_GPIO_Port, SPI5_NSS_Pin, GPIO_PIN_RESET);
}/*** @brief   拉高片选线* @param   无* @retval  无*/
void SPI_FLASH_NSS_HIGH(void)
{HAL_GPIO_WritePin(SPI5_NSS_GPIO_Port, SPI5_NSS_Pin, GPIO_PIN_SET);
}/*** @brief   获取 FLASH ID* @param   无* @retval  FLASH ID*/
uint32_t SPI_FLASH_ReadID(void)
{uint32_t temp = 0;uint32_t temp0 = 0;uint32_t temp1 = 0;uint32_t temp2 = 0;// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送获取W25Q256芯片ID指令SPI_FLASH_SendByte(W25Q256_JedecDeviceID);// 接收数据temp0 = SPI_FLASH_ReadByte();temp1 = SPI_FLASH_ReadByte();temp2 = SPI_FLASH_ReadByte();// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();temp = temp0 << 16 | temp1 << 8 | temp2;return temp;
}/*** @brief   发送一个字节* @param   无* @retval  无*/
void SPI_FLASH_SendByte(uint8_t ch)
{HAL_SPI_Transmit(&hspi5, &ch, 1, 500);
}/*** @brief   发送n个字节* @param   pData:发送数据首地址* @param   data_number:发送数据个数(以字节为单位)* @retval  无*/
void SPI_FLASH_SendnByte(uint8_t *pData, uint32_t data_number)
{HAL_SPI_Transmit(&hspi5, pData, data_number, 500);
}/*** @brief   接收一个字节* @param   无* @retval  接收的数据*/
uint8_t SPI_FLASH_ReadByte(void)
{uint8_t rxData = 0;HAL_SPI_Receive(&hspi5, &rxData, 1, 500);return rxData;
}/*** @brief   接收n个字节* @param   pData:接收数据首地址* @param   data_number:接收数据个数(以字节为单位)* @retval  无*/
void SPI_FLASH_ReadnByte(uint8_t *pData, uint32_t data_number)
{HAL_SPI_Receive(&hspi5, pData, data_number, 500);
}/*** @brief   使能写命令* @param   无* @param   无* @retval  无*/
void SPI_FLASH_WriteEnable(void)
{// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送写使能指令SPI_FLASH_SendByte(W25Q256_WriteEnable);// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();
}/*** @brief   等待写入、擦除等操作完成* @param   无* @param   无* @retval  无*/
void SPI_FLASH_WaitForWriteEnd(void)
{uint8_t FLASH_Status = 0;// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送写状态寄存器1指令SPI_FLASH_SendByte(W25Q256_ReadStatusReg);do{// 获取写状态寄存器1的值并做判断。0:空闲、1:忙碌FLASH_Status = SPI_FLASH_ReadByte();} while (SET == (FLASH_Status & WIP_Flag));// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();
}/*** @brief   擦除扇区* @param   SectorAddr:擦除扇区首地址* @retval  无*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{// uint8_t ADDR[4] = {0x00,0x00,0x00,0x00};//  使能写命令SPI_FLASH_WriteEnable();// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送擦除扇区命令SPI_FLASH_SendByte(W25Q256_SectorErase);// 发送擦除地址24 ~ 31bitSPI_FLASH_SendByte((SectorAddr & 0xFF000000) >> 24);// 发送擦除地址16 ~ 23bitSPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);// 发送擦除地址8 ~ 15bitSPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);// 发送擦除地址0 ~ 7bitSPI_FLASH_SendByte(SectorAddr & 0xFF);// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();// HAL_Delay(3000);// 等待擦除操作结束SPI_FLASH_WaitForOperaEnd();
}/*** @brief   配置4字节模式* @param   无* @retval  无*/
void SPI_FLASH_FOUR_MODE(void)
{uint8_t temp = 0;// 使能写命令SPI_FLASH_WriteEnable();// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送写状态寄存器3命令SPI_FLASH_SendByte(W25Q256_WriteStatusRegister3);// 发送要写的数据SPI_FLASH_SendByte(0x02);// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送读状态寄存器3命令SPI_FLASH_SendByte(W25Q256_ReadStatusRegister3);// 读取数据temp = SPI_FLASH_ReadByte();// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();if (1 == (0x02 & temp)){// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送配置四字节模式指令SPI_FLASH_SendByte(W25Q256_Enter4ByteMode);// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();}SPI_FLASH_WaitForOperaEnd();
}/*** @brief   对 FLASH 按页写入数据,调用本函数写入数据前需要先擦除扇区* @param   pBuffer:要写入数据的指针* @param   WriteAddr:写入数据地址* @param   NumByteToWrite:写入数据长度。必须小于等于SPI_FLASH_PerWritePageSize* @retval  无*/
void SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{// 使能写命令SPI_FLASH_WriteEnable();// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送页写入指令SPI_FLASH_SendByte(W25Q256_PageProgram);// 发送写入地址[24,31]bitSPI_FLASH_SendByte((WriteAddr & 0xFF000000) >> 24);// 发送写入地址[16,23]bitSPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);// 发送写入地址[8,15]bitSPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);// 发送写入地址[0,7]bitSPI_FLASH_SendByte(WriteAddr & 0xFF);if (NumByteToWrite > SPI_FLASH_PerWritePageSize){NumByteToWrite = SPI_FLASH_PerWritePageSize;printf("256\r\n");}for (int i = 0; i < NumByteToWrite; i++){SPI_FLASH_SendByte(pBuffer[i]);}// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();
}/*** @brief   FALSH不定量数据写入函数,调用本函数写入数据前需要先擦除扇区* @param   pBuffer:要写入数据的指针* @param   WriteAddr:写入数据地址* @param   NumByteToWrite:写入数据长度* @retval  无*/
void SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage = 0;uint8_t NumOfSingle = 0;uint8_t Addr = 0;uint8_t count = 0;uint8_t temp = 0;/*mod 运算求余,若 writeAddr 是 SPI_FLASH_PageSize 整数倍,运算结果 Addr 值为0*/Addr = WriteAddr % SPI_FLASH_PageSize;/* 差 count 个数据值,刚好可以对齐到页地址 */count = SPI_FLASH_PageSize - Addr;/* 计算出要写多少整数页 */NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;/*mod 运算求余,计算出剩余不满一页的字节数 */NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;/* Addr=0, 则 WriteAddr 刚好按页对齐 aligned */if (0 == Addr){/*NumByteToWrite < SPI_FLASH_PageSize*/if (0 == NumOfPage){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}else{/* 先把整数页都写了 */for (int i = 0; i < NumOfPage; i++){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr += SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}/* 若有多余的不满一页的数据,把它写完 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}else /* 若地址与 SPI_FLASH_PageSize 不对齐 */{/*NumByteToWrite < SPI_FLASH_PageSize*/if (0 == NumOfPage){/* 当前页剩余的 count 个位置比 NumOfSingle 小,写不完 */if (NumOfSingle > count){temp = NumOfSingle - count;/* 先写满当前页 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr += count;pBuffer += count;/* 再写剩余的数据 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}else /* 当前页剩余的 count 个位置能写完 NumOfSingle 个数据 */{SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}else /*NumByteToWrite > SPI_FLASH_PageSize*/{/*先把距离页地址的count个数据减去,计算需要写的页数和NumOfSingle,然后写数据时先把原来减去的count个数据写入,写满当前页*//*再写剩余数据,即计算好的NumOfPage和NumOfSingle*/NumByteToWrite -= count;NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr += count;pBuffer += count;/* 把整数页都写了 */for (int i = 0; i < NumOfPage; i++){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr += SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}if (0 != NumOfSingle){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}}
}/*** @brief   读取FLASH数据* @param   pBuffer:存储读出数据的指针* @param   WriteAddr:读取地址* @param   NumByteToRead:读取数据长度* @retval  无*/
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送读取数据指令SPI_FLASH_SendByte(W25Q256_ReadData);// 发送读取地址[24,31]bitSPI_FLASH_SendByte((ReadAddr & 0xFF000000) >> 24);// 发送读取地址[16,23]bitSPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);// 发送读取地址[8,15]bitSPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);// 发送读取地址[0,7]bitSPI_FLASH_SendByte(ReadAddr & 0xFF);// 读取数据for (int i = 0; i < NumByteToRead; i++){// 读取一个字节数据pBuffer[i] = SPI_FLASH_ReadByte();}// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();SPI_FLASH_WaitForOperaEnd(); // 等待操作完成
}/*** @brief   等待写入、擦除等操作结束* @param   none* @param   none* @param   none* @retval  none*/
void SPI_FLASH_WaitForOperaEnd(void)
{uint8_t FLASH_Status = 0;// 拉低片选线,开始通信SPI_FLASH_NSS_LOW();// 发送读状态寄存器1指令SPI_FLASH_SendByte(W25Q256_ReadStatusReg);do{// 接收读取状态寄存器1寄存器内容FLASH_Status = SPI_FLASH_ReadByte();} while (SET == (FLASH_Status & WIP_Flag));// 拉高片选线,结束通信SPI_FLASH_NSS_HIGH();
}
int main(void)
{/* USER CODE BEGIN 1 *//* 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_SPI5_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */// 进入4字节地址模式SPI_FLASH_FOUR_MODE();printf("W25Q256 SPI readwrite test!!!\r\n");device_ID = SPI_FLASH_ReadID();printf("device_ID = 0x%x\r\n", device_ID);SPI_FLASH_SectorErase(0x00); // 擦除扇区数据// 读取擦除后的数据SPI_FLASH_BufferRead(ReadBuff, 0x00, 4096);printf("*****************读取擦出后的数据*****************\r\n");for (int i = 0; i < 4096; i++){printf("ReadBuff[%d] = 0x%02x\t", i, ReadBuff[i]);if (0 == (i + 1) % 8 && (i + 1) >= 8){printf("\r\n");}}for (int i = 0; i < 256; i++){WriteBuff[i] = i;}SPI_FLASH_BufferWrite(WriteBuff, 0xFF, 256);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成// 读数据SPI_FLASH_BufferRead(ReadBuff, 0xFF, 256);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成printf("*****************读取写入后的数据*****************\r\n");for (int i = 0; i < 256; i++){printf("ReadBuff[%d] = 0x%02x\t", i, ReadBuff[i]);if (0 == (i + 1) % 8 && (i + 1) >= 8){printf("\r\n");}}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */LED_TIME();}/* USER CODE END 3 */
}

6、实验现象

 

相关文章:

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…...

C++11异步与通信之 packaged_task

概念简介 packaged_task 用于包装可调用目标(Callable)为一个对象,如lambda&#xff0c;普通函数&#xff0c;小括号重载等&#xff0c;用于异步调用。 其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中&#xff0c;和promise类似。 将函数的调用与函数返…...

磁盘的管理

一、磁盘的分区 查看磁盘 lsblk fdisk -l 2、分区 没有e扩展&#xff0c;则都是主分区&#xff0c;已经有三个主分区了&#xff0c;剩下的全设置为扩展 查看分区结果&#xff1a; 二、格式化 三、挂载...

数据结构:完全二叉树的性质

完全二叉树的性质&#xff1a; 具有 n n n个结点的完全二叉树的深度为 [ l o g 2 n ] 1 ( [ x ] 表示不大于 x 的最大整数 ) [log_2n]1([x]表示不大于x的最大整数) [log2​n]1([x]表示不大于x的最大整数) 对于任意一个结点 &#xff08; 1 < i < n &#xff09; &…...

【数据结构】‘双向链表’冲冲冲

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

Linux 编译CEF源码详细记录

Linux CEF&#xff08;Chromium Embedded Framework&#xff09;源码下载编译 背景 由于CEF默认的二进制分发包不支持音视频播放&#xff0c;需要自行编译源码&#xff0c;将ffmpeg开关打开才能支持。这里介绍的是Linux平台下的CEF源码下载编译过程。 Windows平台参考&#…...

LeetCode 2810. Faulty Keyboard【模拟,双端队列,字符串】简单

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

两个数组的交集-C语言/Java

描述 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序。&#xff08;1 < nums1.length, nums2.length < 1000&#xff0c;0 < nums1[i], nums2[i] < 1000&#xff09; 示例1 输入…...

Arduino+esp32学习笔记

学习目标&#xff1a; 使用Arduino配置好蓝牙或者wifi模块 学习使用python配置好蓝牙或者wifi模块 学习内容&#xff08;笔记&#xff09;&#xff1a; 一、 Arduino语法基础 Arduino语法是基于C的语法,C又是c基础上增加了面向对象思想等进阶语言。那就只记录没见过的。 单多…...

计算机网络-专业术语

计算机网络-专业术语 实体 实体:任何可发送或接收信息的硬件或软件进程 对等实体:收发双方相同层次中的实体 协议 控制两个对等实体进行逻辑通信的规则的集合 协议三要素 语法 定义所交换的信息的格式 是用户数据与控制信息的结构和格式 语义 定义收发双方所需要完成的操作…...

E. Maximum Monogonosity

You are given an array aa of length nn and an array bb of length nn. The cost of a segment [l,r][l,r], 1≤l≤r≤n1≤l≤r≤n, is defined as |bl−ar||br−al||bl−ar||br−al|. Recall that two segments [l1,r1][l1,r1], 1≤l1≤r1≤n1≤l1≤r1≤n, and [l2,r2][l2,…...

已解决Excel file format cannot be determined, you must specify an engine manually

问题 我使用以下语句时出现错误 data pd.read_excel(temp_inputc.csv, headerNone)出现错误&#xff1a; Excel file format cannot be determined, you must specify an engine manually有很多人说添加engine&#xff0c;但接下来会出现这个错误&#xff1a; File is not…...

Centos yum命令大全

1.使用YUM查找软件包 $ yum search python 2.列出所有可安装的软件包 $ yum list | grep python 3.列出所有可更新的软件包 $ yum list updates 4.列出所有已安装的软件包 $ yum list installed | grep python...

内网横向移动—ARP攻击图片捕捉数据劫持DNS劫持

内网横向移动—ARP攻击&图片捕捉&数据劫持&DNS劫持 1. ARP1.1. APR介绍1.1.1. ARP工作原理1.1.2. APR欺骗工作原理 1.2. 环境准备1.3. 适用场景 2. ARP断网攻击演示2.1. 使用kali进行演示2.1.1. nmap判断存活2.1.2. 安装工具2.1.3. 攻击Windows 10虚拟机2.1.3.1. 查…...

react之Hooks的介绍、useState与useEffect副作用的使用

react之Hooks的介绍、useState与useEffect副作用的使用 一、Hooks的基本介绍二、useState的使用2.1 简单使用2.2 数组结构简化2.3 状态的读取和修改2.3 组件的更新过程 三、useEffect的使用3.1 副作用介绍3.2 基本使用3.3 依赖3.4 不要对依赖项撒谎3.5 依赖项可以是空数组3.6 清…...

django——创建 Django 项目和 APP

2.创建 Django 项目和 APP 命令&#xff1a; 创建Django项目 django-admin startproject name 创建子应用 python manager.py startapp name 2.1 创建工程 在使用Flask框架时&#xff0c;项目工程目录的组织与创建是需要我们自己手动创建完成的。 在django中&#xff0c;…...

== 和 equals 的对比 [面试题]

和 equals 的对比[面试题] 文章目录 和 equals 的对比[面试题]1. 和 equals 简介2. Object 类中 equals() 源码3. String 类中 equals() 源码4. Integer 类中 equals() 源码5. 如何重写 equals 方法 1. 和 equals 简介 是一个比较运算符 &#xff1a;既可以判断基本数据类型…...

SpringBoot集成Redis及Redis使用方法

目录 应用背景 Redis简介 更新问题 一&#xff1a;环境配置 1.1: 在pom.xml文件中添加依赖 1.2&#xff1a;配置SpringBoot核心配置文件application.properties 二&#xff1a;在Config文件夹中创建RedisConfig配置文件类 2.1&#xff1a;RedisTemplate中的几个角色&am…...

Redis可以用作数据库吗?它的适用场景是什么?

是的&#xff0c;Redis可以用作数据库。虽然Redis通常被认为是一个内存数据库&#xff08;in-memory database&#xff09;&#xff0c;但它也可以通过持久化机制将数据保存在磁盘上&#xff0c;以便在重启后恢复数据。 Redis的适用场景包括但不限于以下几个方面&#xff1a; …...

@Param详解

文章目录 背景什么是ParamParam的使用方法使用方法&#xff1a;遇到的问题及因Param解决了什么问题使用与不使用对比 Param是如何进行映射的总结 背景 最近在开发过程中&#xff0c;在写mapper接口是在参数前加了Param注解&#xff0c;但是在运行的时候就会报错&#xff0c;说…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...