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

STM32移植文件系统FATFS——片外SPI FLASH

一、电路连接

        主控芯片选型为:STM32F407ZGT6,SPI FLASH选型为:W25Q256JV。

        采用了两片32MB的片外SPI FLASH,电路如图所示。

        SPI FLASH与主控芯片的连接方式如表所示。

STM32F407GT6W25Q256JV
PB3SPI1_SCK
PB4SPI1_MISO
PB5SPI1_MOSI
PB7FLASH_CS1
PB8FLASH_CS2

二、SPI FLASH直接读写

        本文采用硬件SPI通信,分为四个文件,分别为:spi.c、spi.h、flash.c、flash.h。

2.1 spi.c源文件

        spi.c源文件如下,主要进行spi硬件初始化和收发函数定义。

#include "spi.h"SPI_HandleTypeDef hspi1;static u8 pRx = 0;void SPI_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_SPI1_CLK_ENABLE();GPIO_InitStructure.Pin       = SPI1_CLK | SPI1_MISO | SPI1_MOSI;GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull      = GPIO_PULLUP;GPIO_InitStructure.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStructure.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(SPI1_PORT, &GPIO_InitStructure);hspi1.Instance               = SPI1;hspi1.Init.Mode              = SPI_MODE_MASTER;hspi1.Init.Direction         = SPI_DIRECTION_2LINES;hspi1.Init.DataSize          = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity       = SPI_POLARITY_HIGH;hspi1.Init.CLKPhase          = SPI_PHASE_2EDGE;hspi1.Init.NSS               = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi1.Init.FirstBit          = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode            = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation    = SPI_CRCCALCULATION_ENABLE;hspi1.Init.CRCPolynomial     = 7;HAL_SPI_Init(&hspi1);    
}u8 SPI1_ReadWriteByte(u8 data)
{HAL_SPI_TransmitReceive(&hspi1, &data, &pRx, 1, 10);return pRx;
}

2.2 spi.h头文件       

        spi.h头文件如下,主要定义了接口

#ifndef _SPI_H_
#define _SPI_H_#include "system.h"
#include "delay.h"#define SPI1_CLK  GPIO_PIN_3
#define SPI1_MISO GPIO_PIN_4
#define SPI1_MOSI GPIO_PIN_5
#define SPI1_PORT GPIOBextern SPI_HandleTypeDef hspi1;extern void SPI_Init(void);
extern u8   SPI1_ReadWriteByte(u8 data);#endif

2.3 flash.c源文件

        flash.c源文件如下,主要进行W25Q256JV的硬件初始化和一些设置函数。

#include "flash.h"void W25Q256_Init(uint16_t selectChip)
{GPIO_InitTypeDef GPIO_InitStructure;__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStructure.Pin   = selectChip;GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull  = GPIO_PULLUP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(FLASH_PORT, &GPIO_InitStructure);FLAS_CS_DISABLE(selectChip);SPI_Init();delay_ms(1);W25Q256_4BDSet(selectChip);
}void W25Q256_4BDSet(uint16_t selectChip)
{u8 Reg3;FLAS_CS_ENABLE(selectChip);Reg3 = SPI1_ReadWriteByte(W25Q256_ReadStatusReg3);SPI1_ReadWriteByte(W25Q256_WriteEnable);SPI1_ReadWriteByte(W25Q256_WriteStatusReg3);SPI1_ReadWriteByte(Reg3 | (1<<2));FLAS_CS_DISABLE(selectChip);delay_us(3);
}u8 W25Q256_Read_SR(uint16_t selectChip, u8 Reg)
{u8 byte = 0;FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(Reg);byte = SPI1_ReadWriteByte(0xff);FLAS_CS_DISABLE(selectChip);return byte;
}void W25Q256_Write_SR(uint16_t selectChip, u8 Reg, u8 sr)
{	FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(Reg);SPI1_ReadWriteByte(sr);FLAS_CS_DISABLE(selectChip);
}void W25Q256_Write_Enable(uint16_t selectChip)
{FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_WriteEnable);FLAS_CS_DISABLE(selectChip);
}void W25Q256_Write_Disable(uint16_t selectChip)
{FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_WriteDisable);FLAS_CS_DISABLE(selectChip);
}u16 W25Q256_ReadID(uint16_t selectChip)
{u16 Temp = 0;FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_ManufactDeviceID);SPI1_ReadWriteByte(0x00);SPI1_ReadWriteByte(0x00);SPI1_ReadWriteByte(0x00);Temp |= SPI1_ReadWriteByte(0x00)<<8;  Temp |= SPI1_ReadWriteByte(0x00);	FLAS_CS_DISABLE(selectChip);return Temp;
}void W25Q256_Read(uint16_t selectChip, u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)
{ u16 i;  FLAS_CS_ENABLE(selectChip);	SPI1_ReadWriteByte(W25Q256_ReadData4BA);SPI1_ReadWriteByte((u8)((ReadAddr)>>24)); 	SPI1_ReadWriteByte((u8)((ReadAddr)>>16));     SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   SPI1_ReadWriteByte((u8)ReadAddr);   for (i = 0; i < NumByteToRead; i++){pBuffer[i] = SPI1_ReadWriteByte(0XFF);   //循环读数  }FLAS_CS_DISABLE(selectChip); 				    	      
}static void W25Q256_Write_Page(uint16_t selectChip, u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{u16 i;  W25Q256_Write_Enable(selectChip);FLAS_CS_ENABLE(selectChip);	SPI1_ReadWriteByte(W25Q256_PageProgram4BA);SPI1_ReadWriteByte((u8)((WriteAddr)>>24));SPI1_ReadWriteByte((u8)((WriteAddr)>>16));SPI1_ReadWriteByte((u8)((WriteAddr)>>8));   SPI1_ReadWriteByte((u8)WriteAddr);for(i = 0;i < NumByteToWrite; i++){SPI1_ReadWriteByte(pBuffer[i]); }FLAS_CS_DISABLE(selectChip);W25Q256_Wait_Busy(selectChip);
}static void W25Q256_Write_NoCheck(uint16_t selectChip, u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)   
{ 			 		 u16 pageremain;	   pageremain = 256 - WriteAddr % 256; // 单页剩余的字节数		 	    if(NumByteToWrite <= pageremain){pageremain = NumByteToWrite;    // 不大于256个字节}while(1){	   W25Q256_Write_Page(selectChip, pBuffer, WriteAddr, pageremain);if(NumByteToWrite == pageremain){break;}else{pBuffer   += pageremain;WriteAddr += pageremain;	NumByteToWrite -= pageremain;if(NumByteToWrite > 256){pageremain = 256;}else {pageremain = NumByteToWrite;}}}  
}u8 W25Q256_BUFFER[4096];		 
void W25Q256_Write(uint16_t selectChip, u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)   
{ u32 secpos;u16 secoff;u16 secremain;	   u16 i;    u8 *W25Q256_BUF;W25Q256_BUF = W25Q256_BUFFER;    secpos = WriteAddr/4096;//扇区地址  secoff = WriteAddr%4096;//在扇区内的偏移secremain = 4096-secoff;//扇区剩余空间大小if(NumByteToWrite <= secremain){secremain = NumByteToWrite;//不大于4096个字节}while(1) {	W25Q256_Read(selectChip, W25Q256_BUF, secpos*4096, 4096);//读出整个扇区的内容for(i = 0; i < secremain; i++)//校验数据{if(W25Q256_BUF[secoff+i] != 0XFF){break;}				}if(i < secremain) //需要擦除{W25Q256_Erase_Sector(selectChip, secpos);       //擦除这个扇区for(i = 0; i < secremain; i++)	   //复制{W25Q256_BUF[i+secoff] = pBuffer[i];	  }W25Q256_Write_NoCheck(selectChip, W25Q256_BUF, secpos*4096, 4096);//写入整个扇区  }else {W25Q256_Write_NoCheck(selectChip, pBuffer, WriteAddr, secremain);//写已经擦除了的,直接写入扇区剩余区间. }if(NumByteToWrite == secremain){break;//写入结束了}else//写入未结束{secpos++;//扇区地址增1secoff = 0;//偏移位置为0 	 pBuffer += secremain;  //指针偏移WriteAddr += secremain;//写地址偏移	   NumByteToWrite -= secremain;				//字节数递减if(NumByteToWrite > 4096){secremain=4096;	//下一个扇区还是写不完}else {secremain = NumByteToWrite;			//下一个扇区可以写完了}	 }}	 
}void W25Q256_Erase_Chip(uint16_t selectChip)   
{                                   W25Q256_Write_Enable(selectChip);W25Q256_Wait_Busy(selectChip);   FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_ChipErase);FLAS_CS_DISABLE(selectChip);W25Q256_Wait_Busy(selectChip);
}void W25Q256_Erase_Sector(uint16_t selectChip, u32 Dst_Addr)   
{  	  Dst_Addr *= 4096;W25Q256_Write_Enable(selectChip);W25Q256_Wait_Busy(selectChip);FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_SectorErase4BA);SPI1_ReadWriteByte((u8)((Dst_Addr)>>24));SPI1_ReadWriteByte((u8)((Dst_Addr)>>16));SPI1_ReadWriteByte((u8)((Dst_Addr)>>8));   SPI1_ReadWriteByte((u8)Dst_Addr);  FLAS_CS_DISABLE(selectChip);W25Q256_Wait_Busy(selectChip);
}void W25Q256_Wait_Busy(uint16_t selectChip)   
{   while((W25Q256_Read_SR(selectChip, W25Q256_ReadStatusReg1) & 0x01) == 0x01);
}void W25Q256_Power_Down(uint16_t selectChip)   
{ FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_PowerDown);FLAS_CS_DISABLE(selectChip);delay_us(3);
} void W25Q256_WAKEUP(uint16_t selectChip)   
{  FLAS_CS_ENABLE(selectChip);SPI1_ReadWriteByte(W25Q256_ReleasePowerDown);FLAS_CS_DISABLE(selectChip);delay_us(3);
}

2.4 flash.h头文件

        flash.h头文件如下:

#ifndef _FLASH_H_
#define _FLASH_H_#include "system.h"
#include "spi.h"#define FLASH1     GPIO_PIN_7
#define FLASH2     GPIO_PIN_8
#define FLASH_PORT GPIOB#define FLAS_CS_ENABLE(x)  HAL_GPIO_WritePin(FLASH_PORT, x, GPIO_PIN_RESET)
#define FLAS_CS_DISABLE(x) HAL_GPIO_WritePin(FLASH_PORT, x, GPIO_PIN_SET)// W25Q256指令集 4字节地址
#define W25Q256_WriteEnable      0x06
#define W25Q256_SRWriteEnable    0x50
#define W25Q256_WriteDisable     0x04
#define W25Q256_ReleasePowerDown 0xAB
#define W25Q256_ManufactDeviceID 0x90
#define W25Q256_JedecDeviceID	 0x9F
#define W25Q256_ReadUniqueID     0x4B
#define W25Q256_ReadData         0x03
#define W25Q256_ReadData4BA      0x13
#define W25Q256_FastReadData     0x0B
#define W25Q256_FastReadData4BA  0x0C
#define W25Q256_PageProgram		 0x02
#define W25Q256_PageProgram4BA	 0x12
#define W25Q256_SectorErase		 0x20
#define W25Q256_SectorErase4BA	 0x21
#define W25Q256_BlockErase32	 0x52
#define W25Q256_BlockErase64	 0xD8
#define W25Q256_BlockErase644BA  0xDC
#define W25Q256_ChipErase		 0xC7
#define W25Q256_ReadStatusReg1   0x05
#define W25Q256_WriteStatusReg1  0x01
#define W25Q256_ReadStatusReg2   0x35
#define W25Q256_WriteStatusReg2  0x31
#define W25Q256_ReadStatusReg3   0x15
#define W25Q256_WriteStatusReg3  0x11
#define W25Q256_ReadExtAddrReg   0xC8
#define W25Q256_WriteExtAddrReg  0xC5
#define W25Q256_ReadSfdpReg      0x5A
#define W25Q256_EraseSecReg      0x44
#define W25Q256_ProgramSecReg    0x42
#define W25Q256_ReadSecReg       0x48
#define W25Q256_GlobalBlockLock  0x7E
#define W25Q256_GlobalBlockUlock 0x98
#define W25Q256_ReadBlockLock    0x3D
#define W25Q256_IndivBlockLock   0x36
#define W25Q256_IndivBlockUlock  0x39
#define W25Q256_EraProSuspend    0x75
#define W25Q256_RraProResume     0x7A
#define W25Q256_PowerDown        0xB9
#define W25Q256_Enter4BAMode     0xB7
#define W25Q256_Exit4BAMode      0xE9
#define W25Q256_EnableReset      0x66
#define W25Q256_ResetDev         0x99extern void W25Q256_Init(uint16_t selectChip);
extern void W25Q256_4BDSet(uint16_t selectChip);
extern u8   W25Q256_Read_SR(uint16_t selectChip, u8 Reg);
extern void W25Q256_Write_SR(uint16_t selectChip, u8 Reg, u8 sr);
extern void W25Q256_Write_Enable(uint16_t selectChip);
extern void W25Q256_Write_Disable(uint16_t selectChip);
extern u16  W25Q256_ReadID(uint16_t selectChip);
extern void W25Q256_Read(uint16_t selectChip, u8* pBuffer,u32 ReadAddr,u16 NumByteToRead);
extern void W25Q256_Write(uint16_t selectChip, u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
extern void W25Q256_Erase_Chip(uint16_t selectChip);
extern void W25Q256_Erase_Sector(uint16_t selectChip, u32 Dst_Addr);
extern void W25Q256_Wait_Busy(uint16_t selectChip);
extern void W25Q256_Power_Down(uint16_t selectChip);
extern void W25Q256_WAKEUP(uint16_t selectChip);#endif

        通过这四个文件可以实现对两片flash的读写操作。

三、FATFS文件系统移植

3.1 源码下载

        源码下载地址:http://elm-chan.org/fsw/ff/00index_e.html

        下载的版本是:R0.15a

3.2 源码目录

        FATFS下载解压缩后,如图:       

        documents文件夹下存放一些帮助文档之类的,可以不用考虑,用到的时候再去百度。

        source文件夹下存放FATFS文件系统源码,包括diskio.c、diskio.h、ff.c、ff.h、ffconf.h、ffsystem.c、ffunicode.c,共四个源码和三个头文件。后续需配置只需要修改diskio.cffconf.h两个文件即可。

 3.3 源码复制到自己的工程

        ① 将FATFS源码中的七个文件复制到自己的工程文件夹中:

        ② 将源文件添加至keil工程

        ③ 添加头文件路径

        此时点击编译会报错和警告,需要对源文件的信息进行配置。

3.4 修改diskio.c

3.4.1 添加头文件

        spi.h和flash.h为第二章中的两个头文件,定义了与硬件直接交互的代码。delay.h为延时头文件。

3.4.2 定义设备驱动号

        将原来代码中的0、1、2三个硬件驱动号删掉定义自己的设备。我有两块SPI FLASH,所以定义了两个设备驱动号。

3.4.3 修改disk_status函数

        这个函数是查询设备状态的函数,我们使用flash.c中定义的W25Q256_ReadID函数读W25Q256的设备ID号,如果能正确读取,则系统状态正常。

        原来的代码是:

        修改后的代码是:

3.4.4 修改disk_initialize函数

        这个函数是对设备进行初始化的函数,在代码中调用flash.c中定义的W25Q256_Init函数对设备进行初始化。

        原来的代码是:

        修改后的代码是:

3.4.5 修改disk_read函数

        这个函数是对文件进行读的操作,直接调用flash.c中的W25Q256_Read函数即可。

        原来的代码是:

        修改后的代码是:(sector和count左移12位的原因分别:LBA_t定义的sector是扇区的逻辑地址,即0,1,2...,通过左移12位(乘4096)获得扇区的物理地址;count是读取多少个字节的内容)

3.4.6 修改disk_write函数

        这个函数是对文件进行写操作的函数,直接调用flash.c中的W25Q256_Write函数即可,在flash.c中每次写都会先擦除在写入,所以此处不需要再进行扇区擦除,如果W25Q256_Write函数中未进行擦除操作,则在此处还需进行擦除在写入,否则会写入出错。

        原来的代码是:

        修改后的代码是:

3.4.7 修改disk_ioctl函数

        这个函数是获取设备的一些硬件信息之类的,如果此处有问题可能会导致后续挂载创建文件系统失败。

        原来的代码是:

        修改后的代码是:(SPI_FLASH1和SPI_FLASH2中处理过程一样,SECTOR_SIZE是扇区大小、SECTOR_COUNT是扇区数量,W25Q256扇区大小是4096,一共有8192个扇区。此处的扇区数量必须填写,开始本人漏掉了这个,后续创建文件系统时一直返回14号错误代码,通过一点一点的打印寻找,才发现在f_mkfs函数中调用disk_ioctl查询扇区数量时一直为0导致的

3.4.8 添加get_fattime函数

        这个函数源代码中未给出,直接编译会导致报错。所以需要手动添加,此函数是为了获取文件读写时间的,如果用了RTC实时时钟可以替换这里的年月日时分秒。

3.4.9 diskio.c完整代码

        修改后的完整diskio.c文件如下:

#include "ff.h"			/* Obtains integer types */
#include "diskio.h"		/* Declarations of disk functions */
#include "spi.h"
#include "flash.h"
#include "delay.h"#define SPI_FLASH1	0
#define SPI_FLASH2	1#define PAGE_SIZE    256
#define SECTOR_SIZE  4096
#define SECTOR_COUNT 8192  DSTATUS disk_status(BYTE pdrv)
{DSTATUS stat = STA_NOINIT;switch (pdrv){case SPI_FLASH1:if (W25Q256_ReadID(FLASH1) == 0xEF18){stat &= ~STA_NOINIT;}break;case SPI_FLASH2:if (W25Q256_ReadID(FLASH2) == 0xEF18){stat &= ~STA_NOINIT;}break;}return stat;
}DSTATUS disk_initialize(BYTE pdrv)
{DSTATUS stat = STA_NOINIT;switch (pdrv){case SPI_FLASH1:W25Q256_Init(FLASH1);delay_us(200);stat = disk_status(pdrv);break;case SPI_FLASH2:W25Q256_Init(FLASH2);delay_us(200);stat = disk_status(pdrv);break;}return stat;
}// pdrv  : Physical drive nmuber to identify the drive
// buff  : Data buffer to store read data
// sector: Start sector in LBA
// count : Number of sectors to read
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
{DRESULT res = RES_PARERR;switch (pdrv) {case SPI_FLASH1:W25Q256_Read(FLASH1, buff, sector << 12, count << 12);res = RES_OK;break;case SPI_FLASH2:W25Q256_Read(FLASH2, buff, sector << 12, count << 12);res = RES_OK;break;}return res;
}#if FF_FS_READONLY == 0
// pdrv   : Physical drive nmuber to identify the drive
// buff   : Data to be written 
// sector : Start sector in LBA
// count  : Number of sectors to write
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
{DRESULT res = RES_PARERR;switch (pdrv) {case SPI_FLASH1:W25Q256_Write(FLASH1, (u8 *)buff, sector << 12, count << 12);res = RES_OK;break;case SPI_FLASH2:W25Q256_Write(FLASH2, (u8 *)buff, sector << 12, count << 12);res = RES_OK;break;}return res;
}#endif// pdrv : Physical drive nmuber
// cmd  : Control code
// buff : Buffer to send/receive control data
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{DRESULT res = RES_PARERR;switch (pdrv) {case SPI_FLASH1:switch (cmd){case CTRL_SYNC:break;case CTRL_TRIM:break;case GET_BLOCK_SIZE:break;case GET_SECTOR_SIZE:*(DWORD*)buff = SECTOR_SIZE;break;case GET_SECTOR_COUNT:*(DWORD*)buff = SECTOR_COUNT;break;default:res = RES_PARERR;break;}res = RES_OK;case SPI_FLASH2:switch (cmd){case CTRL_SYNC:break;case CTRL_TRIM:break;case GET_BLOCK_SIZE:break;case GET_SECTOR_SIZE:*(DWORD*)buff = SECTOR_SIZE;break;case GET_SECTOR_COUNT:*(DWORD*)buff = SECTOR_COUNT;break;default:res = RES_PARERR;break;}res = RES_OK;}return res;
}__weak DWORD get_fattime(void)              // 获取时间
{return 		((DWORD)(2024-1980)<<25)    // 设置年份为2024|	((DWORD)1<<21)      // 设置月份为1|	((DWORD)1<<16)      // 设置日期为1|	((DWORD)1<<11)      // 设置小时为1|	((DWORD)1<<5)       // 设置分钟为1|	((DWORD)1<<1);      // 设置秒数为1
}

3.5 修改ffconf.h

        修改宏定义FF_USE_MKFS:(作用:创建文件系统函数,定义后才能创建文件系统)

        修改宏定义FF_CODE_PAGE:(作用:文件语言,设置为简体中文)

          修改宏定义FF_VOLUMES:(作用:硬件系统数量,我这挂了两个spi flash,所以是2)

        修改宏定义FF_MIN_SS和FF_MAX_SS:(作用:配置扇区最小和最大空间,W25Q256的扇区大小是4096)

        完整的ffconf.h文件如下:

/*---------------------------------------------------------------------------/
/  Configurations of FatFs Module
/---------------------------------------------------------------------------*/#define FFCONF_DEF	5380	/* Revision ID *//*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/#define FF_FS_READONLY	0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/  Read-only configuration removes writing API functions, f_write(), f_sync(),
/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/  and optional writing functions as well. */#define FF_FS_MINIMIZE	0
/* This option defines minimization level to remove some basic API functions.
/
/   0: Basic functions are fully enabled.
/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/      are removed.
/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/   3: f_lseek() function is removed in addition to 2. */#define FF_USE_FIND		0
/* This option switches filtered directory read functions, f_findfirst() and
/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */#define FF_USE_MKFS		1
/* This option switches f_mkfs(). (0:Disable or 1:Enable) */#define FF_USE_FASTSEEK	0
/* This option switches fast seek feature. (0:Disable or 1:Enable) */#define FF_USE_EXPAND	0
/* This option switches f_expand(). (0:Disable or 1:Enable) */#define FF_USE_CHMOD	0
/* This option switches attribute control API functions, f_chmod() and f_utime().
/  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */#define FF_USE_LABEL	0
/* This option switches volume label API functions, f_getlabel() and f_setlabel().
/  (0:Disable or 1:Enable) */#define FF_USE_FORWARD	0
/* This option switches f_forward(). (0:Disable or 1:Enable) */#define FF_USE_STRFUNC	0
#define FF_PRINT_LLI	0
#define FF_PRINT_FLOAT	0
#define FF_STRF_ENCODE	3
/* FF_USE_STRFUNC switches the string API functions, f_gets(), f_putc(), f_puts()
/  and f_printf().
/
/   0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/   1: Enable without LF - CRLF conversion.
/   2: Enable with LF - CRLF conversion.
/
/  FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
/  makes f_printf() support floating point argument. These features want C99 or later.
/  When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character
/  encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/  to be read/written via those functions.
/
/   0: ANSI/OEM in current CP
/   1: Unicode in UTF-16LE
/   2: Unicode in UTF-16BE
/   3: Unicode in UTF-8
*//*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/#define FF_CODE_PAGE	936
/* This option specifies the OEM code page to be used on the target system.
/  Incorrect code page setting can cause a file open failure.
/
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
/     0 - Include all code pages above and configured by f_setcp()
*/#define FF_USE_LFN		0
#define FF_MAX_LFN		255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/   0: Disable LFN. FF_MAX_LFN has no effect.
/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.
/
/  To enable the LFN, ffunicode.c needs to be added to the project. The LFN feature
/  requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/  additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/  The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/  be in range of 12 to 255. It is recommended to be set 255 to fully support the LFN
/  specification.
/  When use stack for the working buffer, take care on stack overflow. When use heap
/  memory for the working buffer, memory management functions, ff_memalloc() and
/  ff_memfree() exemplified in ffsystem.c, need to be added to the project. */#define FF_LFN_UNICODE	0
/* This option switches the character encoding on the API when LFN is enabled.
/
/   0: ANSI/OEM in current CP (TCHAR = char)
/   1: Unicode in UTF-16 (TCHAR = WCHAR)
/   2: Unicode in UTF-8 (TCHAR = char)
/   3: Unicode in UTF-32 (TCHAR = DWORD)
/
/  Also behavior of string I/O functions will be affected by this option.
/  When LFN is not enabled, this option has no effect. */#define FF_LFN_BUF		255
#define FF_SFN_BUF		12
/* This set of options defines size of file name members in the FILINFO structure
/  which is used to read out directory items. These values should be suffcient for
/  the file names to read. The maximum possible length of the read file name depends
/  on character encoding. When LFN is not enabled, these options have no effect. */#define FF_FS_RPATH		0
/* This option configures support for relative path.
/
/   0: Disable relative path and remove related API functions.
/   1: Enable relative path. f_chdir() and f_chdrive() are available.
/   2: f_getcwd() is available in addition to 1.
*//*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/#define FF_VOLUMES		2
/* Number of volumes (logical drives) to be used. (1-10) */#define FF_STR_VOLUME_ID	0
#define FF_VOLUME_STRS		"RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/  When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/  number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/  logical drive. Number of items must not be less than FF_VOLUMES. Valid
/  characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/  compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/  not defined, a user defined volume string table is needed as:
/
/  const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/#define FF_MULTI_PARTITION	0
/* This option switches support for multiple volumes on the physical drive.
/  By default (0), each logical drive number is bound to the same physical drive
/  number and only an FAT volume found on the physical drive will be mounted.
/  When this feature is enabled (1), each logical drive number can be bound to
/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/  will be available. */#define FF_MIN_SS		4096
#define FF_MAX_SS		4096
/* This set of options configures the range of sector size to be supported. (512,
/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/  harddisk, but a larger value may be required for on-board flash memory and some
/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is
/  configured for variable sector size mode and disk_ioctl() needs to implement
/  GET_SECTOR_SIZE command. */#define FF_LBA64		0
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/  To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */#define FF_MIN_GPT		0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and 
/  f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */#define FF_USE_TRIM		0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/  To enable this feature, also CTRL_TRIM command should be implemented to
/  the disk_ioctl(). *//*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/#define FF_FS_TINY		0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/  At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/  Instead of private sector buffer eliminated from the file object, common sector
/  buffer in the filesystem object (FATFS) is used for the file data transfer. */#define FF_FS_EXFAT		0
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/  To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/  Note that enabling exFAT discards ANSI C (C89) compatibility. */#define FF_FS_NORTC		0
#define FF_NORTC_MON	11
#define FF_NORTC_MDAY	1
#define FF_NORTC_YEAR	2024
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/  an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/  timestamp feature. Every object modified by FatFs will have a fixed timestamp
/  defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/  To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added
/  to the project to read current time form real-time clock. FF_NORTC_MON,
/  FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/  These options have no effect in read-only configuration (FF_FS_READONLY = 1). */#define FF_FS_NOFSINFO	0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/  option, and f_getfree() at the first time after volume mount will force
/  a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/  bit0=0: Use free cluster count in the FSINFO if available.
/  bit0=1: Do not trust free cluster count in the FSINFO.
/  bit1=0: Use last allocated cluster number in the FSINFO if available.
/  bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/#define FF_FS_LOCK		0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/  and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/  is 1.
/
/  0:  Disable file lock function. To avoid volume corruption, application program
/      should avoid illegal open, remove and rename to the open objects.
/  >0: Enable file lock function. The value defines how many files/sub-directories
/      can be opened simultaneously under file lock control. Note that the file
/      lock control is independent of re-entrancy. */#define FF_FS_REENTRANT	0
#define FF_FS_TIMEOUT	1000
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/  module itself. Note that regardless of this option, file access to different
/  volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/  and f_fdisk(), are always not re-entrant. Only file/directory access to
/  the same volume is under control of this featuer.
/
/   0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
/   1: Enable re-entrancy. Also user provided synchronization handlers,
/      ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(),
/      must be added to the project. Samples are available in ffsystem.c.
/
/  The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
*//*--- End of configuration options ---*/

四、文件系统测试

        在主函数中只需要包含ff.h文件即可,完整的主程序如下:

#include <stdio.h>
#include "system.h"
#include "delay.h"
#include "uart.h"
#include "flash.h"
#include "ff.h"// 文件系统变量
FATFS   fs;
FIL     fp;
FRESULT fres;
UINT    fnum;// 文件读写变量
BYTE    buffer[4096] = {0};
BYTE    textBuffer[] = "ABCDEFG";
uint8_t c[256]       = {0};int main(void)
{HAL_Init();SystemClock_Config();Uart_Init(115200);fres = f_mount(&fs, "1:", 1);                      // 挂载文件系统if(fres == FR_NO_FILESYSTEM)                       // 检测是否存在文件系统{fres = f_mkfs("1:", NULL, buffer, 4096);       // 创建文件系统if(fres == FR_OK)                              // 判断是否创建成功{printf("FATFS has been mkf\n");fres = f_mount(NULL, "1:", 0);             // 卸载文件系统fres = f_mount(&fs,  "1:", 1);             // 重新挂载文件系统}else                                           // 创建失败{printf("FATFS mkf filed: %d\n", fres);while(1)                                   // 死循环{}               }}else if(fres != FR_OK)                             // 挂载失败{printf("mount ERROR:%d\n", fres);while(1)                                       // 死循环{}}else                                                    // 挂载成功{printf("mount OK\n");}fres = f_open(&fp, "1:ABC.txt", FA_CREATE_ALWAYS | FA_WRITE);  // 创建文件                      if(fres == FR_OK)                                  // 判断是否创建成功{printf("File open is OK\n");}fres = f_write(&fp, "ABCDEFG", 7, &fnum);        // 写入数据if(fres == FR_OK)                                  // 判断是否写入成功{printf("File write is OK\n");}else                                                    // 写入失败{printf("%d\n", fres);}f_close(&fp);                                         // 关闭文件if(fres == FR_OK)                                  // 判断是否关闭成功{printf("File close is OK\n");}else                                                    // 关闭失败{printf("%d\n", fres);}fres = f_unmount("1:");                            // 卸载文件系统                fres = f_mount(&fs,"1:",1);                        // 重新挂载文件系统fres = f_open(&fp, "1:ABC.txt", FA_OPEN_EXISTING | FA_READ);   // 打开文件if(fres == FR_OK)                                  // 判断是否打开成功{printf("File open is OK\n");}else                                                    // 打开失败{printf("%d\n", fres);}fres = f_read(&fp, c, 7, &fnum);                 // 读取文件内容if(fres == FR_OK)                                  // 判断是否读取成功{printf("File read is OK\n");printf("%s\n", c);}else                                                    // 读取失败{printf("%d\n", fres);}f_close(&fp);                                         // 关闭文件fres = f_unmount("1:");                            // 卸载文件系统if(fres == FR_OK)                                  // 判断是否卸载成功{printf("unmount OK\n");}while (1){		delay_ms(500);}
}

        测试结果:

        完整工程链接: https://pan.baidu.com/s/1YCRDXtLZMiMOpGDCTqMhLQ?pwd=ccvg

        提取码: ccvg

相关文章:

STM32移植文件系统FATFS——片外SPI FLASH

一、电路连接 主控芯片选型为&#xff1a;STM32F407ZGT6&#xff0c;SPI FLASH选型为&#xff1a;W25Q256JV。 采用了两片32MB的片外SPI FLASH&#xff0c;电路如图所示。 SPI FLASH与主控芯片的连接方式如表所示。 STM32F407GT6W25Q256JVPB3SPI1_SCKPB4SPI1_MISOPB5SPI1_MOSI…...

华为HG8546M光猫宽带密码破解

首先进光猫管理界面 将password改成text就可以看到加密后的密码了 复制密码到下面代码里 import hashlibdef sha256(todo):return hashlib.sha256(str(todo).encode()).hexdigest()def md5(todo):return hashlib.md5(str(todo).encode()).hexdigest()def find_secret(secret,…...

驱动-兼容不同设备-container_of

驱动兼容不同类型设备 在 Linux 驱动开发中&#xff0c;container_of 宏常被用来实现一个驱动兼容多种不同设备的架构。这种设计模式在 Linux 内核中非常常见&#xff0c;特别 是在设备驱动模型中。linux内核的主要开发语言是C&#xff0c;但是现在内核的框架使用了非常多的面向…...

UE5 检测球形范围的所有Actor

和Untiiy不同&#xff0c;不需要复杂的调用 首选确保角色添加了Sphere Collision 然后直接把sphere拖入蓝图&#xff0c;调用GetOverlappingActors来获取碰撞范围内的所有Actor...

AI大模型学习十:‌Ubuntu 22.04.5 调整根目录大小,解决根目录磁盘不够问题

一、说明 由于默认安装时导致home和根目录大小一样&#xff0c;导致根目录不够&#xff0c;所以我们调整下 二、调整 # 确认/home和/是否为独立逻辑卷&#xff0c;并属于同一卷组&#xff08;VG&#xff09; rootnode1:~# lsblk NAME MAJ:MIN RM SIZE…...

在ros2上使用opencv显示一张图片

1.先将图片放到桌面上 2.打开终端ctrlaltT&#xff0c;查看自己是否已安装opencv 3.创建工作环境 4.进入工作目录并创建ROS2包添加OpenCV依赖项 5.进入/home/kong/opencv_ws/opencv_use/src目录创建.cpp文件并编辑 6.代码如下 my_opencv.cpp #include <cstdio> #include…...

训练神经网络的原理(前向传播、反向传播、优化、迭代)

训练神经网络的原理 通过前向传播计算预测值和损失&#xff0c;利用反向传播计算梯度&#xff0c;然后通过优化算法更新参数&#xff0c;最终使模型在给定任务上表现更好。 核心&#xff1a;通过计算损失函数&#xff08;通常是模型预测与真实值之间的差距&#xff09;对模型参…...

每日一题(小白)暴力娱乐篇30

顺时针旋转&#xff0c;从上图中不难看出行列进行了变换。因为这是一道暴力可以解决的问题&#xff0c;我们直接尝试使用行列转换看能不能得到想要的结果。 public static void main(String[] args) {Scanner scan new Scanner(System.in);int nscan.nextInt();int mscan.next…...

【HTTPS】免费SSL证书配置Let‘s Encrypt自动续期

【HTTPS】免费SSL证书配置Lets Encrypt自动续期 1. 安装Certbot1.1 snapd1.2 certbot2. 申请泛域名证书使用 DNS 验证申请泛域名证书3.配置nginx申请的 SSL 证书文件所在目录nginx配置证书示例查看证书信息和剩余时间4.自动续期手动自动5.不同服务器使用1. 安装Certbot 1.1 sn…...

企业应如何防范 AI 驱动的网络安全威胁?

互联网技术和 AI 科技为世界开启了一个新的发展篇章。同时&#xff0c;网络攻击也呈现出愈发强势的发展势头&#xff1a;高级持续性威胁 &#xff08;APT&#xff1a;Advanced Persistent Threat&#xff09;组织采用新的战术、技术和程序 (TTP)、AI 驱动下攻击数量和速度的提高…...

决策树简介

【理解】决策树例子 决策树算法是一种监督学习算法&#xff0c;英文是Decision tree。 决策树思想的来源非常朴素&#xff0c;试想每个人的大脑都有类似于if-else这样的逻辑判断&#xff0c;这其中的if表示的是条件&#xff0c;if之后的else就是一种选择或决策。程序设计中的…...

ScrollView(滚动视图)详解和按钮点击事件

文章目录 **ScrollView&#xff08;滚动视图&#xff09;详解****1. 核心特性****2. 基本用法****XML 示例&#xff1a;简单滚动布局** **3. 水平滚动&#xff1a;HorizontalScrollView****4. 高级用法****(1) 嵌套滚动控件****(2) 动态添加内容****(3) 监听滚动事件** **5. 注…...

2025年3月,再上中科院1区TOP,“等级熵+状态识别、故障诊断”

引言 2025年3月&#xff0c;研究者在国际机械领域顶级期刊《Mechanical Systems and Signal Processing》&#xff08;JCR 1区&#xff0c;中科院1区 Top&#xff0c;IF&#xff1a;7.9&#xff09;上以“Rating entropy and its multivariate version”为题发表科学研究成果。…...

根据pdf文档生成问答并进行评估

目标是根据pdf文档生成问答&#xff0c;并进行评估。 首先&#xff0c;安装依赖 pip install PyPDF2 pandas tqdm openai -q 具体过程如下&#xff1a; 1、将pdf放在opeai_blog_pdfs目录下&#xff0c;引用依赖 2、上传pdf文件&#xff0c;创建向量库 3、单个提问的向量检索…...

计算机网络 - 四次挥手相关问题

通过一些问题来讨论 TCP 的四次挥手断开连接 说一下四次挥手的过程&#xff1f;为什么需要四次呢&#xff1f;time-wait干嘛的&#xff0c;close-wait干嘛的&#xff0c;在哪一个阶段&#xff1f;状态CLOSE_WAIT在什么时候转换成下一个状态呢&#xff1f;为什么 TIME-WAIT 状态…...

SLAM | 两组时间戳不同但同时开始的imu如何对齐

场景&#xff1a; 两个手机在支架上&#xff0c;同时开始采集数据 需求&#xff1a; 对齐两个数据集的imu数据 做到A图片 B imu 做法&#xff1a; 取出来两组imu数据到excel表中&#xff0c;画图 A组 B组&#xff1a; x轴 &#xff1a; 所有imu的时间戳减去第一个时间…...

code review时线程池的使用

一、多线程的作用 多个任务并行执行可以提升效率异步&#xff0c;让与主业务无关的逻辑异步执行&#xff0c;不阻塞主业务 二、问题描述 insertSelective()方法是一个并发度比较高的业务&#xff0c;主要是插入task到任务表里&#xff0c;新建task&#xff0c;并且insertSele…...

物流网络暗战升级DHL新布局将如何影响eBay卖家库存分布策略?

物流网络暗战升级&#xff1a;DHL新布局将如何影响eBay卖家库存分布策略&#xff1f; 跨境电商发展迅猛&#xff0c;卖家对物流的依赖程度不言而喻。尤其是平台型卖家&#xff0c;例如在eBay上经营多站点的卖家&#xff0c;物流成本和时效几乎直接决定了利润空间与客户满意度。…...

JAMA Netw. Open:机器学习解码大脑:精准预测PTSD症状新突破

创伤后应激障碍&#xff08;PTSD&#xff09;是一种常见的心理健康状况&#xff0c;它可以在人们经历或目睹创伤性事件&#xff08;如战争、严重事故、自然灾害、暴力攻击等&#xff09;后发展。PTSD的症状可能包括 flashbacks&#xff08;闪回&#xff09;、噩梦、严重的焦虑、…...

域控制器升级的先决条件验证失败,证书服务器已安装

出现“证书服务器已安装”导致域控制器升级失败时&#xff0c;核心解决方法是卸载已安装的证书服务‌。具体操作如下&#xff1a;‌ ‌卸载证书服务‌ 以管理员身份打开PowerShell&#xff0c;执行命令&#xff1a; Remove-WindowsFeature -Name AD-Certificate该命令会移除A…...

Node.js入门

Node.js入门 html,css,js 30年了 nodejs环境 09年出现 15年 nodejs为我们解决了2个方面的问题&#xff1a; 【锦上添花】让我们前端工程师拥有了后端开发能力&#xff08;开接口&#xff0c;访问数据库&#xff09; - 大公司BFF&#xff08;50&#xff09;【✔️】前端工程…...

使用CubeMX新建EXTI外部中断工程——不使用回调函数

具体的使用CubeMX新建工程的步骤看这里&#xff1a;STM32CubeMX学习笔记&#xff08;3&#xff09;——EXTI(外部中断)接口使用_cubemx exti-CSDN博客 之前一直都是在看野火的视频没有亲手使用CubeMX生成工程&#xff0c;而且野火给的例程代码框架和自动生成的框架也不一样&…...

Verilog的整数除法

1、可变系数除法实现----利用除法的本质 timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2025/04/15 13:45:39 // Design Name: // Module Name: divide_1 // Project Name: // Target Devices: // Tool Versions: // Description: // // Depe…...

win32汇编环境,网络编程入门之十九

;win32汇编环境,网络编程入门之十九 ;在这一编程里&#xff0c;我们学习一下如何使用gethostbyname函数&#xff0c;也顺便学一下如何将C定义的函数在WIN32汇编环境中使用 ;先看一下官方解释&#xff1a;从主机数据库中检索与主机名对应的主机信息。 ;它的原理是从你的电脑DNS中…...

Java学习手册:Java线程安全与同步机制

在Java并发编程中&#xff0c;线程安全和同步机制是确保程序正确性和数据一致性的关键。当多个线程同时访问共享资源时&#xff0c;如果不加以控制&#xff0c;可能会导致数据不一致、竞态条件等问题。本文将深入探讨Java中的线程安全问题以及解决这些问题的同步机制。 线程安…...

在生信分析中,从生物学数据库中下载的序列存放在哪里?要不要建立一个小型数据库,或者存放在Gitee上?

李升伟 整理 在Galaxy平台中使用时&#xff0c;从NCBI等生物学数据库下载的DNA序列的存储位置和管理方式需要根据具体的工作流程和需求进行调整。以下是详细的分步说明和建议&#xff1a; 一、Galaxy中DNA序列的默认存储位置 在Galaxy的“历史记录”&#xff08;History&…...

Python异步编程入门:Async/Await实战详解

引言 在当今高并发的应用场景下&#xff0c;传统的同步编程模式逐渐暴露出性能瓶颈。Python通过asyncio模块和async/await语法为开发者提供了原生的异步编程支持。本文将手把手带你理解异步编程的核心概念&#xff0c;并通过实际代码案例演示如何用异步爬虫提升10倍效率&#…...

cmd 终端输出乱码问题 |Visual Studio 控制台输出中文乱码解决

在网上下载&#xff0c;或者移植别人的代码到自己的电脑&#xff0c;使用VS运行后&#xff0c;控制台输出中文可能出现乱码。这是因为源代码的编码格式和控制台的编码格式不一致。 文章目录 查看源代码文件编码格式查看输出控制台编码格式修改编码格式修改终端代码页 补充总结 …...

【算法】椭圆曲线签名(ECDSA)

&#x1f914;什么是椭圆曲线签名&#xff08;ECDSA&#xff09;&#xff1f; 椭圆曲线签名算法&#xff08;Elliptic Curve Digital Signature Algorithm&#xff0c;简称 ECDSA&#xff09;是一种基于 椭圆曲线密码学 的数字签名算法。它主要用于加密货币&#xff08;如 Bit…...

Linux下使用MTK的SP_Flash_tool刷机工具

MTK的SP_Flash_tool刷机工具安装流程如下&#xff1a; 1、解压SP_Flash_Tool_Linux_v5.1336.00.100_Customer.zip unzip SP_Flash_Tool_exe_Linux_64Bit_v5.1520.00.100.zip 2、首先安装 libusb-dev 这个包&#xff1a; sudo apt-get install libusb-dev 3、安装成功之后…...

FRP内网穿透代理两个web页面(多端口内网穿透)

内网机器代理两个web页面出来 下载frp 选择0.51.2版本下载&#xff0c;高版本测试为成功 frp下载地址 部署frp server端&#xff08;公网部署&#xff09; #上传到opt rootsdgs-server07:/opt# ll frp_0.51.2_linux_amd64.tar.gz -rw-r--r-- 1 root root 11981480 Apr 15 1…...

Jenkins插件下载慢解决办法

jenkins设置插件使用国内镜像_jenkins 国内镜像-CSDN博客 国内源 以下是一些常用的国内 Jenkins 插件更新源地址&#xff1a; 清华大学&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json华为开源镜像站&#xff1a;https://mirrors.huawei…...

【Unity笔记】Unity开发笔记:ScriptableObject实现高效游戏配置管理(含源码解析)

在Unity开发中&#xff0c;高效管理游戏配置数据是提升开发效率的关键。本文分享如何使用ScriptableObject构建可编辑的键值对存储系统&#xff0c;并实现运行时动态读取。 一、为什么选择ScriptableObject&#xff1f; 1.1 ScriptableObject的核心优势 独立资源&#xff1a;…...

FPAG IP核调用小练习

一、调用步骤 1、打开Quartus 右上角搜索ROM&#xff0c;如图所示 2、点击后会弹出如图所示 其中文件路径需要选择你自己的 3、点击OK弹出如图所示 图中红色改为12与1024 4、然后一直点NEXT&#xff0c;直到下图 这里要选择后缀为 .mif的文件 5、用C语言生成 .mif文件 //…...

vue动画

1、动画实现 &#xff08;1&#xff09;、操作css的transition或animation &#xff08;2&#xff09;、在插入、更新或移除DOM元素时&#xff0c;在合适的时候给元素添加样式类名 &#xff08;3&#xff09;、过渡的相关类名&#xff1a; xxx-enter-active: 进入的时候激活…...

大数据学习(106)-hivesql函数

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…...

AI日报 - 2025年04月16日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; 模型井喷 | OpenAI (o3/o4-mini, GPT-4.1), Meta (Llama 4 Scout/Maverick), Z.ai (GLM-4家族), Cohere (Embed 4), Google (DolphinGemma) 等发布新模型&#xff0c;多模态、长文本、高效推理成焦点。 ▎&#x1f4bc; 商业…...

C# 经纬度坐标的精度及WGS84(谷歌)、GCJ02(高德)、BD09(百度)坐标相互转换(含高精度转换)

1. 概述 WGS-84坐标系&#xff08;World Geodetic System一1984 Coordinate System&#xff09;是一种国际上采用的地心坐标系&#xff0c;GCJ-02是由中国国家测绘局&#xff08;G表示Guojia国家&#xff0c;C表示Cehui测绘&#xff0c;J表示Ju局&#xff09;制订的地理信息系…...

案例:陌陌聊天数据分析

背景分析&#xff1a; 陌陌作为聊天平台每天都会有大量的用户在线&#xff0c;会出现大量的聊天数据&#xff0c;通过对 聊天数据的统计分析 &#xff0c;可以更好的 对用户构建精准的 用户画像 &#xff0c;为用户提供更好的服务以及实现 高 ROI 的平台运营推广&#xff…...

关闭谷歌浏览器(Google Chrome)的自动更新可以通过以下方法实现。具体操作步骤取决于你的操作系统。

关闭谷歌浏览器&#xff08;Google Chrome&#xff09;的自动更新可以通过以下方法实现。具体操作步骤取决于你的操作系统。 1. 在 Windows 上关闭 Chrome 自动更新2. 在 macOS 上关闭 Chrome 自动更新3. 在 Linux 上关闭 Chrome 自动更新4. 注意事项1. 在 Windows 上关闭 Chro…...

进程(完)

今天我们就补充一个小的知识点,查看进程树命令,来结束我们对linux进程的学习,那么话不多说,来看. 查看进程树 pstree 基本语法&#xff1a; pstree [选项] 优点&#xff1a;可以更加直观的来查看进程信息 常用选项&#xff1a; -p&#xff1a;显示进程的pid -u&#xff…...

(劳特巴赫调试器学习笔记)四、Practice脚本.cmm文件编写

Lauterbach调试器 文章目录 Lauterbach调试器一、什么是Practice脚本文件二、cmm脚本使用示例总结 一、什么是Practice脚本文件 官方文档解释&#xff1a; 因为Practice脚本以cmm为后缀&#xff0c;所以大多数人叫它cmm脚本。 以tricore为例&#xff0c;在安装目录下&#xff…...

并行流parallelStream.map().collect()

一、使用场景 先贴代码 public static void main(String[] args) {List<String> stringList new ArrayList<>();List<Integer> integerList new ArrayList<>();int num 10000;for (int i 0;i<num;i){stringList.add(String.valueOf(i));}stri…...

2025最新版flink2.0.0安装教程(保姆级)

Flink支持多种安装模式。 local&#xff08;本地&#xff09;——本地模式 standalone——独立模式&#xff0c;Flink自带集群&#xff0c;开发测试环境使用 standaloneHA—独立集群高可用模式&#xff0c;Flink自带集群&#xff0c;开发测试环境使用 yarn——计算资源统一…...

软件测试小讲

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 在 Web 项目开发中&#xff0c;全面的测试是保证系统稳定性、功能完整性和良好用户体验的关键。下面是一个详细的 Web 项目测试点列表&#xff0c;涵盖了不同方面的测试&#xff1a; 1. 功能测试 确保应用…...

DP35 【模板】二维前缀和 ---- 前缀和

目录 一&#xff1a;题目 二&#xff1a;算法原理 三&#xff1a;代码实现 一&#xff1a;题目 题目链接&#xff1a;【模板】二维前缀和_牛客题霸_牛客网 二&#xff1a;算法原理 三&#xff1a;代码实现 #include <iostream> #include <vector> using name…...

C语言——分支语句

在现实生活中&#xff0c;我们经常会遇到作出选择和判断的时候&#xff0c;在C语言中也同样要面临作出选择和判断的时候&#xff0c;所以今天&#xff0c;就让我们一起来了解一下&#xff0c;C语言是如何作出选择判断的。 目录 1.何为语句&#xff1f; 2.if语句 2.1 if语句的…...

使用Docker安装Jenkins

1、准备 2、安装 详见&#xff1a; https://www.jenkins.io/doc/book/installing/ https://www.jenkins.io/zh/doc/book/installing/ https://www.jenkins-zh.cn/tutorial/get-started/install/ # 方式1&#xff1a; # 详见&#xff1a;https://www.jenkins.io/doc/book/inst…...

东方博宜OJ ——2395 - 部分背包问题

贪心入门 ————2395 - 部分背包问题 2395 - 部分背包问题题目描述输入输出样例问题分析贪心算法思路代码实现总结 2395 - 部分背包问题 题目描述 阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N (N < 100)堆金币&#xff0c;第i堆金币的总重量和总价值分别是mi,vi (l …...

【期中准备特辑】计组,电路,信号

计组 以点带面地复习书中内容&#xff01; 指令体系结构&#xff08;ISA&#xff09;是计算机硬件和软件的分界面 世界上第一台电子计算机是 ENIAC&#xff08;埃尼阿克&#xff09; 第一代计算机采用电子管作为主要器件&#xff1b;第二代计算机采用晶体管&#xff1b;第三代…...