STM32之SDIO通讯接口和SD卡(九)

news2025/1/19 3:07:25

STM32F407 系列文章 - SDIO-To-SD Card(九)


目录

前言

一、SDIO接口

二、SD卡

三、实现程序

1.SD卡结构体参数说明

2.头文件定义

3.函数sd_init()

4.函数HAL_SD_MspInit()

5.函数get_sd_card_info()

6.函数get_sd_card_state()

7.函数sd_read_disk()

8.函数sd_write_disk()

9.函数show_sdcard_info()

总结


前言

当单片机需要保存大量数据时,靠它自身的容量往往是不能满足需求的,一般采取的措施是外挂一个存储器。目前市面上存储器的种类繁多,根据它们各自特点,选择一款最适合单片机存储器,莫过于SD卡了,它不仅价格便宜、体积小、速度快、而且容量可以做到很大,并支持SPI/SDIO驱动,能满足单片机的要求。只需要少数几个IO口即可外扩一个高达32GB或以上的外部存储器,容量从几十M到几十G选择范围很大,更换也很方便,编程也简单,是单片机大容量外部存储器的首选。一般MCU都会自带SDIO接口,因此要实现此功能,需准备一块带SD卡接口的开发板,在本章中,将向大家介绍,如何通过SDIO通讯接口实现对Micor SD卡数据的读取。


一、SDIO接口

SDIO(Secure Digital Input and Output,安全数字输入输出),最早由SD协会(SD Association, SDA)于2001年发布,是在SD标准上定义的一种外设接口,不仅支持传统的存储功能,还允许设备通过SD卡接口进行输入输出操作,常见的多媒体卡(MMC卡)、SD存储卡、SDI/O卡和CEATA设备都有SDIO接口。关于SDIO更为详细的介绍可以参考下知乎上面的一篇文章,链接如下SDIO协议从入门到精通 - 知乎 (zhihu.com)。

SDIO遵循SD物理标准,因此支持SD卡的设备通常也能够兼容SDIO设备。常见的SDIO卡尺寸和普通的SD卡相同,包括标准尺寸(SD)、迷你尺寸(miniSD)和微型尺寸(microSD)‌,本文将选用microSD作为设计目标,另采用的407芯片使用自带的SDIO接口驱动,使用4位数据总线模式,最高通信速度可达 48Mhz(分频器旁路时),最高每秒可传输数据24M字节,对于一般应用足够了。407芯片的SDIO控制器包含2部分,SDIO适配器模块和APB2总线接口,其功能框图如下所示:

二、SD卡

SD卡(Secure Digital Memory Card,SD存储卡,简称SD卡),SD卡主要有SD、Mini SD和microSD三种类型,Mini SD已经被microSD取代,使用得不多。本文选用microSD作为设计目标,microSD原名Trans-flash Card(TF卡),2004年正式更名为Micro SD Card,由SanDisk(闪迪)公司发明,主要应用于嵌入式设备,具体介绍参考Micro SD卡_百度百科 (baidu.com)。

市场上卖microSD卡样式如下(示例),及对应SD通讯模式下相应引脚的含义:

与microSD卡匹配的卡座(自锁式)样式如下:

SD卡的驱动方式之一是用SDIO接口通讯,F407芯片自带SDIO接口,MCU单片机与SD卡连接示意图如下所示:

三、实现程序

SD卡的驱动

1.SD卡结构体参数说明

该结构体参数定义来自于STM32的HAL库,主要是完成对SD卡详细信息以参数化定义,具体说明及代码如下:

/** 
 * @brief SD 操作句柄结构体定义 
 */ 
typedef struct { 
    SD_TypeDef *Instance;     /* SD 相关寄存器基地址 */ 
    SD_InitTypeDef Init;      /* SDIO 初始化变量 */ 
    HAL_LockTypeDef Lock;     /* 互斥锁,用于解决外设访问冲突 */ 
    uint8_t *pTxBuffPtr;      /* SD 发送数据指针 */ 
    uint32_t TxXferSize;      /* SD 发送缓存按字节数的大小 */ 
    uint8_t *pRxBuffPtr;      /* SD 接收数据指针 */ 
    uint32_t RxXferSize;      /* SD 接收缓存按字节数的大小 */ 
    __IO uint32_t Context;    /* HAL 库对 SD 卡的操作阶段 */ 
    __IO HAL_SD_StateTypeDef State; /* SD 卡操作状态 */ 
    __IO uint32_t ErrorCode;        /* SD 卡错误代码 */ 
    DMA_HandleTypeDef *hdmatx;      /* SD DMA 数据发送指针 */ 
    DMA_HandleTypeDef *hdmarx;      /* SD DMA 数据接收指针 */ 
    HAL_SD_CardInfoTypeDef SdCard;  /* SD 卡信息的 */ 
    uint32_t CSD[4];                /* 保存 SD 卡 CSD 寄存器信息 */ 
    uint32_t CID[4];                /* 保存 SD 卡 CID 寄存器信息 */ 
} SD_HandleTypeDef;

/** 
 * @brief SD 卡信息结构定义 
 */ 
typedef struct { 
    uint32_t CardType;     /* 存储卡类型标记:标准卡、高速卡 */ 
    uint32_t CardVersion;  /* 存储卡版本 */ 
    uint32_t Class;        /* 卡类型 */ 
    uint32_t RelCardAdd;   /* 卡相对地址 */ 
    uint32_t BlockNbr;     /* 卡存储块数 */ 
    uint32_t BlockSize;    /* SD 卡每个存储块大小 */ 
    uint32_t LogBlockNbr;  /* 以块表示的卡逻辑容量 */ 
    uint32_t LogBlockSize; /* 以字节为单位的逻辑块大小 */ 
} HAL_SD_CardInfoTypeDef;

2.头文件定义

这里完成对IO引脚的定义和操作方式,并定义了SD卡的一些操作函数定义,代码如下(示例):

/* SDIO的信号线: SD_D0 ~ SD_D3/SD_CLK/SD_CMD 引脚 定义 
 * 如果你使用了其他引脚做SDIO的信号线,修改这里写定义即可适配.
 */
#define SD_D0_GPIO_PORT                GPIOC
#define SD_D0_GPIO_PIN                 GPIO_PIN_8
/* 所在IO口时钟使能 */
#define SD_D0_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) 
   
#define SD_D1_GPIO_PORT                GPIOC
#define SD_D1_GPIO_PIN                 GPIO_PIN_9
/* 所在IO口时钟使能 */
#define SD_D1_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)    

#define SD_D2_GPIO_PORT                GPIOC
#define SD_D2_GPIO_PIN                 GPIO_PIN_10
/* 所在IO口时钟使能 */
#define SD_D2_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)    

#define SD_D3_GPIO_PORT                GPIOC
#define SD_D3_GPIO_PIN                 GPIO_PIN_11
/* 所在IO口时钟使能 */
#define SD_D3_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)   

#define SD_CLK_GPIO_PORT               GPIOC
#define SD_CLK_GPIO_PIN                GPIO_PIN_12
/* 所在IO口时钟使能 */
#define SD_CLK_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)   

#define SD_CMD_GPIO_PORT               GPIOD
#define SD_CMD_GPIO_PIN                GPIO_PIN_2
/* 所在IO口时钟使能 */
#define SD_CMD_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)    

#define SD_TIMEOUT             ((uint32_t)100000000)    /* 超时时间 */
#define SD_TRANSFER_OK         ((uint8_t)0x00)
#define SD_TRANSFER_BUSY       ((uint8_t)0x01)

/* 根据 SD_HandleTypeDef 定义的宏,用于快速计算容量 */
#define SD_TOTAL_SIZE_BYTE(__Handle__)  (((uint64_t)((__Handle__)->SdCard.LogBlockNbr) * ((__Handle__)->SdCard.LogBlockSize)) >> 0)
#define SD_TOTAL_SIZE_KB(__Handle__)    (((uint64_t)((__Handle__)->SdCard.LogBlockNbr) * ((__Handle__)->SdCard.LogBlockSize)) >> 10)
#define SD_TOTAL_SIZE_MB(__Handle__)    (((uint64_t)((__Handle__)->SdCard.LogBlockNbr) * ((__Handle__)->SdCard.LogBlockSize)) >> 20)
#define SD_TOTAL_SIZE_GB(__Handle__)    (((uint64_t)((__Handle__)->SdCard.LogBlockNbr) * ((__Handle__)->SdCard.LogBlockSize)) >> 30)

/*  
 *  SD传输时钟分频,由于HAL库运行效率低,很容易产生上溢(读SD卡时)/下溢错误(写SD卡时)
 *  使用4bit模式时,需降低SDIO时钟频率,将该宏改为 1,SDIO时钟频率:48/( SDIO_TRANSF_CLK_DIV + 2 ) = 16M * 4bit = 64Mbps 
 *  使用1bit模式时,该宏SDIO_TRANSF_CLK_DIV改为 0,SDIO时钟频率:48/( SDIO_TRANSF_CLK_DIV + 2 ) = 24M * 1bit = 24Mbps 
 */
#define  SDIO_TRANSF_CLK_DIV        1   

extern SD_HandleTypeDef        g_sdcard_handler;        /* SD卡句柄 */
extern HAL_SD_CardInfoTypeDef  g_sd_card_info_handle;   /* SD卡信息结构体 */

/* 函数声明 */
uint8_t sd_init(void);                                              /* 初始化SD卡 */
uint8_t get_sd_card_info(HAL_SD_CardInfoTypeDef *cardinfo);         /* 获取卡信息函数 */
uint8_t get_sd_card_state(void);                                    /* 获取卡的状态 */
uint8_t sd_read_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt);  /* 读SD卡 */
uint8_t sd_write_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt); /* 写SD卡 */
void show_sdcard_info(void);  

3.函数sd_init()

SD卡初始化函数,被main函数调用,主要是完成对SDIO结构体的控制句柄填充,即将该结构体类型指针变量初始化,然后使用HAL库的HAL_SD_Init初始化函数即可,在此过程中HAL_SD_Init会调用函数 HAL_SD_MspInit回调函数,根据外设的情况,我们可以设置数据总线宽度为4位,代码如下(示例):

SD_HandleTypeDef g_sdcard_handler;            /* SD卡句柄 */
HAL_SD_CardInfoTypeDef g_sd_card_info_handle; /* SD卡信息结构体 */

/**
 * @brief       初始化SD卡
 * @param       无
 * @retval      返回值:0 初始化正确;其他值,初始化错误
 */
uint8_t sd_init(void)
{
    uint8_t SD_Error;
    /* 初始化时的时钟不能大于400KHZ */
    g_sdcard_handler.Instance = SDIO;
    g_sdcard_handler.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;  /* 上升沿 */
    /* 不使用bypass模式,直接用HCLK进行分频得到SDIO_CK */
    g_sdcard_handler.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
    /* 空闲时不关闭时钟电源 */  
    g_sdcard_handler.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;           
    g_sdcard_handler.Init.BusWide = SDIO_BUS_WIDE_1B;      /* 1位数据线 */
    /* 关闭硬件流控 */
    g_sdcard_handler.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; 
    g_sdcard_handler.Init.ClockDiv = SDIO_TRANSF_CLK_DIV;  /* SD传输时钟频率最大25MHZ */

    SD_Error = HAL_SD_Init(&g_sdcard_handler);
    if (SD_Error != HAL_OK)
        return 1;
    HAL_SD_GetCardInfo(&g_sdcard_handler, &g_sd_card_info_handle);  /* 获取SD卡信息 */
    /* 使能4bit宽总线模式 */
    SD_Error = HAL_SD_ConfigWideBusOperation(&g_sdcard_handler, SDIO_BUS_WIDE_4B);  
    if (SD_Error != HAL_OK)
        return 2;
    return 0;
}

4.函数HAL_SD_MspInit()

完成SDIO底层驱动,时钟使能,引脚配置,被sd_init()函数中的HAL_SD_Init函数调用,代码如下(示例):

/**
 * @brief       SDIO底层驱动,时钟使能,引脚配置
                此函数会被HAL_SD_Init()调用
 * @param       hsd:SD卡句柄
 * @retval      无
 */
void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
{
    GPIO_InitTypeDef gpio_init_struct;
    __HAL_RCC_SDIO_CLK_ENABLE();    /* 使能SDIO时钟 */
    SD_D0_GPIO_CLK_ENABLE();        /* D0引脚IO时钟使能 */
    SD_D1_GPIO_CLK_ENABLE();        /* D1引脚IO时钟使能 */
    SD_D2_GPIO_CLK_ENABLE();        /* D2引脚IO时钟使能 */
    SD_D3_GPIO_CLK_ENABLE();        /* D3引脚IO时钟使能 */
    SD_CLK_GPIO_CLK_ENABLE();       /* CLK引脚IO时钟使能 */
    SD_CMD_GPIO_CLK_ENABLE();       /* CMD引脚IO时钟使能 */

    gpio_init_struct.Pin = SD_D0_GPIO_PIN;              /* SD_D0引脚模式设置 */
    gpio_init_struct.Mode = GPIO_MODE_AF_PP;            /* 推挽复用 */
    gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;      /* 高速 */
    gpio_init_struct.Alternate = GPIO_AF12_SDIO;        /* 复用为SDIO */
    HAL_GPIO_Init(SD_D0_GPIO_PORT, &gpio_init_struct);  /* 初始化 */
    gpio_init_struct.Pin = SD_D1_GPIO_PIN;              /* SD_D1引脚模式设置 */
    HAL_GPIO_Init(SD_D1_GPIO_PORT, &gpio_init_struct);  /* 初始化 */

    gpio_init_struct.Pin = SD_D2_GPIO_PIN;              /* SD_D2引脚模式设置 */
    HAL_GPIO_Init(SD_D2_GPIO_PORT, &gpio_init_struct);  /* 初始化 */

    gpio_init_struct.Pin = SD_D3_GPIO_PIN;              /* SD_D3引脚模式设置 */
    HAL_GPIO_Init(SD_D3_GPIO_PORT, &gpio_init_struct);  /* 初始化 */

    gpio_init_struct.Pin = SD_CLK_GPIO_PIN;             /* SD_CLK引脚模式设置 */
    HAL_GPIO_Init(SD_CLK_GPIO_PORT, &gpio_init_struct); /* 初始化 */

    gpio_init_struct.Pin = SD_CMD_GPIO_PIN;             /* SD_CMD引脚模式设置 */
    HAL_GPIO_Init(SD_CMD_GPIO_PORT, &gpio_init_struct); /* 初始化 */
}

5.函数get_sd_card_info()

获取卡信息函数,代码如下(示例):

/**
 * @brief       获取卡信息函数
 * @param       cardinfo:SD卡信息句柄
 * @retval      返回值:读取卡信息状态值
 */
uint8_t get_sd_card_info(HAL_SD_CardInfoTypeDef *cardinfo)
{
    uint8_t sta;
    sta = HAL_SD_GetCardInfo(&g_sdcard_handler, cardinfo);
    return sta;
}

6.函数get_sd_card_state()

获取卡状态函数,判断SD卡是否可以传输(读写)数据,代码如下(示例):

/**
 * @brief       判断SD卡是否可以传输(读写)数据
 * @param       无
 * @retval      返回值:SD_TRANSFER_OK      传输完成,可以继续下一次传输
                       SD_TRANSFER_BUSY SD 卡正忙,不可以进行下一次传输
 */
uint8_t get_sd_card_state(void)
{
    return ((HAL_SD_GetCardState(&g_sdcard_handler) == HAL_SD_CARD_TRANSFER) ?
         SD_TRANSFER_OK : SD_TRANSFER_BUSY);
}

7.函数sd_read_disk()

完成对SD卡中数据信息读取,代码如下(示例):

/**
 * @brief       读SD卡(fatfs/usb调用)
 * @param       pbuf  : 数据缓存区
 * @param       saddr : 扇区地址
 * @param       cnt   : 扇区个数
 * @retval      0, 正常;  其他, 错误代码(详见SD_Error定义);
 */
uint8_t sd_read_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt)
{
    uint8_t sta = HAL_OK;
    uint32_t timeout = SD_TIMEOUT;
    long long lsector = saddr;
    
    __disable_irq();   /* 关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!) */                                                                 
    sta = HAL_SD_ReadBlocks(&g_sdcard_handler, (uint8_t *)pbuf, lsector, cnt, 
            SD_TIMEOUT); /* 多个sector的读操作 */
    /* 等待SD卡读完 */
    while (get_sd_card_state() != SD_TRANSFER_OK)
    {
        if (timeout-- == 0)
            sta = SD_TRANSFER_BUSY;
    }
    __enable_irq();    /* 开启总中断 */

    return sta;
}

8.函数sd_write_disk()

完成对SD卡中数据信息写入,代码如下(示例):

/**
 * @brief       写SD卡(fatfs/usb调用)
 * @param       pbuf  : 数据缓存区
 * @param       saddr : 扇区地址
 * @param       cnt   : 扇区个数
 * @retval      0, 正常;  其他, 错误代码(详见SD_Error定义);
 */
uint8_t sd_write_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt)
{
    uint8_t sta = HAL_OK;
    uint32_t timeout = SD_TIMEOUT;
    long long lsector = saddr;
    
    __disable_irq();  /* 关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!) */
    sta = HAL_SD_WriteBlocks(&g_sdcard_handler, (uint8_t *)pbuf, lsector, cnt, 
            SD_TIMEOUT); /* 多个sector的写操作 */
    /* 等待SD卡写完 */
    while (get_sd_card_state() != SD_TRANSFER_OK)
    {
        if (timeout-- == 0)
            sta = SD_TRANSFER_BUSY;
    }
    __enable_irq();     /* 开启总中断 */
    
    return sta;
}

9.函数show_sdcard_info()

打印SD卡相关信息,代码如下(示例):

/**
 * @brief       打印SD卡相关信息
 * @param       无
 * @retval      无
 */
void show_sdcard_info(void)
{
    HAL_SD_CardCIDTypeDef sd_card_cid;
    HAL_SD_GetCardCID(&g_sdcard_handler, &sd_card_cid); /* 获取CID */
    get_sd_card_info(&g_sd_card_info_handle);           /* 获取SD卡信息 */

    switch (g_sd_card_info_handle.CardType)
    {
        case CARD_SDSC:
        {
            if (g_sd_card_info_handle.CardVersion == CARD_V1_X)
                printf("Card Type:SDSC V1\r\n");
            else if (g_sd_card_info_handle.CardVersion == CARD_V2_X)
                printf("Card Type:SDSC V2\r\n");
        }
        break;

        case CARD_SDHC_SDXC:
            printf("Card Type:SDHC\r\n");
            break;
        default: break;
    }
    /* 制造商ID */
    printf("Card ManufacturerID:%d\r\n", sd_card_cid.ManufacturerID); 
    /* 卡相对地址 */                       
    printf("Card RCA:%d\r\n", g_sd_card_info_handle.RelCardAdd);          
    /* 显示逻辑块数量 */
    printf("LogBlockNbr:%d \r\n", (uint32_t)(g_sd_card_info_handle.LogBlockNbr));
    /* 显示逻辑块大小 */       
    printf("LogBlockSize:%d \r\n", (uint32_t)(g_sd_card_info_handle.LogBlockSize));
    /* 显示容量 */
    printf("Card Capacity:%d MB\r\n", (uint32_t)SD_TOTAL_SIZE_MB(&g_sdcard_handler));
    /* 显示块大小 */
    printf("Card BlockSize:%d\r\n\r\n", g_sd_card_info_handle.BlockSize); 
}

总结

这章完成是STM32的SDIO通讯接口和SD卡介绍,为下一章FATFS文件系统做铺垫。

下面提供的代码,基于STM32F407ZGT芯片编写,可直接在原子开发板上运行,也可运行在各工程项目上,但需要注意各接口以及相应的引脚应和原子开发板上保持一致。

相应的代码链接:代码程序

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

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

相关文章

Vue 提供了Transition,可以帮助你制作基于状态变化的过渡和动画

官方文档&#xff1a;https://cn.vuejs.org/guide/built-ins/transition.html Transition​ Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动画&#xff1a; <Transition> 会在一个元素或组件进入和离开 DOM 时应用动画。本章节会介绍如何使用…

04 创建一个属于爬虫的主虚拟环境

文章目录 回顾conda常用指令创建一个爬虫虚拟主环境Win R 调出终端查看当前conda的虚拟环境创建 spider_base 的虚拟环境安装完成查看环境是否存在 为 pycharm 配置创建的爬虫主虚拟环境选一个盘符来存储之后学习所写的爬虫文件用 pycharm 打开创建的文件夹pycharm 配置解释器…

鸿蒙UI开发——渐变色效果

1、概 述 ArkTs可以通过颜色渐变接口&#xff0c;设置组件的背景颜色渐变效果&#xff0c;实现在两个或多个指定的颜色之间进行平稳的过渡。 目前提供三种渐变类型&#xff1a;线性渐变、角度渐变、径向渐变。 我们在鸿蒙UI布局实战 —— 个人中心页面开发中&#xff0c;默认…

渗透测试--数据库攻击

这篇文章瘾小生其实想了很久&#xff0c;到底是放在何处&#xff0c;最终还是想着单拎出来总结&#xff0c;因为数据库攻击对我们而言非常重要&#xff0c;而且内容众多。本篇文章将讲述在各位获取数据库权限的情况下&#xff0c;各个数据库会被如何滥用&#xff0c;以及能够滥…

Java——异常机制(上)

1 异常机制本质 (异常在Java里面是对象) (抛出异常&#xff1a;执行一个方法时&#xff0c;如果发生异常&#xff0c;则这个方法生成代表该异常的一个对象&#xff0c;停止当前执行路径&#xff0c;并把异常对象提交给JRE) 工作中&#xff0c;程序遇到的情况不可能完美。比如…

Idea Spring Initializr没有 Java 8选项解决办法

问题描述 在使用IDEA中的Spring Initializr创建新项目时&#xff0c;Java 版本近可选择Java17,21 。不能选择Java8;SpringBoot 版本也只有 3.x 问题原因 Spring 官方&#xff08; https://start.spring.io/&#xff09;不再提供旧版本的初始化配置 解决方案 方案 1 使用阿里…

npm发布插件到私有仓库保姆级教程

在开发项目的过程中&#xff0c;我们经常需要安装插件依赖&#xff0c;那么怎么把自己开发的组件封装成一个插件&#xff0c;并发布到npm 插件市场或者上传到私有仓库里面呢&#xff1f;今天总结下自己发布插件到私有仓库的记录&#xff1a; 一、创建组件 执行命令创建一个空…

渗透测试---burpsuite(5)web网页端抓包与APP渗透测试

声明&#xff1a;学习素材来自b站up【泷羽Sec】&#xff0c;侵删&#xff0c;若阅读过程中有相关方面的不足&#xff0c;还请指正&#xff0c;本文只做相关技术分享,切莫从事违法等相关行为&#xff0c;本人与泷羽sec团队一律不承担一切后果 视频地址&#xff1a;泷羽---bp&…

关闭windows11的“热门搜索”

win10搜索栏热门搜索怎么关闭&#xff1f;win10搜索栏热门搜索关闭方法分享_搜索_onecdll-GitCode 开源社区 注册表地址是&#xff1a;计算机\HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\ 最后效果如下&#xff1a;

【MySQL】视图详解

视图详解 一、视图的概念二、视图的常用操作2.1创建视图2.2查询视图2.3修改视图2.4 删除视图2.5向视图中插入数据 三、视图的检查选项3.1 cascaded&#xff08;级联 &#xff09;3.2 local(本地) 四、视图的作用 一、视图的概念 视图&#xff08;View&#xff09;是一种虚拟存…

数据结构 (22)哈夫曼树及其应用

前言 哈夫曼树&#xff08;Huffman Tree&#xff09;&#xff0c;又称最优二叉树或最优树&#xff0c;是一种特殊的二叉树结构&#xff0c;其带权路径长度&#xff08;WPL&#xff09;最短。 一、哈夫曼树的基本概念 定义&#xff1a;给定N个权值作为N个叶子结点&#xff0c;构…

Jenkins 的HTTP Request 插件为什么不能配置Basic认证了

本篇遇到的问题 还是因为Jenkins需要及其所在的OS需要升级&#xff0c;升级策略是在一台新服务器上安装和配置最新版本的Jenkins&#xff0c; 当前的最新版本是&#xff1a; 2.479.2 LTS。 如果需要这个版本的话可以在官方站点下载&#xff0c;也可以到如下地址下载&#xff1…

1.1 Beginner Level学习之“创建 ROS msg 和 srv”(第十节)

学习大纲&#xff1a; 1. msg 和 srv msg 文件是描述 ROS 消息字段的简单文本文件。它们用于为不同语言生成消息的源代码。srv 文件则描述了一个服务&#xff0c;包括两部分&#xff1a;请求和响应。Srv 文件用于生成服务的源代码。msg 文件存储在包的 msg 目录中。srv 文件存…

ubuntu中使用ffmpeg库进行api调用开发

一般情况下&#xff0c;熟悉了ffmpeg的命令行操作&#xff0c;把他当成一个工具来进行编解码啥的问题不大&#xff0c;不过如果要把功能集成进自己的软件中&#xff0c;还是要调用ffmpeg的api才行。 ffmpeg的源码和外带的模块有点太多了&#xff0c;直接用官网别人编译好的库就…

deepsort复现报错TypeError: tuple indices must be integers or slices, not tuple 解决

deepsort复现中遇到的TypeError: tuple indices must be integers or slices, not tuple问题的解决-CSDN博客 以上为参考教程。 复现的时候出现这个报错&#xff0c;搞了好久试了好多方法&#xff0c;包括降 scikit-learn版本&#xff0c;都不行&#xff0c;最后终于找到这个博…

Rigol DP711自动控制--SCPI命令

通过串口的SCPI命令来控制通道输入输出 也可以用UltraSigma UI来发送SCPI 物理连接&#xff1a; Pin2_2, Pin3_3, Pin5_5 串口命令控制&#xff1a; 命令&#xff1a;9600&#xff0c; 8bit, None SCPI CMD(Standard Commands for Programmable Instruments) OUTPut CH1, On…

【Java Web】Tomcat 快速入门

通常&#xff0c;为了让 Java 开发的应用程序&#xff08;app&#xff09;能够在服务器上正常运行&#xff0c;必须安装 Java 运行时环境&#xff08;JRE&#xff09;。JRE 主要支持 Java SE&#xff0c;而如果要运行 Java EE 应用&#xff0c;则需要更多的支持&#xff0c;比如…

RabbitMQ延迟消息的实现

RabbitMQ延迟队列的实现 延迟消息是什么延迟消息的实现死信交换机代码实现 延迟消息插件 延迟消息是什么 延迟消息是将消息发送到MQ中&#xff0c;消费者不会立即收到消息&#xff0c;而是过一段时间之后才会收到消息&#xff0c;进行处理。在一些业务中&#xff0c;可以用到延…

SpringMvc完整知识点一

SpringMVC概述 定义 SpringMVC是一种基于Java实现MVC设计模型的轻量级Web框架 MVC设计模型&#xff1a;即将应用程序分为三个主要组件&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff09;。这种分离…

强化学习新突破:情节记忆与奖励机制引领多智能体协作

简介 本推文介绍了韩国科学技术院发表在人工智能顶会ICLR 2024上的论文《Efficient Episodic Memory Utilization of Cooperative Multi-Agent Reinforcement Learning》。该论文提出创新性高效情节记忆利用&#xff08;Efficient Episodic Memory Utilization&#xff0c;EMU…