STM32基础教程——软件SPI

目录

前言

技术实现 

接线图 

代码实现 

技术要点 

引脚操作

SPI初始化

SPI起始信号

SPI终止信号

SPI字节交换

宏替换命令 

W25Q64写使能 

忙等待

读取设备ID号和制造商ID

页写入

数据读取

实验结果

问题记录 


前言

SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信接口规范,主要用于短距离通信,广泛应用于嵌入式系统中。它使一个主设备能够与一个或多个从设备进行通信。SPI使用四条主要信号线:MOSI(主机输出/从机输入)、MISO(主机输入/从机输出)、SCK(串行时钟)和SS/CS(从选/片选)来实现数据的双向传输。这种接口方式支持全双工通信,具有传输速率高、延迟低的优点,但相比其他一些接口协议,使用的信号线较多。SPI常用于连接传感器、存储器、ADC(模数转换器)等外围设备。

SPI硬件电路

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

W25Q64是华邦公司(Winbond)推出的一款基于SPI通信的大容量闪存产品,其存储容量为64Mb(即8MB)。该芯片支持2.7~3.6V的工作电压范围,并且具备至少10万次的擦写周期和长达20年的数据保存时间。W25Q64以其灵活性和出色的性能著称,非常适合用于存储声音、文本和数据等应用。它被组织为32768个可编程页面,每个页面包含256字节的数据。此外,W25Q64还支持多种擦除命令,包括4KB扇区擦除、32KB块擦除、64KB块擦除以及全片擦除,并且兼容标准SPI模式0和模式3,最高支持133MHz的时钟频率。通过SPI接口,W25Q64可以轻松地与各种微控制器进行集成,实现高效的数据读写操作。

W25Q64由8MB的存储容量,存储区域被划分成了128个块,每个块又被划分成了16个扇区,每个扇区又被划分成了 16个页。

W25Q64写入操作时

  •  在写入操作之前,必须先进行写使能。
  • 每个数据为只能有1改写成0,不能由0改写成1。
  • 写入数据之前必须先擦除,擦除后,所有的数据位都变为1。
  • 擦除必须以最小单元擦除(这里最小擦除单元时4kb扇区)。
  • 连续写入多个字节时最多写入一页的数据(256Byte),超过页尾的数据会回到页首覆盖写入。
  • 写入操作完成后,芯片进入忙状态,不响应新的写操作。

W25Q64读操作时:

  • 直接调取读操作时序,无需写使能,无需其他操作,没有页限制,读取操作完成后芯片不会进入忙状态,但是芯片忙状态时不能进行读操作。

技术实现 

原理图

 

接线图 

代码实现 

main.c

/**********************************************************
1.实验名称:软件SPI读写W25Q64
2.实验环境:STM32F103C8T6最小系统板
3.实验内容:使用软件模拟SPI读取W25Q64	
4.作者;abai
5.实验时间:2025-5-6
**********************************************************/
#include "stm32f10x.h"                  // Device header
#include "Delay.h"						//延时函数
#include "OLED.h"
#include "W25Q64.h"uint8_t MF;
uint16_t ID;
uint8_t SendArry[] = {0x05,0x06,0x07,0x08};
uint8_t ReceiveArry[4];int main(void)
{/*OLED初始化*/OLED_Init();W25Q64_Init();OLED_ShowString(1,1,"MF:");OLED_ShowString(2,1,"ID:");OLED_ShowString(3,1,"W:");OLED_ShowString(4,1,"R:");W25Q64_SectorErase(0x000000);												//写入数据之前必须页擦除W25Q64_PageProgram(0x000000,SendArry,4);W25Q64_ReadData(0x000000,ReceiveArry,4);W25Q64_ReadID(&MF,&ID);OLED_ShowHexNum(3,3,SendArry[0],2);OLED_ShowHexNum(3,5,SendArry[1],2);OLED_ShowHexNum(3,7,SendArry[2],2);OLED_ShowHexNum(3,9,SendArry[3],2);OLED_ShowHexNum(4,3,ReceiveArry[0],2);OLED_ShowHexNum(4,5,ReceiveArry[1],2);OLED_ShowHexNum(4,7,ReceiveArry[2],2);OLED_ShowHexNum(4,9,ReceiveArry[3],2);OLED_ShowHexNum(1,4,MF,2);OLED_ShowHexNum(2,4,ID,4);while(1){}
}

MySPI.h 

#ifndef MYSPI_H
#define MYSPI_H#include "stm32f10x.h"                  // Device headervoid MySPI_Init(void);
void MySPI_CS_W(uint8_t BitValue);
void MySPI_SCK_W(uint8_t BitValue);
void MySPI_MOSI_W(uint8_t BitValue);
uint8_t MySPI_MISO_R(void);
void MySPI_Start(void);
void MySPI_Stop(void);
uint8_t MySPI_SwapByte(uint8_t ByteValue);#endif

 MySPI.c

#include "MySPI.h"/***@brief  SPI初始化*@param  None*@retval None**/
void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_Out_PP;								//推挽输出GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_6;GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_IPU;								//上拉输入GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);//引脚初始化MySPI_CS_W(1);																//片选信号默认为高电平MySPI_SCK_W(0);																//SPI模式0,时钟信号默认为低电平}/***@brief  SPI CS控制*@param  BitValue 要写入CS的位数据*@retval None**/
void MySPI_CS_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}/***@brief  SPI SCK控制*@param  BitValue 要写入SCK的位数据*@retval None**/
void MySPI_SCK_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}/***@brief  SPI MOSI写操作*@param  BitValue 要写入MOSI的位数据*@retval None**/
void MySPI_MOSI_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}/***@brief  SPI MISO读*@param  None*@retval MISO数据线接受到的数据**/
uint8_t MySPI_MISO_R(void)
{return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}/***@brief  SPI起始信号*@param  None*@retval None**/
void MySPI_Start(void)
{MySPI_CS_W(0);																//将片选信号拉低发送起始信号
}/***@brief  SPI终止信号*@param  None*@retval None**/
void MySPI_Stop(void)
{MySPI_CS_W(1);																//将片选信号拉高发送终止信号
}/***@brief  SPI交换字节*@param  None*@retval 交换的字节**/
uint8_t MySPI_SwapByte(uint8_t ByteValue)
{//掩码操作uint8_t ByteReceive = 0x00;uint8_t i;for(i=0;i<8;i++){MySPI_MOSI_W((ByteValue<<i) & 0x80);MySPI_SCK_W(1);if(MySPI_MISO_R() == 1)ByteReceive |= (0x80>>i);MySPI_SCK_W(0);}return ByteReceive;//移位操作
//	uint8_t i;
//	for(i=0;i<8;i++)
//	{
//		MySPI_MOSI_W(ByteValue& 0x80);
//		ByteValue <<= 1;
//		MySPI_SCK_W(1);
//		if(MySPI_MISO_R() == 1)
//			ByteValue |= 0x01;
//		MySPI_SCK_W(0);
//	}
//	
//	return ByteValue;
}

W25Q64_Ins.h 

#ifndef W25Q64_INS_H
#define W25Q64_INS_H#define W25Q64_WRITEENABLE 				0x06
#define W25Q64_READSTATUSREGISTER1 		0x05
#define W25Q64_PAGEPROGRAM 				0x02
#define W25Q64_SECTORERASE4KB 			0x20
#define W25Q64_JEDECID 					0X9F
#define W25Q64_READDATA 				0x03
#define W25Q64_DUMMY_BYTE 				0xFF#endif

W25Q64.h 

#ifndef W25Q64_H
#define W25Q64_H#include "stm32f10x.h"                  // Device header
#include "MySPI.h"void W25Q64_Init(void);
void W25Q64_ReadID(uint8_t* MF, uint16_t*ID);
void W25Q64_WriteEnable(void);
void W25Q64_WaitBusy(void);
void W25Q64_PageProgram(uint32_t Address, uint8_t* DataArry, uint16_t Count);
void W25Q64_SectorErase(uint32_t Address);
void W25Q64_ReadData(uint32_t Address,uint8_t* DataArry, uint32_t Count);#endif

W25Q64.c 

#include "W25Q64.h"
#include "W25Q64_Ins.h"/***@brief  W25Q64初始化*@param  None*@retval None**/
void W25Q64_Init(void)
{MySPI_Init();
}/***@brief  W25Q64ID读取*@param  None*@retval None**/
void W25Q64_ReadID(uint8_t* MF, uint16_t*ID)
{MySPI_Start();//发送读取ID指令MySPI_SwapByte(W25Q64_JEDECID);//发送空指令交换数据*MF = MySPI_SwapByte(W25Q64_DUMMY_BYTE);													//随便发送一个数据用于与从机交换数据,一般使用0xFF或0x00*ID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*ID <<= 8;*ID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);MySPI_Stop();
}/***@brief  W25Q64ID写使能*@param  None*@retval None**/
void W25Q64_WriteEnable(void)
{MySPI_Start();//发送写使能指令MySPI_SwapByte(W25Q64_WRITEENABLE);MySPI_Stop();
}/***@brief  W25Q64ID忙等待*@param  None*@retval None**/
void W25Q64_WaitBusy(void)
{MySPI_Start();//发送读状态寄存器指令MySPI_SwapByte(W25Q64_READSTATUSREGISTER1);//等待BUSY位清零,则从设备退出忙状态while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0X01) == 0X01);MySPI_Stop();
}/***@brief  W25Q64ID页写入*@param  None*@retval None**/
void W25Q64_PageProgram(uint32_t Address, uint8_t* DataArry, uint16_t Count)
{uint16_t i;W25Q64_WriteEnable();														//写使能MySPI_Start();MySPI_SwapByte(W25Q64_PAGEPROGRAM);//发送24位地址MySPI_SwapByte(Address>>16);MySPI_SwapByte(Address>>8);MySPI_SwapByte(Address);//发送指定数量的数据for(i=0;i<Count;i++){MySPI_SwapByte(DataArry[i]);}MySPI_Stop();W25Q64_WaitBusy();															//事后等待忙状态
}/***@brief  W25Q64ID指定扇区擦除*@param  None*@retval None**/
void W25Q64_SectorErase(uint32_t Address)
{			W25Q64_WriteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_SECTORERASE4KB);//发送24位地址MySPI_SwapByte(Address>>16);MySPI_SwapByte(Address>>8);MySPI_SwapByte(Address);MySPI_Stop();W25Q64_WaitBusy();
}/***@brief  W25Q64ID读取数据*@param  None*@retval None*@note   数据接收的数量也要指定,不然无法停止数据读取操作**/
void W25Q64_ReadData(uint32_t Address,uint8_t* DataArry, uint32_t Count)
{uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READDATA);//发送24位地址MySPI_SwapByte(Address>>16);MySPI_SwapByte(Address>>8);MySPI_SwapByte(Address);for(i=0;i<Count;i++){DataArry[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop();
}

 OLED部分代码参照文章《STM32基础教程——OLED显示》

技术要点 

引脚操作

/***@brief  SPI CS控制*@param  BitValue 要写入CS的位数据*@retval None**/
void MySPI_CS_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}/***@brief  SPI SCK控制*@param  BitValue 要写入SCK的位数据*@retval None**/
void MySPI_SCK_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}/***@brief  SPI MOSI写操作*@param  BitValue 要写入MOSI的位数据*@retval None**/
void MySPI_MOSI_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}/***@brief  SPI MISO读*@param  None*@retval MISO数据线接受到的数据**/
uint8_t MySPI_MISO_R(void)
{return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}

对单个引脚的操作进行封装,用于模拟SPI引脚电平翻转或引脚电平读取。 

SPI初始化

/***@brief  SPI初始化*@param  None*@retval None**/
void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_Out_PP;								//推挽输出GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_6;GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_IPU;								//上拉输入GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);//引脚初始化MySPI_CS_W(1);																//片选信号默认为高电平MySPI_SCK_W(0);																//SPI模式0,时钟信号默认为低电平}

实验使用软件模拟SPI,PA4引脚模拟SPI的CS引脚,PA5模拟SPI的SCK引脚,PA6模拟MISO引脚,PA7模拟MOSI引脚。根据输出引脚配置为推挽输出,输入引脚配置为上拉输入的要求初始化GPIO。初始化完成后,对CS引脚和SCK引脚初始化。片选信号CS默认为高电平,表示未选中从设备。模拟SPI模式0,SCK初始默认电平为低电平。

SPI起始信号

SPI的起始时序是CS(SS)从高电平切换为低电平 。

/***@brief  SPI起始信号*@param  None*@retval None**/
void MySPI_Start(void)
{MySPI_CS_W(0);																//将片选信号拉低发送起始信号
}

SPI终止信号
 

 SPI的终止时序是CS(SS)从低电平切换为高电平 。

/***@brief  SPI终止信号*@param  None*@retval None**/
void MySPI_Stop(void)
{MySPI_CS_W(1);																//将片选信号拉高发送终止信号
}

SPI字节交换

SPI为同步全双工通信,每一次通信都会进行数据交换。

/***@brief  SPI交换字节*@param  None*@retval 交换的字节**/
uint8_t MySPI_SwapByte(uint8_t ByteValue)
{//掩码操作uint8_t ByteReceive = 0x00;uint8_t i;for(i=0;i<8;i++){MySPI_MOSI_W((ByteValue<<i) & 0x80);MySPI_SCK_W(1);if(MySPI_MISO_R() == 1)ByteReceive |= (0x80>>i);MySPI_SCK_W(0);}return ByteReceive;
}

SPI模式0下,SCK第一个边沿移入数据,所以当第一个边沿到来之前数据已经移出。 

MySPI_MOSI_W((ByteValue<<i) & 0x80);

 所以通过MOSI发送一个数据字节。然后将SCK拉高,SCK的第一个边沿将数据移入。

if(MySPI_MISO_R() == 1)ByteReceive |= (0x80>>i);

 ByteValue默认为0x00,只有当移入的数据为1时将对应位置1,为0时不执行操作。

MySPI_SCK_W(0);

 然后将SCK拉低,发生数据移出操作。

使用for循环完成一个字节的数据交换,最后将数据返回。

宏替换命令 

#ifndef W25Q64_INS_H
#define W25Q64_INS_H#define W25Q64_WRITEENABLE 				0x06
#define W25Q64_READSTATUSREGISTER1 		0x05
#define W25Q64_PAGEPROGRAM 				0x02
#define W25Q64_SECTORERASE4KB 			0x20
#define W25Q64_JEDECID 					0X9F
#define W25Q64_READDATA 				0x03
#define W25Q64_DUMMY_BYTE 				0xFF#endif

将对W25Q64操作的命令使用宏代替, 提高代码的便捷性和可读性。

W25Q64写使能 

/***@brief  W25Q64ID写使能*@param  None*@retval None**/
void W25Q64_WriteEnable(void)
{MySPI_Start();//发送写使能指令MySPI_SwapByte(W25Q64_WRITEENABLE);MySPI_Stop();
}

将写使能操作封装,方便使用。主机与从机交换数据,发送写使能命令,对从机进行写使能操作。

忙等待

/***@brief  W25Q64ID忙等待*@param  None*@retval None**/
void W25Q64_WaitBusy(void)
{MySPI_Start();//发送读状态寄存器指令MySPI_SwapByte(W25Q64_READSTATUSREGISTER1);//等待BUSY位清零,则从设备退出忙状态while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0X01) == 0X01);MySPI_Stop();
}

 发送读取状态寄存器1的命令,判断BUSY位的状态,使用while循环等待芯片退出忙状态将BUSY位清零。

读取设备ID号和制造商ID

/***@brief  W25Q64ID读取*@param  None*@retval None**/
void W25Q64_ReadID(uint8_t* MF, uint16_t*ID)
{MySPI_Start();//发送读取ID指令MySPI_SwapByte(W25Q64_JEDECID);//发送空指令交换数据*MF = MySPI_SwapByte(W25Q64_DUMMY_BYTE);													//随便发送一个数据用于与从机交换数据,一般使用0xFF或0x00*ID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*ID <<= 8;*ID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);MySPI_Stop();
}

 主机发送读取JEDEC ID的命令,从机向主机发送数据,数据格式为第一个字节为制造商ID,第二个和第三个字节为设备ID。这里使用指针进行数据操作。

页写入

/***@brief  W25Q64ID页写入*@param  None*@retval None**/
void W25Q64_PageProgram(uint32_t Address, uint8_t* DataArry, uint16_t Count)
{uint16_t i;W25Q64_WriteEnable();														//写使能MySPI_Start();MySPI_SwapByte(W25Q64_PAGEPROGRAM);//发送24位地址MySPI_SwapByte(Address>>16);MySPI_SwapByte(Address>>8);MySPI_SwapByte(Address);//发送指定数量的数据for(i=0;i<Count;i++){MySPI_SwapByte(DataArry[i]);}MySPI_Stop();W25Q64_WaitBusy();															//事后等待忙状态
}

页写入操作,先进行写使能,然后发送起始信号,发送页写入命令。然后发送24位地址,高16位为页地址,低八位为字节地址。使用for循环写入指定数量的数据,数据的数量不应超过256字节。最后发送停止信号,然后进行芯片忙等待操作(忙等待如果加在函数开始,那读取操作也要加忙等待函数调用,这样会使操作更复杂。)。所有写操作函数与本函数类似,不再赘述。

数据读取

/***@brief  W25Q64ID读取数据*@param  None*@retval None*@note   数据接收的数量也要指定,不然无法停止数据读取操作**/
void W25Q64_ReadData(uint32_t Address,uint8_t* DataArry, uint32_t Count)
{uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READDATA);//发送24位地址MySPI_SwapByte(Address>>16);MySPI_SwapByte(Address>>8);MySPI_SwapByte(Address);for(i=0;i<Count;i++){DataArry[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop();
}

数据读取操作无需写使能,无需进行其他操作。发送读数据命令,然后发送24位地址,同样高16位地址为页地址,低八位为字节地址。读取操作不受页限制。

实验结果

问题记录 

暂无

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

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

相关文章

(B题|矿山数据处理问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…

无网络环境下配置并运行 word2vec复现.py

需运行文件 # -*- coding: utf-8 -*- import torch import pandas as pd import jieba import torch import torch.nn as nn from tqdm import tqdm from torch.utils.data import DataLoader,Dataset from transformers import AutoTokenizer,AutoModeldef get_stop_word():w…

读《暗时间》有感

读《暗时间》有感 反思与笔记 这本书还是我无意中使用 ima 给我写职业规划的时候给出的&#xff0c;由于有收藏的习惯&#xff0c;我就去找了这本书。当读到第一章暗时间的时候给了我很大的冲击&#xff0c;我本身就是一个想快速读完一本书的人&#xff0c;看到东西没有深入思…

ubuntu安装Go SDK

# 下载最新版 Go 安装包&#xff08;以 1.21.5 为例&#xff09; wget https://golang.google.cn/dl/go1.21.5.linux-amd64.tar.gz # 解压到系统目录&#xff08;需要 root 权限&#xff09; sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz # 使用 Go 官方安装脚本…

FFmpeg(7.1版本)编译生成ffplay

FFmpeg在编译的时候,没有生成ffplay,怎么办? 1. 按照上一篇文章:FFmpeg(7.1版本)在Ubuntu18.04上的编译_ffmpeg-7.1-CSDN博客 在build.sh脚本里配置了ffplay 但是,实际上却没有生成ffplay,会是什么原因呢? 2. 原因是编译ffplay的时候,需要一些依赖库 sudo apt-get i…

【Python 函数】

Python 中的函数&#xff08;Function&#xff09;是可重复使用的代码块&#xff0c;用于封装特定功能并提高代码复用性。以下是函数的核心知识点&#xff1a; 一、基础语法 1. 定义函数 def greet(name):"""打印问候语""" # 文档字符串&…

7. HTML 表格基础

表格是网页开发中最基础也最实用的元素之一,尽管现代前端开发中表格布局已被 CSS 布局方案取代,但在展示结构化数据时,表格依然发挥着不可替代的作用。本文将基于提供的代码素材,系统讲解 HTML 表格的核心概念与实用技巧。 一、表格的基本结构 一个完整的 HTML 表格由以下…

极狐GitLab 命名空间的类型有哪些?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 命名空间 命名空间在极狐GitLab 中组织项目。因为每一个命名空间都是单独的&#xff0c;您可以在多个命名空间中使用相同的项…

powershell批处理——io校验

powershell批处理——io校验 在刷题时&#xff0c;时常回想&#xff0c;OJ平台是如何校验竞赛队员提交的代码的&#xff0c;OJ平台并不看代码&#xff0c;而是使用“黑盒测试”&#xff0c;用测试数据来验证。对于每题&#xff0c;都事先设定了很多组输入数据&#xff08;data…

前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制

看完本篇你将基本了解webpack!!! 目录 一、Webpack 的作用 1、基本配置结构 2、配置项详解 1. entry —— 构建入口 2. output —— 输出配置 3. mode:模式设置 4. module:模块规则 5. plugins:插件机制 6. resolve:模块解析配置(可选) 7. devServer:开发服务器…

面试算法刷题练习1(核心+acm)

3. 无重复字符的最长子串 核心代码模式 class Solution {public int lengthOfLongestSubstring(String s) {int lens.length();int []numnew int[300];int ans0;for(int i0,j0;i<len;i){num[s.charAt(i)];while(num[s.charAt(i)]>1){num[s.charAt(j)]--;j;}ansMath.max…

拉削丝锥,螺纹类加工的选择之一

在我们的日常生活中&#xff0c;螺纹连接无处不在&#xff0c;从简单的螺丝钉到复杂的机械设备&#xff0c;都离不开螺纹的精密加工。今天&#xff0c;给大家介绍一种的螺纹刀具——拉削丝锥&#xff1a; 一、拉削丝锥的工作原理 拉削丝锥&#xff0c;听起来有点陌生吧&#…

数据清洗-电商双11美妆数据分析(二)

1.接下来用seaborn包给出每个店铺各个大类以及各个小类的销量销售额 先观察销量&#xff0c;各店小类中销量最高的是相宜本草的补水类商品以及妮维雅的清洁类商品&#xff0c;这两类销量很接近。而销售额上&#xff0c;相宜本草的补水类商品比妮维雅的清洁类商品要高得多&#…

【上位机——MFC】对话框

对话框的使用 1.添加对话框资源 2.定义一个自己的对话框类(CMyDlg)&#xff0c;管理对话框资源&#xff0c;派生自CDialog或CDialogEx均可 对话框架构 #include <afxwin.h> #include "resource.h"class CMyDlg :public CDialog {DECLARE_MESSAGE_MAP() publi…

2025东三省C题深圳杯C题数学建模挑战赛数模思路代码文章教学: 分布式能源接入配电网的风险分析

完整内容请看文章最下面的推广群 数据整理与分析 表1&#xff1a;有源配电网62节点系统负荷参数 内容&#xff1a;列出了62个节点的有功负荷&#xff08;单位&#xff1a;kW&#xff09;。 特点&#xff1a; 负荷范围&#xff1a;24 kW&#xff08;节点19&#xff09;到420 …

【人工智能】边缘计算技术及应用概述

边缘计算&#xff08;Edge Computing&#xff09;是一种分布式计算范式&#xff0c;其核心思想是将数据处理、存储和计算能力从传统的云端数据中心下沉到靠近数据源的边缘设备&#xff08;如传感器、摄像头、工业设备等&#xff09;或边缘服务器。这种架构旨在减少数据传输延迟…

FAISS(Facebook AI Similarity Search)

First steps with Faiss for k-nearest neighbor search in large search spaces - Davide’s GitHub pages FAISS&#xff08;Facebook AI Similarity Search&#xff09;是由Meta&#xff08;原Facebook&#xff09;AI团队开发的高效相似性搜索库&#xff0c;主要用于处理大规…

嵌入式开发学习日志Day15

一、指针指向字符型数组 &#xff08;1&#xff09;【const】&#xff1a;在指针变量中使用时&#xff0c;无法通过该指针修改被指向的变量&#xff1b; &#xff08;2&#xff09;【const】&#xff1a;关键字&#xff0c;在C和C中&#xff0c;能加就加&#xff0c;加了一定…

现代卷积神经网络

一、网络中的网络 (NiN: Network in Network) 参考&#xff1a;Network In Network——卷积神经网络的革新 - 殷大侠 - 博客园 深度学习&#xff08;二十六&#xff09;Network In Network学习笔记-CSDN博客 ① MLPconv 层 参考&#xff1a;深度学习基础模型NIN(Network in Net…

【大模型面试每日一题】Day 11:参数高效微调方法(如LoRA、Adapter)的核心思想是什么?相比全参数微调有何优缺点?

【大模型面试每日一题】Day 11&#xff1a;参数高效微调方法&#xff08;如LoRA、Adapter&#xff09;的核心思想是什么&#xff1f;相比全参数微调有何优缺点&#xff1f; &#x1f4cc; 题目重现 &#x1f31f;&#x1f31f; 面试官&#xff1a;参数高效微调方法&#xff0…