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.pswp.cn/pingmian/79839.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79839.shtml
英文地址,請注明出處:http://en.pswp.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…