STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统
STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统
- Norflash简介
- NorFlash操作
- 驱动代码
- 文件系统
- 测试代码
Norflash简介
NOR Flash是一种类型的非易失性存储器,它允许在不移除电源的情况下保留数据。NOR Flash的名字来源于其内部结构中使用的NOR逻辑门。与另一种常见的闪存类型NAND Flash相比,NOR Flash提供了更快速的读取速度和随机访问能力,这使得它非常适合用于存储需要频繁、快速访问的代码或数据。
NOR Flash的特点包括:
- 快速读取:NOR Flash的读取速度非常快,适合执行存储于其中的程序代码。
- 随机访问:可以像SRAM一样进行随机访问,这使得它非常适合存储和运行代码。
- 写入和擦除速度较慢:尽管读取速度快,但NOR Flash的写入和擦除操作相对缓慢。
- 可靠性高:NOR Flash提供了比NAND Flash更高的可靠性和更低的位错误率。
- 成本较高:相对于每比特的价格来说,NOR Flash比NAND Flash要贵,尤其是在大容量存储方面。
应用场景
- NOR Flash通常用于那些需要快速启动和执行代码的应用中,例如嵌入式系统、消费电子产品以及汽车电子等。此外,由于其高可靠性和快速的读取速度,它也常被用来存储关键的固件或引导加载程序。
- 尽管NAND Flash在大规模数据存储上更为常用(如USB驱动器、SSD等),但在需要高效能执行代码的小型设备中,NOR Flash仍然是一个优选。随着技术的发展,NOR Flash也在不断进化以满足新的市场需求。
NorFlash操作
本文以Puya P25Q64SH 8MB Norflash为例
指令表
驱动代码
drv_spi_norflash.h
#ifndef __DRV_SPI_NORFLASH_H__
#define __DRV_SPI_NORFLASH_H__#include "app_config.h"
#include "Type_def.h"#if TCFG_DRV_SPI_NORFLASH_SUPPORT#define NORFLASH_PAGE_SIZE 256 // 256Byte
#define NORFLASH_SECTOR_SIZE 4096 // 4KB
#define NROFLASH_HALF_BLOCK_SIZE 32768 // 32KB
#define NORFLASH_BLOCK_SIZE 65536 // 64KB#define NORFLASH_FATFS_SECTOR_SIZE (NORFLASH_PAGE_SIZE * 2) // EatFs 文件系统读写扇区大小 支持页擦除的Norflash设置为2页/* 指令表 */
#define NOR_WriteEnable 0x06 /* 写使能 */
#define NOR_WriteDisable 0x04 /* 写禁止 */
#define NOR_VolatileSRWriteEnable 0x50
#define NOR_ReleasePowerDown 0xAB
#define NOR_ManufactDeviceID 0x90
#define NOR_JEDEC_ID 0x9F
#define NOR_ReadUniqueID 0x5A
#define NOR_ReadData 0x03
#define NOR_FastRead 0x0B
#define NOR_PageProgram 0x02
#define NOR_PageErase 0x81 /* 擦除1个页 256字节 ,部分Norflash不支持页擦除! */
#define NOR_SectorErase_4KB 0x20 /* 擦除1个扇区=4KB */
#define NOR_BlockErase_32KB 0x52 /* 擦除半个块=32KB */
#define NOR_BlockErase_64KB 0xD8 /* 擦除1个块=64KB */
#define NOR_ChipErase 0x60 /* or 0xC7 */#define NOR_ReadStatusREG1 0x05
#define NOR_WriteStatusREG1 0x01
#define NOR_ReadStatusREG2 0x35
#define NOR_WriteStatusREG2 0x31
#define NOR_ReadStatusREG3 0x15
#define NOR_WriteStatusREG3 0x11#define NOR_ReadSFDPREG 0x5A
#define NOR_EraseSecurityREG 0x44
#define NOR_ProgramSecurityREG 0x42
#define NOR_ReadSecurityREG 0x48
#define NOR_EraseProgramSuspend 0x75
#define NOR_EraseProgramResume 0x7A
#define NOR_Powerdown 0xB9
#define NOR_EnableReset 0x66
#define NOR_ResetDevice 0x99#define NOR_FastReadDualOutput 0x3B
#define NOR_FastReadDual_IO 0xBB
#define NOR_QuadInputPageProgram 0x32
#define NOR_FastReadQuadOutput 0x6B
#define NOR_FastReadQuad_IO 0xEB
#define NOR_WordReadQuad_IO 0xE7
#define NOR_SetBurstWithWrap 0x77#define NOR_DummyByte 0xFFenum {NORFLASH_ERASE_PAGE=0, /* 擦除页 256Byte */NORFLASH_ERASE_SECTOR, /* 擦除扇区 4KB */NORFLASH_ERASE_HALF_BLOCK, /* 擦除半块 32KB*/NORFLASH_ERASE_BLOCK, /* 擦除整块 64KB*/NORFLASH_ERASE_ALLCHIP, /* 擦除全部空间 */
};// #pragma pack(1)
// #pragma pack()// #pragma pack(push,1)
// #pragma pack(pop) #pragma pack(1)
struct norflash_reg_t{union { struct {uint8_t BUSY:1; // S0uint8_t WEL: 1; // S1uint8_t PB0: 1; // S2uint8_t PB1: 1; // S3uint8_t BP2: 1; // S4uint8_t _TB: 1; // S5uint8_t _SEC: 1; // S6uint8_t SRP0: 1; // S7}R;uint8_t _data; }REG1;union { struct {uint8_t SRP1: 1; // S8uint8_t _QE: 1; // S9uint8_t LB0: 1; // S10uint8_t LB1: 1; // S11uint8_t LB2: 1; // S12uint8_t LB3: 1; // S13uint8_t CMP: 1; // S14uint8_t SUS: 1; // S15}R;uint8_t _data;}REG2;union { struct {uint8_t Reserved2: 5;// uint8_t DRV2: 1; // S21uint8_t DRVS: 2; // S21 S22uint8_t Reserved1: 1; // S23}R;uint8_t _data;}REG3;
};
#pragma pack()struct jedec_id_t {uint8_t manufacturer_id; /* 制造商ID */uint8_t memory_type; /* 存储类型 */uint8_t capacity; /* 存储容量 */
};struct norflash_dev_t { uint16_t device_id;uint32_t page_size;uint32_t sector_size;uint32_t sector_count;uint32_t block_size;struct jedec_id_t jedec_id;struct norflash_reg_t reg;
};struct norflash_dev_t* NorFlash_Handler(void);void NorFlash_Read_JEDEC_ID(void);uint16_t NorFlash_ReadID(void);void NorFlash_ReadStatus(void);void NorFlash_Sleep(void);void NorFlash_Wakeup(void);uint8_t NorFlash_Erase(uint8_t eraser, uint32_t address);uint8_t NorFlash_ReadBuffer(uint8_t *buffer, uint32_t address, uint32_t len);uint8_t NorFlash_WritePage(uint8_t *buffer, uint32_t address, uint32_t len);uint8_t NorFlash_WriteBuffer(uint8_t *buffer, uint32_t address, uint32_t len);uint8_t NorFlash_Init(void);uint8_t NorFlash_GPIO_Config(void);void NorFlash_Test(void);#endif#endif
drv_spi_norflash.c
#include <stdio.h>
#include <string.h>#include "config.h"
#include "STC32G_Timer.h"
#include "STC32G_GPIO.h"
#include "STC32G_NVIC.h"
#include "STC32G_Exti.h"
#include "STC32G_Delay.h"#include "app_config.h"
#include "drv_spi_norflash.h"
#include "debug.h"#if TCFG_DRV_SPI_NORFLASH_SUPPORT#define NOR_CS P77 // CS 片选
#define NOR_DI P76 // DI 数据输入
#define NOR_CLK P75 // CLK 时钟
#define NOR_DO P74 // DO 数据输出#define NOR_WP P73 // WP 写保护 不使用可接至VCC
#define NOR_HOLD P74 // HOLD 引脚保持 不使用可接至VCCstatic struct norflash_dev_t xdata norflash_dev;
#define __this norflash_dev/*** @brief 获取NorFlash设备句柄* @param 无* @return struct norflash_dev_t类型指针
*/
struct norflash_dev_t* NorFlash_Handler(void)
{return (struct norflash_dev_t*)&norflash_dev;
} /*** @brief NorFlash读字节* @param 无* @return 读取字节数据
*/
static uint8_t NorFlash_Read(void)
{// CLK下升沿DO输出数据uint8_t i,dat=0;NOR_DO = 1;for (i=0; i<8; i++){NOR_CLK=1;dat<<=1;dat |= NOR_DO; NOR_CLK=0;}return dat;
}/*** @brief NorFlash写字节* @param dat:写入字节数据* @return 无
*/
static void NorFlash_Write(uint8_t dat)
{// CLK上升沿DI读入数据uint8_t i;for (i=0; i<8; i++){NOR_CLK=0;NOR_DI = (dat&0x80);NOR_CLK=1;dat <<=1;}NOR_CLK= 0;NOR_DI = 0;
}/*** @brief NorFlash读写字节(写入1字节数据,同时读取1字节数据)* @param dat:写入字节数据* @return 读取字节数据
*/
static uint8_t NorFlash_ReadWrite(uint8_t dat)
{// CLK上升沿DI读入数据 // CLK下升沿DO输出数据(CLK=0数据变化,CLK=1数据锁存 读取数据)uint8_t i,read=0;NOR_DO = 1;for (i=0; i<8; i++){ NOR_CLK = 0;NOR_DI = (dat&0x80);dat <<= 1;NOR_CLK=1;read<<=1;read |= NOR_DO;}NOR_CLK=0;NOR_DI = 0;return read;
}/*** @brief NorFlash等待准备好信号(BUSY标志位)* @param 无* @return 0:准备好,1:忙状态
*/
static uint8_t NorFlash_WaitReady(void)
{uint8_t tryes;uint8_t value=0;tryes = 200;do {NOR_CS = 0;NorFlash_Write(NOR_ReadStatusREG1);__this.reg.REG1._data = NorFlash_Read();NOR_CS = 1;delay_ms(5);}while(__this.reg.REG1.R.BUSY&&tryes--);if (__this.reg.REG1.R.BUSY) {return 1; // 出错} else {return 0; // 正常}
}void NorFlash_SendAddress(uint32_t address)
{if (0) { // 4Byte Address EnableNorFlash_Write((uint8_t)((address>>24)&0xFF)); }NorFlash_Write((uint8_t)((address>>16)&0xFF));NorFlash_Write((uint8_t)((address>>8)&0xFF));NorFlash_Write((uint8_t)(address&0xFF));
}/*** @brief NorFlash读取状态寄存器* @param 无* @return 无
*/
void NorFlash_ReadStatus(void)
{NOR_CS = 0;NorFlash_Write(NOR_ReadStatusREG1);__this.reg.REG1._data = NorFlash_Read();// __this.SREG1 = NorFlash_Read();NOR_CS = 1;NOR_CS = 0;NorFlash_Write(NOR_ReadStatusREG2);__this.reg.REG2._data = NorFlash_Read();// __this.SREG2 = NorFlash_Read();NOR_CS = 1;NOR_CS = 0;NorFlash_Write(NOR_ReadStatusREG3);__this.reg.REG3._data = NorFlash_Read();// __this.SREG3 = NorFlash_Read();NOR_CS = 1;log_d("REG1:%02X, BUSY:%d, WEL:%d, SRP0:%d\n", __this.reg.REG1._data, __this.reg.REG1.R.BUSY, __this.reg.REG1.R.WEL, __this.reg.REG1.R.SRP0);log_d("REG2:%02X\n", __this.reg.REG2._data);log_d("REG3:%02X, DRVS:%d\n", __this.reg.REG3._data, __this.reg.REG3.R.DRVS);
}/*** @brief NorFlash休眠* @param 无* @return 无*/
void NorFlash_Sleep(void)
{NOR_CS = 0;NorFlash_Write(NOR_Powerdown);NOR_CS = 1;
}/*** @brief NorFlash唤醒* @param 无* @return 无*/
void NorFlash_Wakeup(void)
{NOR_CS = 0;NorFlash_Write(NOR_ReleasePowerDown);NOR_CS = 1;
}/*** @brief NorFlash读取JEDEC ID* @param 无* @return 无
*/
void NorFlash_Read_JEDEC_ID(void)
{NOR_CS = 0;NorFlash_Write(NOR_JEDEC_ID);__this.jedec_id.manufacturer_id = NorFlash_Read(); // Manufacturer ID__this.jedec_id.memory_type = NorFlash_Read(); // Memory Type__this.jedec_id.capacity = NorFlash_Read(); // CapacityNOR_CS = 1;
}/*** @brief NorFlash读取设备ID* @param 无* @return 2字节设备ID
*/
uint16_t NorFlash_ReadID(void)
{uint16_t device_id=0xFFFF;#if 0NOR_CS = 0;NorFlash_Write(NOR_ManufactDeviceID);// 写入address:0x000000NorFlash_Write(0x00);NorFlash_Write(0x00);NorFlash_Write(0x00);// 读取Device ID 2Bytedevice_id = NorFlash_Read();// log_d("ID:%X",device_id);device_id <<= 8;device_id |= NorFlash_Read(); NOR_CS = 1;
#elseNOR_CS = 0;NorFlash_ReadWrite(NOR_ManufactDeviceID);// 写入address:0x000000NorFlash_SendAddress(0x000000);// 读取Device ID 2Bytedevice_id = NorFlash_ReadWrite(NOR_DummyByte);device_id <<= 8;device_id |= NorFlash_ReadWrite(NOR_DummyByte); NOR_CS = 1;
#endifreturn device_id;
}uint8_t NorFlash_Erase(uint8_t eraser, uint32_t address)
{uint32_t i;u8 eraser_cmd;// 执行擦除命令前先检查忙状态if (NorFlash_WaitReady()) {log_d("Erase Wait 1 Error\n");return 1;}switch(eraser){case NORFLASH_ERASE_PAGE:log_i("NORFLASH_ERASE_PAGE\n");address = address / 256 * 256; // 页对齐,1页=256字节eraser_cmd = NOR_PageErase; break;case NORFLASH_ERASE_SECTOR:log_i("NORFLASH_ERASE_SECTOR\n");address = address / 4096 * 4096; // 扇区对齐,1扇区=4096字节eraser_cmd = NOR_SectorErase_4KB;break;case NORFLASH_ERASE_HALF_BLOCK:log_i("NORFLASH_ERASE_HALF_BLOCK\n");address = address / 32768 * 32768; // 半块对齐,半个块=32768字节=32KBeraser_cmd = NOR_BlockErase_32KB;break;case NORFLASH_ERASE_BLOCK:log_i("NORFLASH_ERASE_BLOCK\n");address = address / 65535 * 65535; // 块对齐,1个块=65535字节=64KBeraser_cmd = NOR_BlockErase_64KB;break;case NORFLASH_ERASE_ALLCHIP:log_i("NORFLASH_ERASE_ALLCHIP\n");eraser_cmd = NOR_ChipErase; break;default:log_e("Erase CMD Error\n");return 1;}// 发送写使能命令NOR_CS = 0;NorFlash_Write(NOR_WriteEnable);NOR_CS = 1;// 发送擦除命令NOR_CS = 0;NorFlash_Write(eraser_cmd);if (NOR_ChipErase != eraser_cmd) {// 不是擦除全片命令,写入地址NorFlash_SendAddress(address);} NOR_CS = 1;if (NorFlash_WaitReady()) {log_d("Erase Wait 2 Error\n");return 1;}return 0;
}uint8_t NorFlash_ReadBuffer(uint8_t *buffer, uint32_t address, uint32_t len)
{uint32_t i;NOR_CS = 0;NorFlash_Write(NOR_ReadData);NorFlash_SendAddress(address);for(i=0; i<len; i++){buffer[i] = NorFlash_Read();}NOR_CS = 1;return 0;
}uint8_t NorFlash_WritePage(uint8_t *buffer, uint32_t address, uint32_t len)
{uint32_t i;NOR_CS = 0;NorFlash_Write(NOR_WriteEnable);NOR_CS = 1;NOR_CS = 0;NorFlash_Write(NOR_PageProgram);NorFlash_SendAddress(address);for(i=0; i<len; i++){NorFlash_Write(buffer[i]);}NOR_CS = 1;if (NorFlash_WaitReady()) {log_d("Write Wait Error\n");return 1;}return 0;
}uint8_t NorFlash_WriteBuffer(uint8_t *buffer, uint32_t address, uint32_t len)
{uint8_t num_of_page = 0, num_of_single = 0, addr = 0, count = 0, temp = 0;addr = address % NORFLASH_PAGE_SIZE;count = NORFLASH_PAGE_SIZE - addr;num_of_page = len / NORFLASH_PAGE_SIZE;num_of_single = len % NORFLASH_PAGE_SIZE;/* address is NORFLASH_PAGE_SIZE aligned */if(0 == addr){/* len < NORFLASH_PAGE_SIZE */if(0 == num_of_page)NorFlash_WritePage(buffer,address,len);/* len > NORFLASH_PAGE_SIZE */else{while(num_of_page--){NorFlash_WritePage(buffer,address,NORFLASH_PAGE_SIZE);address += NORFLASH_PAGE_SIZE;buffer += NORFLASH_PAGE_SIZE;}NorFlash_WritePage(buffer,address,num_of_single);}}else{/* address is not NORFLASH_PAGE_SIZE aligned */if(0 == num_of_page){/* (len + address) > NORFLASH_PAGE_SIZE */if(num_of_single > count){temp = num_of_single - count;NorFlash_WritePage(buffer,address,count);address += count;buffer += count;NorFlash_WritePage(buffer,address,temp);}elseNorFlash_WritePage(buffer,address,len);}else{/* len > NORFLASH_PAGE_SIZE */len -= count;num_of_page = len / NORFLASH_PAGE_SIZE;num_of_single = len % NORFLASH_PAGE_SIZE;NorFlash_WritePage(buffer,address, count);address += count;buffer += count;while(num_of_page--){NorFlash_WritePage(buffer,address,NORFLASH_PAGE_SIZE);address += NORFLASH_PAGE_SIZE;buffer += NORFLASH_PAGE_SIZE;}if(0 != num_of_single)NorFlash_WritePage(buffer,address,num_of_single);}}return 0;
}uint8_t NorFlash_Init(void)
{log_d("NorFlash_Init\n");NOR_WP = 1;NOR_HOLD = 1;NOR_CS = 1;NOR_CLK = 0;NOR_DI = 0;NOR_DO = 0;NorFlash_Read_JEDEC_ID();log_d("manufacturer_id:0x%X\n", __this.jedec_id.manufacturer_id);log_d("memory_type:0x%X\n", __this.jedec_id.memory_type);log_d("capacity:0x%X\n", __this.jedec_id.capacity);__this.device_id = NorFlash_ReadID();log_d("DeviceID:0x%04X\n", __this.device_id);#if 0__this.page_size = 256;__this.sector_size = 16*256; // 4KB__this.sector_count = 16777216/4096;// 扇区个数=总容量/扇区大小__this.block_size = 16*16*256; // 64KB
#endif}uint8_t NorFlash_GPIO_Config(void)
{// P7_SPEED_LOW(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2);P7_SPEED_HIGH(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2);P7_PULL_UP_ENABLE(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2);P7_DRIVE_MEDIUM(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2);// P7_DRIVE_HIGH(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2);P7_MODE_OUT_PP(GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_3|GPIO_Pin_2);// 配置DI为高阻输入模式P7_MODE_IO_PU(GPIO_Pin_4);// P7_MODE_IN_HIZ(GPIO_Pin_4);P7_DIGIT_IN_ENABLE(GPIO_Pin_4);// P7_PULL_UP_ENABLE(GPIO_Pin_4);// P7_PULL_UP_DISABLE(GPIO_Pin_4);
}#if 0
#define D_NORFLASH_TEST_ADDR 0x000000 //(0x400000)
void NorFlash_Test(void)
{int i=0;uint8_t buffer[256*4];memset(buffer, 0, sizeof(buffer));NorFlash_Erase(NORFLASH_ERASE_SECTOR, D_NORFLASH_TEST_ADDR);log_d("Erase Sector\n");for(i=0; i<512; i++){if (i<256)buffer[i] = i;elsebuffer[i] = 0x3A;}NorFlash_WritePage(buffer, D_NORFLASH_TEST_ADDR, 512);log_d("Norflash Write\n");NorFlash_ReadBuffer(buffer, D_NORFLASH_TEST_ADDR, 512);log_d("NorFlash Read:\n");for(i=0; i<512; i++){log_d("%02x,", buffer[i]);}log_d("\n");
}
#endif#endif
文件系统
FatFs/diskio.c
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */#include "app_config.h"#if TCFG_LIB_FATFS_SUPPORT#if TCFG_DRV_SD_CARD_SPI_SUPPORT
#include "drv_sd.h"
#endif#if TCFG_DRV_SPI_NORFLASH_SUPPORT
#include "drv_spi_norflash.h"
#endif#include "debug.h"/* Definitions of physical drive number for each drive */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
#define DEV_NOR 3 /* NorFlash *//*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/DSTATUS disk_status (BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{DSTATUS stat = STA_NOINIT;int result;switch (pdrv) {case DEV_RAM :// result = RAM_disk_status();// translate the reslut code herelog_d("disk_status DEV_RAM\n");return stat;case DEV_MMC :// result = MMC_disk_status();// translate the reslut code herestat = 0;log_d("disk_status DEV_MMC\n");return stat;case DEV_USB :// result = USB_disk_status();// translate the reslut code herelog_d("disk_status DEV_USB\n");return stat;case DEV_NOR:#if TCFG_DRV_SPI_NORFLASH_SUPPORTlog_d("disk_status DEV_NOR\n"); stat = 0;#endifreturn stat;}return STA_NOINIT;
}/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/DSTATUS disk_initialize (BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{DSTATUS stat;int result;switch (pdrv) {case DEV_RAM :// result = RAM_disk_initialize();// translate the reslut code herelog_d("disk_initialize DEV_RAM\n");return stat;case DEV_MMC :// result = MMC_disk_initialize();// translate the reslut code here#if TCFG_DRV_SD_CARD_SPI_SUPPORTif(SD_Init() == 0) {stat = 0;} else {stat = RES_ERROR;}#endiflog_d("disk_initialize DEV_MMC\n");return stat;case DEV_USB :// result = USB_disk_initialize();// translate the reslut code herelog_d("disk_initialize DEV_USB\n");return stat;case DEV_NOR:#if TCFG_DRV_SPI_NORFLASH_SUPPORTlog_d("disk_initialize DEV_NOR\n");NorFlash_Init();stat = 0;#endifreturn stat;}return STA_NOINIT;
}/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/DRESULT disk_read (BYTE pdrv, /* Physical drive nmuber to identify the drive */BYTE *buff, /* Data buffer to store read data */LBA_t sector, /* Start sector in LBA */UINT count /* Number of sectors to read */
)
{DRESULT res;int result;switch (pdrv) {case DEV_RAM :// translate the arguments here// result = RAM_disk_read(buff, sector, count);// translate the reslut code herelog_d("disk_read DEV_RAM\n");return res;case DEV_MMC :// translate the arguments here// result = MMC_disk_read(buff, sector, count);// translate the reslut code here#if TCFG_DRV_SD_CARD_SPI_SUPPORTif (count == 1) {if (SD_ReadSingelBlock(buff, sector) == 0) {res = RES_OK;} else {res = RES_ERROR;}} else {if (SD_ReadMultipleBlock(buff, sector, count) == 0) {res = RES_OK;} else {res = RES_ERROR;}}#endiflog_d("disk_read DEV_MMC\n");return res;case DEV_USB :// translate the arguments here// result = USB_disk_read(buff, sector, count);// translate the reslut code herelog_d("disk_read DEV_USB\n");return res;case DEV_NOR:#if TCFG_DRV_SPI_NORFLASH_SUPPORTlog_d("disk_read DEV_NOR\n");NorFlash_ReadBuffer(buff, sector*NORFLASH_FATFS_SECTOR_SIZE, count*NORFLASH_FATFS_SECTOR_SIZE);res = RES_OK;#endifreturn res;}return RES_PARERR;
}/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/#if FF_FS_READONLY == 0DRESULT disk_write (BYTE pdrv, /* Physical drive nmuber to identify the drive */const BYTE *buff, /* Data to be written */LBA_t sector, /* Start sector in LBA */UINT count /* Number of sectors to write */
)
{DRESULT res;int result;switch (pdrv) {case DEV_RAM :// translate the arguments here// result = RAM_disk_write(buff, sector, count);// translate the reslut code herelog_d("disk_write DEV_RAM\n");return res;case DEV_MMC :// translate the arguments here// result = MMC_disk_write(buff, sector, count);// translate the reslut code here#if TCFG_DRV_SD_CARD_SPI_SUPPORTif (count == 1) {if (SD_WriteSingleBlock(buff, sector) == 0) {res = RES_OK;} else {res = RES_ERROR;}} else {if (SD_WriteMultipleBlock(buff, sector, count) == 0) {res = RES_OK;} else {res = RES_ERROR;}}#endiflog_d("disk_write DEV_MMC\n");return res;case DEV_USB :// translate the arguments here// result = USB_disk_write(buff, sector, count);// translate the reslut code herelog_d("disk_write DEV_USB\n");return res;case DEV_NOR:{#if TCFG_DRV_SPI_NORFLASH_SUPPORTuint8_t i;BYTE *buf = buff;log_d("disk_write DEV_NOR\n");for (i=0; i<count; i++){// 写之前必须先擦除写入扇区:擦除512字节 = 2页NorFlash_Erase(NORFLASH_ERASE_PAGE, sector * NORFLASH_FATFS_SECTOR_SIZE); // 擦除页NorFlash_Erase(NORFLASH_ERASE_PAGE, sector * NORFLASH_FATFS_SECTOR_SIZE + NORFLASH_PAGE_SIZE); // 擦除页NorFlash_WriteBuffer(buf, sector * NORFLASH_FATFS_SECTOR_SIZE, NORFLASH_FATFS_SECTOR_SIZE); sector += 1; } res = RES_OK;#endifreturn res;}}return RES_PARERR;
}#endif/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/DRESULT disk_ioctl (BYTE pdrv, /* Physical drive nmuber (0..) */BYTE cmd, /* Control code */void *buff /* Buffer to send/receive control data */
)
{DRESULT res = RES_OK;int result;switch (pdrv) {case DEV_RAM :// Process of the command for the RAM drivelog_d("disk_ioctl DEV_RAM cmd:0x%02x\n", cmd);return res;case DEV_MMC :#if TCFG_DRV_SD_CARD_SPI_SUPPORT// Process of the command for the MMC/SD cardlog_d("disk_ioctl DEV_MMC cmd:%d\n", cmd);if (CTRL_SYNC == cmd) {log_d("CTRL_SYNC\n");} else if (GET_SECTOR_COUNT == cmd) {log_d("GET_SECTOR_COUNT\n");// *(DWORD *)buff = 1536;} else if (GET_SECTOR_SIZE == cmd) {log_d("GET_SECTOR_SIZE\n");*(WORD *)buff = 512;} else if (GET_BLOCK_SIZE == cmd) { log_d("GET_BLOCK_SIZE\n");*(WORD *)buff = 1 ; //每次擦除一个扇区} else if (CTRL_TRIM == cmd) {log_d("CTRL_TRIM\n");}#endifreturn res;case DEV_USB :// Process of the command the USB drivelog_d("disk_ioctl DEV_USB cmd:%d\n", cmd);return res;case DEV_NOR:#if TCFG_DRV_SPI_NORFLASH_SUPPORTlog_d("disk_ioctl DEV_NOR cmd:%d\n", cmd);if (CTRL_SYNC == cmd) {log_d("CTRL_SYNC\n");res = RES_OK;} else if (GET_SECTOR_SIZE == cmd) {log_d("GET_SECTOR_SIZE\n");// 这个是文件系统每次操作的扇区大小,不一定非要和Norflash的扇区大小一致,但最小值一般为512字节。// 一般单片机RAM资源有限文件系统不能是以实际扇区或块大小来操作// 这里定义文件系统扇区大小为2个页,需要Norflash支持页擦除指令*(DWORD *)buff = NORFLASH_FATFS_SECTOR_SIZE; // NorFlash 最小读写扇区大小res = RES_OK;} else if (GET_SECTOR_COUNT == cmd) {log_d("GET_SECTOR_COUNT\n");*(DWORD *)buff = 8192; //NorFlash扇区个数 = 总容量/文件系统扇区大小 4MB=(4194304/512)=8192个扇区; res = RES_OK;} else if (GET_BLOCK_SIZE == cmd) { log_d("GET_BLOCK_SIZE\n");*(DWORD *)buff = 1; //每次擦除的扇区个数,1res = RES_OK;} else if (CTRL_TRIM == cmd) {log_d("CTRL_TRIM\n");res = RES_OK;}#endifreturn res;}return RES_PARERR;
}/*** @brief 获取日期
*/
DWORD get_fattime (void)
{
/*Return ValueCurrnet local time shall be returned as bit-fields packed into a DWORD value. The bit fields are as follows:bit31:25Year origin from the 1980 (0..127, e.g. 37 for 2017)bit24:21Month (1..12)bit20:16Day of the month (1..31)bit15:11Hour (0..23)bit10:5Minute (0..59)bit4:0Second / 2 (0..29, e.g. 25 for 50)
*/return ((DWORD)(2010 - 1980) << 25) | ((DWORD)1 << 16) | ((DWORD)0 << 11) | ((DWORD)0 << 5) | ((DWORD)0 >> 1);
}#if 0
DWORD get_fattime (void)
{time_t t;struct tm *stm;t = time(0);stm = localtime(&t);return (DWORD)(stm->tm_year - 80) << 25 |(DWORD)(stm->tm_mon + 1) << 21 |(DWORD)stm->tm_mday << 16 |(DWORD)stm->tm_hour << 11 |(DWORD)stm->tm_min << 5 |(DWORD)stm->tm_sec >> 1;
}
#endif#endif //TCFG_LIB_FATFS_SUPPORT
FatFs/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 1
/* 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 1
/* 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 1
/* 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 1
/* 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 //932
/* 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 4 //1
/* 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 512
#define FF_MAX_SS 512
/* 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 ---*/
测试代码
#if 1 // Norflash 文件系统测试static FATFS nor_fatfs; // 必须是全局变量
static BYTE nor_work[FF_MAX_SS]; // 必须是全局变量FRESULT res;
FIL nor_fp;// 挂在文件系统
res = f_mount(&nor_fatfs, "3:", 1); // 挂载SD卡,0=DEV_RAM, 1=DEV_MMC, 2=DEV_USB, 3=DEV_NOR
log_d("norflash f_mount res:%d\n", res);
if (res == FR_NO_FILESYSTEM) {// 无文件系统,尝试创建文件系统res = f_mkfs("3:", 0, nor_work, sizeof(nor_work));if (FR_OK == res) {/* 格式化后,先取消挂载 */f_mount(NULL, "3:", 1); // 取消文件系统res = f_mount(&nor_fatfs, "3:", 1); // 挂载文件系统log_d("norflash f_mount 222 res:%d\n", res); }
}if (FR_OK == res) {// 挂载成功
}// 写文件
#define D_TEST_STR "The realm of fast artificial neural networks (ANNs) stands as a pinnacle of modern computational intelligence. These networks mimic the human brain’s ability to learn from vast amounts of data, making them invaluable in processing complex patterns quickly. The core of their speed lies in their unique architecture, which allows for parallel processing, akin to how neurons in the human brain operate simultaneously. At the heart of these networks are activation functions, which determine the output of neural computations. These functions are crucial as they introduce non-linearity into the system, enabling the network to learn and make sense of complicated data inputs. By effectively handling these computations, fast ANNs can perform tasks ranging from image recognition to language processing at remarkable speeds."
res = f_open(&nor_fp , "3:abcd.txt" , FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_READ |FA_WRITE );
printf("write f_open res = %d\r\n",res);
if (FR_OK == res) {unsigned int wb;if (f_write(&nor_fp, D_TEST_STR, strlen(D_TEST_STR), &wb) == FR_OK) {log_d("write ok:%d\n", wb);} else {log_d("write err\n");}
}
f_sync(&nor_fp);
f_close(&nor_fp);// 读文件
unsigned int rb;
unsigned char buf[1024]={0};
res = f_open(&nor_fp , "3:abcd.txt" , FA_OPEN_ALWAYS|FA_READ |FA_WRITE );
printf("rd res f_open = %d\r\n",res);
if (f_read(&nor_fp, (char*)buf, sizeof(buf), &rb) == FR_OK) {log_d("read buf %d:%s\n", rb, buf);
} else {log_d("read buf err\n");
}
f_close(&nor_fp); #endif
相关文章:
STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统
STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统 Norflash简介NorFlash操作驱动代码文件系统测试代码 Norflash简介 NOR Flash是一种类型的非易失性存储器,它允许在不移除电源的情况下保留数据。NOR Flash的名字来源于其内部结构中使用的NOR逻辑门。…...
uniapp-x 二维码生成
支持X,二维码生成,支持微信小程序,android,ios,网页 - DCloud 插件市场 免费的单纯用爱发电的...
当HTTP遇到SQL注入:Java开发者的攻防实战手册
一、从HTTP请求到数据库查询:漏洞如何产生? 危险的参数拼接:Servlet中的经典错误 漏洞代码重现: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String category = request.getParameter("…...
[dp20_完全背包] 介绍 | 零钱兑换
目录 1. 完全背包 题解 背包必须装满 2.零钱兑换 题解 1. 完全背包 链接: DP42 【模板】完全背包 描述 你有一个背包,最多能容纳的体积是V。 现在有n种物品,每种物品有任意多个,第i种物品的体积为vivi ,价值为wiwi。 &a…...
精打细算 - GPU 监控
精打细算 - GPU 监控 在上一篇,咱们历经千辛万苦,终于让应用程序在 Pod 的“驾驶舱”里成功地“点火”并用上了 GPU。太棒了!但是,车开起来是一回事,知道车速多少、油耗多少、引擎水温是否正常,则是另一回事,而且同样重要,对吧? 我们的 GPU 应用跑起来了,但新的问题…...
故障诊断 | CNN-BiGRU-Attention故障诊断
效果一览 摘要 在现代工业生产中,设备的稳定运行至关重要,故障诊断作为保障设备安全、高效运行的关键技术,其准确性和及时性直接影响着生产效率与成本[[doc_refer_1]][[doc_refer_2]]。随着工业设备复杂性的不断增加,传统故障诊断方法已难以满足实际需求。深度学习技术凭借…...
单片机AIN0、AIN1引脚功能
目录 1. 模拟-数字转换器(ADC) 2. 交流电源(AC) 总结 这两部分有什么区别? 在这个电路图中,两个部分分别是模拟-数字转换器(ADC)和交流电源(AC)。以下是这…...
交换机与路由器的主要区别:深入分析其工作原理与应用场景
在现代网络架构中,交换机和路由器是两种至关重要的设备。它们在网络中扮演着不同的角色,但很多人对它们的工作原理和功能特性并不十分清楚。本文将深入分析交换机与路由器的主要区别,并探讨它们的工作原理和应用场景。 一、基本定义 1. 交换…...
uniApp小程序保存定制二维码到本地(V3)
这里的二维码组件用的 uv-ui 的二维码 可以按需引入 QRCode 二维码 | 我的资料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生态框架 <uv-qrcode ref"qrcode" :size"280" :value"payCodeUrl"></uv-qrcode>&l…...
手机投屏到电视方法
一、投屏软件 比如乐播投屏 二、视频软件 腾讯视频、爱奇艺 三、手机无线投屏功能 四、有线投屏 五、投屏器...
桌面应用UI开发方案
一、基于 Web 技术的跨平台方案 Electron Python/Go 特点: 技术栈:前端使用 HTML/CSS/JS,后端通过 Node.js 集成 Python/Go 模块或服务。 跨平台:支持 Windows、macOS、Linux 桌面端,适合开发桌面应用。 生态成熟&…...
FFmpeg+Nginx+VLC打造M3U8直播
一、视频直播的技术原理和架构方案 直播模型一般包括三个模块:主播方、服务器端和播放端 主播放创造视频,加美颜、水印、特效、采集后推送给直播服务器 播放端: 直播服务器端:收集主播端的视频推流,将其放大后推送给…...
山东科技大学深度学习考试回忆
目录 一、填空(五个空,十分) 二、选择题(五个,十分) 三、判断题(五个,五分) 四、论述题(四个,四十分) 五、计算题(二个ÿ…...
【Flutter动画深度解析】性能与美学的完美平衡之道
Flutter的动画系统是其UI框架中最引人注目的部分之一,它既能创造令人惊艳的视觉效果,又需要开发者对性能有深刻理解。本文将深入剖析Flutter动画的实现原理、性能优化策略以及设计美学,帮助你打造既流畅又美观的用户体验。 一、Flutter动画核…...
【嵌入式】——Linux系统远程操作和程序编译
目录 一、虚拟机配置网络设置 二、使用PuTTY登录新建的账户 1、在ubuntu下开启ssh服务 2、使用PuTTY连接 三、树莓派实现远程登录 四、树莓派使用VNC viewer登录 五、Linux使用talk聊天程序 1、使用linux自带的talk命令 2、使用c语言编写一个talk程序 一、虚拟机配置网络…...
零、HarmonyOS应用开发者基础学习总览
零、HarmonyOS应用开发者基础认证 1 整体学习内容概览 1 整体学习内容概览 通过系统化的课程学习,熟练掌握 DevEco Studio,ArkTS,ArkUI,预览器,模拟器,SDK 等 HarmonyOS 应用开发的关键概念,具…...
记录一次项目中使用pdf预览过程以及遇到问题以及如何解决
背景 项目中现有的pdf浏览解析不能正确解析展示一些pdf文件,要么内容一直在加载中展示不出来,要么展示的格式很凌乱 解决 方式一:(优点:比较无脑,缺点:不能解决遇到的一些特殊问题࿰…...
致远OA——自定义开发rest接口
文章目录 :apple: 业务流程 🍎 业务流程 代码案例: https://pan.quark.cn/s/57fa808c823f 官方文档: https://open.seeyoncloud.com/seeyonapi/781/https://open.seeyoncloud.com/v5devCTP/39/783.html 登录系统 —— 后台管理 —— 切换系…...
STL之vector基本操作
写在前面 我使用的编译器版本是 g 11.4.0 (Ubuntu 22.04 默认版本),支持C17的全部特性,支持C20的部分特性。 vector的作用 我们知道vector是动态数组(同时在堆上存储数组元素),我们在不确定数…...
dac直通线还是aoc直通线? sfp使用
"DAC直通线" 和 "AOC直通线" 都是高速互连线缆,用于数据中心、服务器、交换机等设备之间的高速互连。它们的选择主要取决于以下几个方面: 🔌 DAC(Direct Attach Cable,直连铜缆) 材质&…...
【Linux篇】探索进程间通信:如何使用匿名管道构建高效的进程池
从零开始:通过匿名管道实现进程池的基本原理 一. 进程间通信1.1 基本概念1.2 通信目的1.3 通信种类1.3.1 同步通信1.3.2 异步通信 1.4 如何通信 二. 管道2.1 什么是管道2.2 匿名管道2.2.1 pipe()2.2.2 示例代码:使用 pipe() 进行父子进程通信2.2.3 管道容…...
Mixture-of-Experts with Expert Choice Routing:专家混合模型与专家选择路由
摘要 稀疏激活的专家混合模型(MoE)允许在保持每个token或每个样本计算量不变的情况下,大幅增加参数数量。然而,糟糕的专家路由策略可能导致某些专家未被充分训练,从而使得专家在特定任务上过度或不足专业化。先前的研究通过使用top-k函数为每个token分配固定数量的专家,…...
ai学习中收藏网址【1】
https://github.com/xuwenhao/geektime-ai-course课程⾥所有的代码部分,通过 Jupyter Notebook 的形式放在了 GitHub 上 https://github.com/xuwenhao/geektime-ai-course 图片创作 https://www.midjourney.com/explore?tabtop 创建填⾊本 How to Create Midjour…...
【滑动窗口】最⼤连续 1 的个数 III(medium)
⼤连续 1 的个数 III(medium) 题⽬描述:解法(滑动窗⼝):算法思路:算法流程: C 算法代码:Java 算法代码: 题⽬链接:1004. 最⼤连续 1 的个数 III …...
ClawCloud的免费空间(github用户登录可以获得$5元/月的免费额度)
免费的空间 Welcome to ClawCloud Lets create your workspace 官网:ClawCloud | Cloud Infrastructure And Platform for Developers 区域选择新加坡 然后这个页面会变成新加坡区域,再按一次确定,就创建好了工作台。 初始界面࿰…...
sql之DML(insert、delete、truncate、update、replace))
🎯 本文专栏:MySQL深入浅出 🚀 作者主页:小度爱学习 数据库使用时,大多数情况下,开发者只会操作数据,也是就增删改查(CRUD)。 增删改查四条语句,最重要的是查…...
Spring Boot常用注解全解析:从入门到实战
🌱 Spring Boot常用注解全解析:从入门到实战 #SpringBoot核心 #注解详解 #开发技巧 #高效编程 一、核心启动与配置注解 1. SpringBootApplication 作用:标记主启动类,整合了Configuration、EnableAutoConfiguration和Component…...
Python 赋能区块链教育:打造去中心化学习平台
Python 赋能区块链教育:打造去中心化学习平台 引言 区块链技术正在重塑全球多个行业,而教育领域也不例外。传统的在线学习平台往往依赖中心化存储和管理模式,导致数据安全、用户隐私、资源共享等问题难以解决。而随着 Web 3.0 的发展,区块链在教育场景中的应用逐渐受到关…...
verilog float mult
module pipe_float_mul(input wire clk ,// 时钟信号input wire en ,// 使能信号input wire rst_n ,// 复位信号input wire round_cfg ,// 决…...
Android开发四大组件和生命周期及setFlags
文章目录 Android开发四大组件1. Activity(活动)2. Service(服务)3. BroadcastReceiver(广播接收器)4. ContentProvider(内容提供者)共同特点 Activity 生命周期详解完整的生命周期方…...
mysql的函数(第二期)
九、窗口函数(MySQL 8.0) 适用于对结果集的子集(窗口)进行计算,常用于数据分析场景。 ROW_NUMBER() 作用:为每一行生成唯一的序号。示例:按分数降序排名 SELECT n…...
MATLAB 控制系统设计与仿真 - 39
多变量系统控制器设计实例2 假如原系统对象中有位于虚轴上的极点,则不能直接应用鲁棒控制设计来设计控制器。 在这样的情况下,需引入一个新的变量p,使得 即可在对象模型中用p变量取代s变量,这样的变换称为双线性变换,…...
深入理解C++ 中的vector容器
一、引言 在C 的标准模板库(STL)中, vector 是一个极为常用且功能强大的序列容器。它就像是一个动态数组,既能享受数组随机访问元素的高效性,又能灵活地动态调整大小。在本文中,我们将深入探讨 vector …...
ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之LED)
目录 ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之LED)简介模块概述功能定义架构位置核心特性 LED外设分析LED外设概述LED外设功能特点常见应用场景LED外设架构图 LED外设API和数据结构公共API事件类型配置…...
[特殊字符] Kotlin与C的类型别名终极对决:typealias vs typedef,如何让代码脱胎换骨?
在 Kotlin 中,typealias 是一个非常实用的关键字,它可以为已有的类型定义一个新的名称,起到简化代码和提升可读性的作用。比如: // 定义一个复杂函数类型的别名 typealias ClickListener (View, Int) -> Unitfun setOnClickL…...
第9期:文本条件生成(CLIP + Diffusion)详解
“让我们用一句话,让模型画出一幅画。” 在前几期中我们学习了 Denoising Diffusion Probabilistic Models(DDPM)如何在无条件情况下生成图像。而在本期,我们将跨入更具挑战性但也更酷的领域 —— 文本条件图像生成(Te…...
8 编程笔记全攻略:Markdown 语法精讲、Typora 编辑器全指南(含安装激活、基础配置、快捷键详解、使用技巧)
1 妙笔在手,编程无忧! 1.1 编程为啥要做笔记?这答案绝了! 嘿,各位键盘魔法师!学编程不记笔记,就像吃火锅不配冰可乐 —— 爽到一半直接噎住!你以为自己脑子是顶配 SSD,结…...
C#测试linq中的左连接的基本用法
使用linq联表或者连接两个对象集合查询时一般使用的是join关键字,返回结果中包含两个表或两个对象集合中连接字段相等的数据记录,如果要实现sql语句中的左连接效果,并没有现成的left join关键字,此时可以使用DefaultIfEmpty 实现左…...
【Android面试八股文】Android系统架构【一】
Android系统架构图 1.1 安卓系统启动 1.设备加电后执行第一段代码:Bootloader 系统引导分三种模式:fastboot,recovery,normal: fastboot模式:用于工厂模式的刷机。在关机状态下,按返回开机 键进…...
什么是 Stream
Stream 是对集合对象功能的增强,它不是集合,也不存储数据,而是从集合中抽象出一条数据通道,让你可以用链式方式一步步处理数据。 🔧 常见操作分类 类型方法举例创建stream(), Stream.of(), Arrays.stream()中间操作fi…...
网络编程 - 4 ( TCP )
目录 TCP 流套接字编程 API 介绍 SeverSocket Socket 用 TCP 实现一个回显服务器 服务端 客户端 运行调试 第一个问题:PrintWriter 内置的缓冲区 - flush 刷新解决 第二个问题:上述代码中,需要进行 close 操作吗? 第三…...
在STM32的定时器外设中,选择使用哪个外部时钟配置函数
在STM32的定时器外设中,选择使用哪个外部时钟配置函数主要取决于以下几个因素: 时钟源类型: TIM_ITRxExternalClockConfig:使用内部触发输入(ITRx),即来自其他定时器的时钟信号 TIM_TIxExternalClockConfig࿱…...
【Tauri2】026——Tauri+Webassembly
前言 不多废话 直言的说,笔者看到这篇文章大佬的文章 【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly,直接开始 正文 准备工作 新建一个项目 安装 vite的rsw插件和rsw pnpm instal…...
jenkins尾随命令
在访问jenkins的网址后面可以追加命令,比如访问地址是 http://10.20.0.124:8080/,常用的有以下几种方式: 1.关闭Jenkins 只要浏览器输入http://10.20.0.124:8080/exit即可退出,或者http://localhost:8080/exit 2.重启Jenkins …...
基于机器学习 LSTM 算法的豆瓣评论情感分析系统
基于机器学习 LSTM 算法的豆瓣评论情感分析系统 博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 ὄ…...
腾讯云对象存储m3u8文件使用腾讯播放器播放
参考腾讯云官方文档: 播放器 SDK Demo 体验_腾讯云 重要的一步来了: 登录腾讯云控制台,找到对象存储的存储桶。 此时,再去刷新刚才创建的播放器html文件,即可看到播放画面了。...
基于chatgpt和deepseek解答显卡的回答
当然可以!了解显卡特别是英伟达(NVIDIA)的系列,对于选购、升级或者了解游戏和创作性能都很重要。下面我帮你系统整理一下 NVIDIA 显卡的各个系列,并加点选购建议,方便你快速上手。 chatgpt 🧠 …...
2025年渗透测试面试题总结-拷打题库06(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 1. Sleep被禁用后的SQL注入 2. XSS属性控制利用 3. CSRF防护 4. 危险请求头 5. XXE高发场景 6. Ja…...
【一起学Rust】使用Thunk工具链实现Rust应用对Windows XP/7的兼容性适配实战
前言 在Rust语言快速发展的今天,开发者经常面临将现代语言特性与遗留系统兼容的挑战。特别是在工业控制、嵌入式设备等场景中,Windows XP/7等经典操作系统仍占据重要地位。本文深入解析如何通过Thunk工具链突破Rust编译器对旧版Windows系统的兼容性限制…...
leetcode 674. Longest Continuous Increasing Subsequence
目录 题目描述 第一步,明确并理解dp数组及下标的含义 第二步,分析明确并理解递推公式 第三步,理解dp数组如何初始化 第四步,理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。与第300题的唯一区别就是&#…...