STM32CubeMX学习笔记20——SD卡FATFS文件系统

news2024/11/16 13:03:15

1. FATFS文件系统简介

文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构(即在存储设备上组织文件的方法)。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统;不带文件系统的SD卡仅能实现简单的读写扇区操作,要真正应用SD卡必须要使用文件系统

FATFS文件存储原理(以FAT32为例),下图为FAT32文件系统布局:

簇是文件存储的最小单元,FAT32分区大小与对应簇空间大小关系如下表示:

分区空间大小簇空间大小每个簇包含的扇区数
< 8GB4KB8
[ 8GB, 16GB )8KB16
[ 16GB, 32GB )16KB32
>= 32GB32KB64

例如:创建一个50字节的test.txt文件,文件大小是50字节,但是占用磁盘空间为4096字节(一个簇)

FATFS是一个完全免费开源,专为小型嵌入式系统设计的FAT(File Allocation Table)文件系统模块。FATFS的编写遵循ANSI C,并且完全与磁盘I/O层分开。支持FAT12/FAT16/FAT32,支持多个存储媒介,有独立的缓冲区,可对多个文件进行读写。兼容Windows文件系统。

FatFs 文件系统的源码可以从 fatfs 官网下载:
FatFs - Generic FAT Filesystem Module

FATFS模块的层次结构如下图示:

- 最顶层是应用层:使用者只需要调用FATFS模块提供给用户的一系列应用接口函数(如f_open, f_read, f_write和f_close等),就可以像在PC上读写文件那样简单
- 中间层FATFS模块:实现了FAT文件读写协议;它提供了 ff.cff.h文件,一般情况下不用修改,使用时将头文件包含进去即可
- 最底层是FATFS模块的底层接口:包括存储媒介读写接口和供给文件创建修改时间的实时时钟,需要在移植时编写对应的代码

FATFS源码相关文件介绍如下表示;移植FATFS模块时,一般只需要修改2个文件(即ffconf.hdiskio.c

与平台无关文件描述
ffconf.hFATFS模块配置文件
ff.hFATFS和应用模块公用的包含文件
ff.cFATFS模块
diskio.hFATFS和disk I/O模块公用的包含文件
interger.h数据类型定义
option可选的外部功能(比如支持中文)
与平台相关文件描述
diskio.cFATFS和disk I/O模块接口层文件

FATFS的移植主要分为三步:

  1. 数据类型:在integer.h里面去定义好数据的类型
  2. 配置:通过ffconf.h配置FATFS相关功能
  3. 函数编写:在diskio.c文件中进行底层驱动编写(6个接口函数disk_initialize、disk_status、disk_read、disk_write、disk_ioctl、get_fattime)

本例程使用的是STM32CubeMX图形化软件配置FATFS,只需要简单设置即可以完成以上三步的工作。下图是STM32CubeMX的FATFS底层实现框图:

STM32CubeMX生成的代码工程里,涉及底层驱动实现的文件主要有以下三个:

1、ff_gen_drv.c文件:FATFS提供的通用驱动文件的实现
//ff_gen_drv.h文件内容
/*Disk IO Driver structure definition */
typedef struct
{
  DSTATUS (*disk_initialize) (BYTE);    //通过指针指向diskio.c中的disk_initialize()
  DSTATUS (*disk_status)     (BYTE);    //通过指针指向diskio.c中的disk_status()
  DRESULT (*disk_read)       (BYTE, BYTE*, DWORD, UINT);    //指向disk_read()
#if _USE_WRITE == 1 
  DRESULT (*disk_write)      (BYTE, const BYTE*, DWORD, UINT);  //指向disk_write()
#endif 
#if _USE_IOCTL == 1  
  DRESULT (*disk_ioctl)      (BYTE, BYTE, void*);   //指向disk_ioctl() 
#endif
}Diskio_drvTypeDef;

/*brief  Global Disk IO Drivers structure definition*/ 
typedef struct{ 
  uint8_t                 is_initialized[_VOLUMES]; //磁盘是否初始化
  Diskio_drvTypeDef       *drv[_VOLUMES];   //磁盘的驱动
  uint8_t                 lun[_VOLUMES];    //磁盘的编号
  __IO uint8_t            nbr;
}Disk_drvTypeDef;
/* Exported functions ------------------------------------------------------- */
uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, char *path, uint8_t lun);
uint8_t FATFS_LinkDriver(Diskio_drvTypeDef *drv, char *path);
uint8_t FATFS_UnLinkDriver(char *path);
uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, char *path, BYTE lun);
uint8_t FATFS_UnLinkDriverEx(char *path, BYTE lun);
uint8_t FATFS_GetAttachedDriversNbr(void);
2、sd_diskio.c:针对SD底层驱动实现,封装成为通用的底层驱动API
//sd_diskio.c文件内容
const Diskio_drvTypeDef  SD_Driver = {
  SD_initialize,    //指向diskio.c中的disk_initialize()
  SD_status,    //指向diskio.c中的disk_status()
  SD_read,  //指向diskio.c中的disk_read()
#if  _USE_WRITE == 1
  SD_write, //指向diskio.c中的disk_write()
#endif /* _USE_WRITE == 1 */  
#if  _USE_IOCTL == 1
  SD_ioctl, //指向diskio.c中的disk_ioctl()
#endif /* _USE_IOCTL == 1 */
};  //定义Diskio_drvTypeDef类型的SD_Driver

/* -------------------以上各函数的实现---------------------------*/
DSTATUS SD_initialize(BYTE lun){
  Stat = STA_NOINIT;  
  if(BSP_SD_Init() == MSD_OK){
    Stat &= ~STA_NOINIT;
  }
  return Stat;
}

DSTATUS SD_status(BYTE lun){
  Stat = STA_NOINIT;
  if(BSP_SD_GetCardState() == MSD_OK){
    Stat &= ~STA_NOINIT;
  }
  return Stat;
}

DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count){
  DRESULT res = RES_ERROR;
  uint32_t timeout = 100000;
  if(BSP_SD_ReadBlocks((uint32_t*)buff,(uint32_t) (sector), count, SD_DATATIMEOUT) == MSD_OK){
    while(BSP_SD_GetCardState()!= MSD_OK){
      if (timeout-- == 0)
        return RES_ERROR;
    }
    res = RES_OK;
  } 
  return res;
}

#if _USE_WRITE == 1
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count){
  DRESULT res = RES_ERROR;
  uint32_t timeout = 100000;
  if(BSP_SD_WriteBlocks((uint32_t*)buff,(uint32_t)(sector),count, SD_DATATIMEOUT) == MSD_OK){
    while(BSP_SD_GetCardState()!= MSD_OK){
      if (timeout-- == 0)
        return RES_ERROR;
    }    
    res = RES_OK;
  }
  return res;
}
#endif /* _USE_WRITE == 1 */

#if _USE_IOCTL == 1
DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff){
  DRESULT res = RES_ERROR;
  BSP_SD_CardInfo CardInfo;  
  if (Stat & STA_NOINIT) return RES_NOTRDY;  
  switch (cmd){
  /* Make sure that no pending write process */
  case CTRL_SYNC :
    res = RES_OK;
    break;
  /* Get number of sectors on the disk (DWORD) */
  case GET_SECTOR_COUNT :
    BSP_SD_GetCardInfo(&CardInfo);
    *(DWORD*)buff = CardInfo.LogBlockNbr;
    res = RES_OK;
    break;
  /* Get R/W sector size (WORD) */
  case GET_SECTOR_SIZE :
    BSP_SD_GetCardInfo(&CardInfo);
    *(WORD*)buff = CardInfo.LogBlockSize;
    res = RES_OK;
    break;
  /* Get erase block size in unit of sector (DWORD) */
  case GET_BLOCK_SIZE :
    BSP_SD_GetCardInfo(&CardInfo);
    *(DWORD*)buff = CardInfo.LogBlockSize;
    res = RES_OK;
    break;
  default:
    res = RES_PARERR;
  } 
  return res;
}
#endif /* _USE_IOCTL == 1 */
3、bsp_driver_sd.c:HAL库的二次封装,将基于SD卡的操作都在该文件下实现
//bsp_driver_sd.h文件内容
uint8_t BSP_SD_Init(void);
uint8_t BSP_SD_ITConfig(void);
void    BSP_SD_DetectIT(void);
void    BSP_SD_DetectCallback(void);
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr);
void BSP_SD_IRQHandler(void);
void BSP_SD_DMA_Tx_IRQHandler(void);
void BSP_SD_DMA_Rx_IRQHandler(void);
uint8_t BSP_SD_GetCardState(void);
void    BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo);
uint8_t BSP_SD_IsDetected(void);
void    BSP_SD_AbortCallback(void);
void    BSP_SD_WriteCpltCallback(void);
void    BSP_SD_ReadCpltCallback(void);

FATFS提供的应用接口如下图示:

下面简单介绍几个常用操作函数:

f_mount:在FATFS模块上注册/注销一个工作区(文件系统对象)
FRESULT f_mount(FATFS* fs, const TCHAR* path, BYTE opt);
参数--> fs:fs工作区(文件系统对象)指针,如果赋值为 NULL 可以取消物理设备挂载
        path:注册/注销工作区的逻辑设备编号,使用设备根路径表示
        opt:注册或注销选项(可选0或1),0表示不立即挂载,1表示立即挂载
f_mkfs:格式化物理设备
FRESULT f_mkfs(const TCHAR* path, BYTE sfd, UINT au);
参数--> path:逻辑设备编号,使用设备根路径表示
        sfd:0或1,0表示为硬盘设备;1表示为软盘设备
        au:指定扇区大小,若为0表示通过disk_ioctl函数获取
f_open:创建/打开一个文件对象
FRESULT f_open(FIL* fp, const TCHAR* path, BYTE mode);
参数--> fp:将创建或打开的文件对象指针
        path:文件名指针,指定将创建或打开的文件名(包含文件类型后缀名)
        mode:访问类型和打开方法
mode可选值:
FA_READ     指定读访问对象。可以从文件中读取数据。 与FA_WRITE结合可以进行读写访问。   
FA_WRITE    指定写访问对象。可以向文件中写入数据。与FA_READ结合可以进行读写访问。   
FA_OPEN_EXISTING    打开文件。如果文件不存在,则打开失败。(默认)  
FA_OPEN_ALWAYS      如果文件存在,则打开;否则,创建一个新文件。  
FA_CREATE_NEW       创建一个新文件。如果文件已存在,则创建失败。   
FA_CREATE_ALWAYS    创建一个新文件。如果文件已存在,则它将被截断并覆盖。
f_close:关闭一个打开的文件
FRESULT f_close (FIL *fp)
参数--> fp:将被关闭的已打开的文件对象结构的指针
f_write:写入数据到一个已打开的文件
FRESULT f_write (FIL* fp, const void *buff, UINT btw, UINT* bw)
参数--> fp:指向将被写入的已打开的文件对象结构的指针
        buff:指向存储写入数据的缓冲区的指针
        btw:要写入的字节数
        bw:指向返回已写入字节数的UINT变量的指针,返回为实际写入的字节数
f_read:从一个打开的文件中读取数据
FRESULT f_read (FIL* fp, const void *buff, UINT btr, UINT* br)
参数--> fp:指向将被读取的已打开的文件对象结构的指针
        buff:指向存储读取数据的缓冲区的指针
        btr:要读取的字节数
        br:指向返回已读取字节数的UINT变量的指针,返回为实际读取的字节数

2. 硬件设计

LED2指示灯用来提示系统运行状态,串口1用来打印调试信息,使用FATFS文件系统对SD卡进行相关操作

  • LED2指示灯
  • USART1
  • TF卡

3 、 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M
  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
  • 激活SDIO,详细请参考SD卡例程
  • 打开FATFS文件系统,选择SD卡模式,配置为中文编码,选择内存空间为HEAP,其余默认值
  • Function Parameters 跳过

  • Locale and Namespace Parameters:

        CODE_PAGE(Code page on target): Simplified Chinese GBK(DBCS,OEM,Windows) 支持简体中文编码
        USE_LFN(Use Long Filename): Enabled with dynamic working buffer on the STACK 支持长文件名,并指定使用栈空间为缓冲区

缓存工作区为什么放在栈?其实fatfs提供了三个选项:BSS,STACK , HEAP,根据个人情况选一个。
在BSS上启用带有静态工作缓冲区的LFN,不能动态分配。
如果选择了HEAP(堆)且自己有属于自己的malloc就去重写ff_memalloc  ff_memfree函数。如果是库的malloc就不需要。
一般都选择使用STACK(栈),能动态分配。
当使用堆栈作为工作缓冲区时,请注意堆栈溢出。

Physical Drive Parameters:
        VOLUMES(Logical drivers): 2 指定物理设备数量,这里设置为 2,包括预留 SD 卡和 SPI Flash 芯片
        MAX_SS(Maximum Sector Size): 512 指定扇区大小的最大值。SD 卡扇区大小一般都为 512 字节,SPI Flash 芯片扇区大小一般设置为 4096 字节,所以需要把 _MAX_SS 改为 512
        MIN_SS(Minimum Sector Size): 512 指定扇区大小的最小值

配置SD卡检测引脚

        SD卡插入检测引脚,如果不配置一个引脚生成文件时会报错,所以这里即使没有硬件连接,也可以任意设置一引脚使用,生成工程后注释代码。

增大栈空间

将最小栈空间改到 0x1000

注意:由于刚才设置长文件名动态缓存存储在堆中,故需要增大堆大小,如果不修改则程序运行时堆会生成溢出,程序进入硬件错误中断(HardFault),死循环。

 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

4、程序编程

int main(void){
    HAL_Init();
    SystemClock_Config();
  /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_CRC_Init();
    MX_FSMC_Init();
    MX_SDIO_SD_Init();
    MX_USART1_UART_Init();
    MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
    uint32_t byteswritten;                /* File write counts */
    uint32_t bytesread;                   /* File read counts */
    uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
    uint8_t rtext[100];                   /* File read buffers */
    char filename[] = "STM32cube.txt";
    char SensorBuff[100];
    printf("********* STM32CubeMX FatFs Example *********\r\n\r\n");    
    if(f_mount(&SDFatFS,SDPath,1) == FR_OK){
        printf("f_mount sucess!!! \r\n");
        if(f_open(&SDFile,filename,FA_CREATE_ALWAYS|FA_WRITE) == FR_OK){
            printf("f_open file sucess!!! \r\n");
            if(f_write(&SDFile,wtext,sizeof(wtext),&byteswritten) == FR_OK){
                printf("f_write file sucess!!! \r\n");
                printf("f_write Data : %s\r\n",wtext);
                if(f_close(&SDFile) == FR_OK)
                    printf("f_close sucess!!! \r\n");
                else
                    printf("f_close error : %d\r\n",retSD);
            }
            else
                printf("f_write file error\r\n");    
        }
        else
            printf("f_open file error\r\n");  
    }else
        printf("f_mount error : %d \r\n",retSD);

    retSD = f_open(&SDFile, filename, FA_READ);
    if(retSD)
        printf("f_open file error : %d\r\n",retSD);
    else
        printf("f_open file sucess!!! \r\n");

    retSD = f_read(&SDFile, rtext, sizeof(rtext), (UINT*)&bytesread);
    if(retSD)
        printf("f_read error!!! %d\r\n",retSD);
    else{
        printf("f_read sucess!!! \r\n");
        printf("f_read Data : %s\r\n",rtext);
    }

    retSD = f_close(&SDFile);
    if(retSD)
        printf("f_close error!!! %d\r\n",retSD);
    else
        printf("f_close sucess!!! \r\n");

    if(bytesread == byteswritten)
        printf("FatFs is working well!!!\r\n");

    if(f_open(&SDFile,(const char*)"Sensor.csv",FA_CREATE_ALWAYS|FA_WRITE) == FR_OK){
        printf("Sensor.csv was opened/created!!!\r\n");
        sprintf(SensorBuff, "Item,Temp,Humi,Light\r\n");
        f_write(&SDFile,SensorBuff,strlen(SensorBuff),&byteswritten);

        for(int i = 0; i < 10; i++){
            sprintf(SensorBuff, "%d,%d,%d,%d\r\n",i + 1, i + 20, i + 30, i + 40);
            f_write(&SDFile,SensorBuff,strlen(SensorBuff),&byteswritten);
            f_sync(&SDFile);
        }
        f_close(&SDFile);
    }

    while (1){
        HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);
        HAL_Delay(500);
    }
}

5. 下载验证

如果使用的是新SD卡,需要在电脑上进行格式化,建立FAT文件系统,FATFS才能识别并操作SD卡

编译无误下载到开发板后,可以看到LED2指示灯不断闪烁,串口打印出如下信息:

将SD卡插入PC后,可以看到SD卡里建立了2个文件:Sensor.csv和STM32cube.txt,打开文件后可以看到写入的数据

 

6、参考文献

STM32CubeMX学习笔记(27)——FatFs文件系统使用(操作SD卡)_stm32cubemx fatfs-CSDN博客

STM32CubeMX系列 | FATFS文件系统 - 知乎 (zhihu.com) 

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

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

相关文章

论文:CLIP(Contrastive Language-Image Pretraining)

Learning Transferable Visual Models From Natural Language Supervision 训练阶段 模型架构分为两部分&#xff0c;图像编码器和文本编码器&#xff0c;图像编码器可以是比如 resnet50&#xff0c;然后文本编码器可以是 transformer。 训练数据是网络社交媒体上搜集的图像…

数据结构---复杂度(2)

1.斐波那契数列的时间复杂度问题 每一行分别是2^0---2^1---2^2-----2^3-------------------------------------------2^(n-2) 利用错位相减法&#xff0c;可以得到结果是&#xff0c;2^(n-1)-1,其实还是要减去右下角的灰色部分&#xff0c;我们可以拿简单的数字进行举例子&…

Halcon测量专栏-圆弧测量

1.前言 1.1什么是圆弧 圆上任意两点间的部分叫做圆弧。由于圆弧有正反的特性&#xff0c;即为有顺时针方向和逆时针方向&#xff0c;在确定圆弧时&#xff0c;也需要确定圆弧的方向。 1.2halcon实现方式 针对圆弧的问题。1&#xff1a;它与圆是相似的&#xff0c;都具备中心…

(完美方案)解决mfc140u.dll文件丢失问题,快速且有效的修复

唉&#xff0c;又是丢失了mfc140u.dll&#xff0c;这该怎么办呢&#xff1f;如果你的电脑突然找不到或丢失mfc140u.dll文件&#xff0c;那就真是太糟糕了。别担心&#xff0c;我分享给你一些干货&#xff0c;告诉你如何快速解决mfc140u.dll丢失的问题。 一.mfc140u.dll属性功能…

分布式之Ribbon使用以及原理

Ribbon使用以及原理 1、负载均衡的两种方式 服务器端负载均衡 传统的方式前端发送请求会到我们的的nginx上去&#xff0c;nginx作为反向代理&#xff0c;然后路由给后端的服务器&#xff0c;由于负载均衡算法是nginx提供的&#xff0c;而nginx是部署到服务器端的&#xff0c;所…

数据结构入门(3)2.链表接口实现

目录 前言 头文件 动态申请一个结点 单链表打印 单链表尾插 单链表的头插 单链表的尾删 单链表头删 单链表查找 单链表在pos位置之后插入x 单链表删除pos位置之后的值 在pos的前面插入 删除pos位置 销毁顺序表 前言 本文将介绍链表常见的功能的实现 头文件 #…

【Java】仓库管理系统 SpringBoot+LayUI+DTree(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【APB协议 UVM_Sequencer Driver Monitor_2024.03.04】

apb协议 写时序 地址、写信号、PSEL、写数据信号同时发生变化&#xff0c;即传输的第一个时钟被称为SETUP周期。在下个时钟上升沿,PENABLE信号拉高&#xff0c;表示ENABLE周期&#xff0c;在该周期内&#xff0c;数据、地址以及控制信号都必须保持有效。整个写传输在这个周期…

【Java常用API】正则表达式的基础使用

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

Matlab|计及需求响应和电能交互的多主体综合能源系统主从博弈优化调度策略

目录 主要内容 部分代码 结果一览 下载链接 主要内容 程序建立了多主体综合能源模型&#xff0c;采用双层模型进行求解&#xff0c;上层用自适应粒子群算法求解出各能源售价和需求响应补偿价格&#xff1b;下层采用混合整数规划算法求解出三个园区、配电网、储能…

leetcode 热题 100_旋转图像

题解一&#xff1a; 翻转数组&#xff1a;先将数组沿右上-左下对角线翻转&#xff0c;再将数组上下翻转。 class Solution {public void rotate(int[][] matrix) {int n matrix.length;for (int i 0; i < n; i) {//沿右上-左下对角线翻转for (int j 0; j < n - i - 1…

vob格式转换mp4怎么转? 如何保持vob原画质?

VOB&#xff08;Video Object&#xff09;文件格式在数字视频制作领域崭露头角。起源于DVD技术的发展&#xff0c;VOB旨在存储包括音频、视频和菜单等多媒体元素的内容。这一格式为数字娱乐提供了高质量的视频体验&#xff0c;然而&#xff0c;由于其相对封闭的特性&#xff0c…

Stable Diffusion 模型下载:Comic Babes(漫画宝贝)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 条目内容类型大模型基础模型SD 1.5来源CIVITAI作者datmuttdoe文件名称comicBabes_v2.safet…

数据治理实践——金融行业大数据治理的方向与实践

目录 一、证券数据治理服务化背景 1.1 金融数据治理发展趋势 1.2 证券行业数据治理建设背景 1.3 证券行业数据治理目标 1.4 证券行业数据治理痛点 二、证券数据治理服务化实践 2.1 国信证券数据治理建设框架 2.2 国信证券数据治理建设思路 2.3 数据模型管理 2.4 数据…

例解变分自编码器(VAE)

本文通过一个回归例子介绍变分自编码器。产生训练和测试样本的代码如下&#xff1a; # data import tensorflow as tf import numpy as np import matplotlib.pyplot as plt %matplotlib inlinedef f(x, sigma):# y 10 * sin(2 * pi) epsilonreturn 10 * np.sin(2 * np.pi *…

【漏洞分析】CVE-2024-27198可RCE身份验证绕过JetBrains TeamCity

CVE-2024-27198可RCE身份验证绕过JetBrains TeamCity 一、基本原理二、创建新的管理员用户三、自我检查四、POC 一、基本原理 向存在漏洞服务器发送一个不存在的页面请求 ?jsp/app/rest/server;.jsp 这会使服务器报错提供版本信息&#xff0c;且无需登录 Fofa app“JET_BRAIN…

Linux工具 - 好用的yum包管理器

~~~~ 前言yum是什么为什么有yum如何使用yum配置用户yum源为什么要配置yum源具体配置备份CentOS-Base.repo文件下载对应阿里yum源到本目录/etc/yum.repos.d/清理yum并生成缓存更改配置文件CentOS-Base.repo更新yum 常用命令listinstall选项-y remove选项-y update 结语 前言 本…

ON1 Portrait AI 2023:智能美颜,打造完美人像 mac版

在数字化时代&#xff0c;人像摄影的需求和追求愈发高涨。为了满足摄影师对于完美人像的追求&#xff0c;ON1推出了全新的ON1 Portrait AI 2023。这款软件结合了先进的人工智能技术与人像处理的专业知识&#xff0c;为人像摄影带来了前所未有的智能体验。 ON1 Portrait AI 202…

2024.3.11

1.结构体数组 代码&#xff1a; #include<myhead.h>struct Stu {char name[100];int age;double score; };int main(int argc, const char *argv[]) {int i,j;struct Stu t{"z",1,1};struct Stu arr[4]{{"甲乙",12,98},{"陈二",13,77},{…

docker启动时环境变量不生效(docker打包成镜像后环境变量失效)

前言 因项目需要多处部署&#xff0c;为了部署的方便&#xff0c;于是准备将项目环境打包成docker镜像以便于部署。mq、mysql这些在仓库中都有现成的镜像&#xff0c;虽然java和nginx的也都有&#xff0c;但是不知道当时是怎么想的&#xff0c;就不想搞太多镜像&#xff0c;也…