【STM32】SD卡

(一)常用卡的认识

在学习这个内容之前,作为生活小白的我对于SD卡、TF卡、SIM卡毫无了解,晕头转向。

SD卡:Secure Digital Card的英文缩写,直译就是“安全数字卡”。一般用于大一些的电子设备比如:电脑、数码相机、AV等,做外存储器用。

TF卡:T-Flash卡,又叫micro SD卡,即微型SD卡。TF卡内存比较小,一般用于手机、mp4等小型数码电子产品的外存储器用。

tf卡是什么卡?-百度经验

SIM卡:用户身份识别卡,差不多就是手机卡,智能卡

SIM卡我们非常熟知,当做手机卡等在用,那TF卡和SD卡又有什么区别呢?

(1)卡的外形不同:SD卡比TF卡的尺寸要大,SD卡上有一个lock开关,即写保护开关,而TF卡没有

(2)转换代替:TF卡插入适配器可以转换成SD卡,但是SD卡一般无法转换成TF卡

img

(二)SD卡介绍

特点:容量大、高安全性、体积小

1.种类

SD存储容量等级分为四种

塔尔杰塔斯微型SD梅约雷斯

SDSC---标准容量SD卡【第一张卡,利用 FAT32 文件系统 因此它不能超过 2 GB的存储空间 ,目前它们已退出市场。】

最高2GB

SDHC---高容量SD存储卡【他们的能力范围从 2 GB至32 GB ,也因存储容量低而退出当前市场。 它是第一个使用 exFAT文件系统

2GB-32GB

SDXC---容量扩大化的安全存储卡(基于NAN闪存技术)【今天最常用的,因为它可以达到 2 TB的存储空间

32GB-2TB

SDUC---超容量SD存储卡【如果 2 TB 的容量对您来说太少,那么您可以选择 SDUC,但是它们目前稀有且昂贵,到时候还是将取代 SDXC】

2TB-128TB

注意:STM32最大仅支持32GB SD卡

2.文件形式

如果你对SD卡跟EEPROM或者NOR FLASH操作,读写数据并验证数据的准确性,则不需要FAT文件系统

但是,SD卡经常被用在Windows操作系统上存取数据,就就得使用操作系统支持的FAT文件系统

3.速度等级

SD卡还根据读写速度划分为不同的速度等级,以满足不同应用场景的需求:

写入速度等级有三个参数表示,分别是普通的速度等级Speed Class(C),超高速速度等级UHS Speed Class(U),视频速度等级Video Speed Class*(V),代表数字表示最低写入速度。

img

【C】普通的速度等级Speed Class ​ 有Class 2、Class 4、Class 6和Class 10,简写为C2、C4、C6、C10,分别表示最低写入速度为2MB/s、4MB/s、6MB/s、10MB/s。C10代表可用于高速或更高速的模式。

【U】超高速速度等级UHS Speed Class ​ UHS Speed Class 1和UHS Speed Class 3,简写为U1、U3。U1代表最低写入速度为10M/S,U3代表最低写入速度为30M/S。UHS与U1/U3(UHS Speed Class)不同,不要弄混了。一个是接口标准,一个是速度

【V】视频速度等级Video Speed Class ​ 有V6、V10、V30、V60和V90,V后面的数字表示最低写入速度,单位MB/s,V6表示最低写入速度为6MB/s,V90表示最低写入速度为90MB/s。这个参数对录制视频来说非常重要,录制不同画质的视频对存储卡视频速度等级也不一样。如果要录制4k画质视频,必须要用V30以上的存储卡。

(三)SD卡的驱动介绍

1.SD卡引脚以及接口

9pinSD卡内部结构

SD 卡允许不同的接口来访问它的内部存储单元。最常见的是 SDIO 模式SPI 模式,根据这两种接口模式,我们也列出 SD 卡引脚对应于这两种不同的电路模式的引脚功能定义

microSD 引脚,比 SD 卡少了一个电源引脚 VSS2,其它的引脚功能类似,操作时序也完全相同,所以可以用完全相同的代码驱动

2.SD卡寄存器

SD卡有8个寄存器,但是不能直接进行读写操作,需要通过命令来控制。SD卡根据收到的命令要求对内部寄存器进行修改

3.SD命令以及响应

一个完整的 SD 卡操作过程是:主机(单片机等)发起“命令”--》SD 卡根据命令的内容决定是否发送响应信息及数据等,如果是数据读/写操作,主机还需要发送停止读/写数据的命令来结束本次操作,这意味着主机发起命令指令后,SD 卡可以没有响应、数据等过程,这取决于命令的含义。

(1)命令格式

SD卡命令格式由6个字节所组成,发送数据时高位在前,SD卡的写入命令格式如下:

SD 卡的命令固定为 48 位,由 6 个字节组成,字节 1 的最高 2 位固定为 01,低 6 位为命令 号(比如 CMD16,为 10000B 即 16 进制的 0X10,完整的 CMD16,第一个字节为 01010000, 即 0X10+0X40)。字节 2~5为命令参数,有些命令是没有参数的。字节 6 的高七位为 CRC 值, 最低位恒定为 1

(2)SD卡命令

SD 卡的命令总共有 12 类,分为 Class0~Class11,以下为一些重要命令

上图中,大部分的命令是初始化的时候用的,而表中的 R1、R1b、R2、R3、R6 和 R7 等是 SD卡的应答信号。在主机发送有响应的命令后,SD卡都会给出相对应的应答,以告知主机 该命令的执行情况,或者返回主机需要获取的数据。

(2)SD卡响应

响应,分为长响应136bit、短响应48bit。R1、R1b、 R3、R6 和 R7 属于短响应,而 R2 属于长响应(若使用SDLO接口时,响应通过cmd线传输)

(3)响应接口格式

响应因使用接口不同,格式也不同

(4)卡模式

在SD卡系统(主机和SD卡)定义了两种操作模式:卡识别模式(识别总线上的SD卡类型)和数据传输模式(读写操作)

系统复位后,主机和SD卡都处于卡识别模式,主机在总线上找设备。当SD卡被识别后,SD卡也进入数据传输模式,而主机在总线上是所有卡都被识别后也进入数据传输模式

只关注两个模式:卡识别模式和数据传输模式就好了。

系统复位之后,主机处于卡识别模式,寻找总线上可用的 SDIO 设备,对 SD 卡进行数据读写之前需要识别卡的种类: V1.0 标准卡、V2.0 标准卡、V2.0 高容量卡或者不被识别卡;同时,SD 卡也处于卡识别模式, 直到被主机识别到,即当 SD 卡在卡识别状态接收到 CMD3 (SEND_RCA)命令后,SD 卡就进 入数据传输模式,而主机在总线上所有卡被识别后也进入数据传输模式。

卡识别模式下,主机会复位所有处于“卡识别模式”的 SD 卡,确认其工作电压范围, 识别 SD 卡类型,并且获取 SD 卡的相对地址(卡相对地址较短,便于寻址)。在卡识别过程中, 要求 SD 卡工作在识别时钟频率 FOD 的状态下

  • 上电

  • CMD0【软件复位】

  • CMD8【主机询问SD卡是否支持电压范围】(V2.0卡支持该命令,V1.x和MMC卡不支持)

    • 如果R1响应,ACMD41

      • R3响应【判断是高容量还是标准】(响应R3中返回OCR寄存器:CCS1 高容量V2.0卡,CCS0 标准V2.0卡)

    • 如果R1不响应,ACMD41【用于判断是V1.x卡还是MMC卡,其中MMC不支持】

      • R1响应,则为V1.x卡

      • R1不响应,CMD1【判断MMC卡或其他不能被识别的卡,其中CMD1激活MMC卡】

        • 响应则是MMC卡

主机上电后,所有卡处于空闲状态,包括当前处于无效状态的卡。主机也可以发送 GO_IDLE_STATE(CMD0)让所有卡软复位从而进入空闲状态,但当前处于无效状态的卡并不 会复位。 主机在开始与卡通信前,需要先确定双方在互相支持的电压范围内。SD 卡有一个电压支持范围,主机当前电压必须在该范围可能才能与卡正常通信。

SEND_IF_COND(CMD8)命令就是用于验证卡接口操作条件的(主要是电压支持)。卡会根据命令的参数来检测操作条件匹配性,如果卡支持主机电压就产生响应,否则不响应。而主机则根据响应内容确定卡的电压匹配性。

SD_SEND_OP_COND(ACMD41)命令可以识别或拒绝不匹配它的电压范围的卡。 ACMD41 命令的 VDD 电压参数用于设置主机支持电压范围,卡响应会返回卡支持的电压范围。

ALL_SEND_CID(CMD2)用来控制所有卡返回它们的卡识别号(CID),处于准备状态的卡 在发送 CID之后就进入识别状态。之后主机就发送 SEND_RELATIVE_ADDR(CMD3)命令,让 卡自己推荐一个相对地址(RCA)并响应命令。这个 RCA 是 16bit 地址,而 CID 是 128bit 地址, 使用 RCA 简化通信。卡在接收到 CMD3 并发出响应后就进入数据传输模式,并处于待机状态, 主机在获取所有卡 RCA 之后也进入数据传输模式。

下图为数据传播模式卡状态转换

(5)数据块读取流程

1.SD卡单块数据块读取流程

  1. 发送CMD16指令,设置数据块大小

  2. 等待CMD16响应(R1)

  3. 发送CMD17指令,开始读取数据

  4. 等待CMD17响应(R1)

  5. 读一个数据块的数据

    其中注意的是:CMD16设置的数据块大小,一般是512字节,此设置直接决定了SD卡的块大小,SD卡默认的块大小自动失效

2.SD卡多块数据块读取流程

  1. 发送CMD16指令,设置数据块大小

  2. 等待CMD16响应(R1)

  3. 发送 CMD18指令,开始读数据块

  4. 等待CMD18响应(R1)

  5. 读一个数据块的数据

  6. 读两个数据块的数据

  7. 读n个数据块的数据

  8. 发送CMD12指令,结束数据块读取

  9. 等待CMD12响应(R1)

  10. 结束多块数据块读取

(5)数据传输格式

SD卡有两种数据模式,一种是常规的 8位宽,即一次按一字节传输,另一种是一次按 512 字节传输,我们只介绍前面一种。当按 8-bit 连续传输时,每次传输从最低字节开始,每字节从最高位(MSB)开始发送,当使用一条数据线时,只能通过 DAT0** 进行数据传输

当使用 4 线模式传输 8-bit 结构的数据时,数据仍按 MSB 先发送的原则,DAT[3:0]的高位发送高数据位,低位发送低数据位。其特点为可提升传输速率。

(四)STM32驱动SD卡代码解析

1.原理图:

(1)SDIO_CK ---> 产生时钟

[SDIO_CK = SDIOCLK【48MHZ】 / ( 2 + CLKDIV ) SD卡初始化时,SDIO_CK不可超过400Khz,初始化完成之后,可设为最大操作频率(但不能超过25Mhz) ]  

(2)SDIO_CMD ---> 发送命令、接收响应

(3)SDIO_D ---> 双向传输数据

2.STM32F4 HAL函数

HAL库有为我们准备专门驱动SD卡的代码,主要存放在 stm32f4xx_hal_sd.c/h 下。

(1)HAL_SD_Init函数

初始化SIOD外设操作,其声明如下

HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)

形参是一个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;

其中的

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)HAL_SD_ConfigWideBusOperation 函数

SD 卡上电后默认使用 1 位数据总线进行数据传输,卡如果允许,可以在初始化完成后重新设置 SD 卡的数据位宽以加快数据传输过程,以下是可修改的总线宽度值

#define SDIO_BUS_WIDE_1B ((uint32_t)0x00000000U)
#define SDIO_BUS_WIDE_4B SDIO_CLKCR_WIDBUS_0
#define SDIO_BUS_WIDE_8B SDIO_CLKCR_WIDBUS_1

(3) HAL_SD_ReadBlocks 函数

SD 卡初始化后从 SD 卡的指定扇区读一定数量的数据:

HAL_StatusTypeDef HAL_SD_ReadBlocks (SD_HandleTypeDef *hsd, uint8_t *pData,
uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout);

(4)HAL_SD_WriteBlocks 函数

SD 卡初始化后,在 SD 卡的指定扇区写入一定数量的数据

HAL_StatusTypeDef HAL_SD_WriteBlocks (SD_HandleTypeDef *hsd, uint8_t *pData,
uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout);

(5)HAL_SD_GetCardInfo 函数

SD 卡初始化后,根据设备句柄读 SD 卡的相关状态信息

HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd,HAL_SD_CardInfoTypeDe*pCardInfo);
3.SDIO驱动SD卡关键代码
(1)使能SDIO和相关GPIO时钟,设置好GPIO工作模式
(2)初始化SDIO
(3)初始化SD卡

sd_init 函数:填充SDMMC结构体的控制句柄,然后使用HAL库的 HAL_SD_Init 初始化函数即可,在此过程中 HAL_SD_Init 会调用 HAL_SD_MspInit 函数回调函数,根据外设的情况,我们可以设置数据总线宽度为 4 位

(4)SD卡读取扇区数据

上我们使用它来对 HAL 库的读函数 HAL_SD_ReadBlocks进行了二次封装,并在最后加入了状态判断以使后续操作(实际上这部分代码也可以省略),直接根据读函数返回值自己作其它处理。为了保护 SD 卡的数据操作,我们在进行操作时暂时关闭了中断以防止数据读过程发生意外。

(5)SD卡写入扇区数据

我们使用它来对 HAL 库的写函数 HAL_SD_WriteBlocks 进行了二次封装,并在最后加入了状态判断以使后续操作(实际上这部分代码也可以省略),直接根据写函数返回值自己作其它处理。为了保护 SD 卡的数据操作,我们在进行操作时暂时关闭了中断以防止数据写过程发生意外。

4.SPI驱动SD卡步骤
(1)SD卡初始化

SPI操作模式下:在SD卡收到复位命令时,CS为有效电平(低电平),则SPI模式被启用,在发送CMD之前要先发送74个时钟,64个为内部供电上升时间,10个用于SD卡同步;之后才能开始CMD操作,在初始化时CLK时钟不能超过400KHz

(1)初始化与SD卡连接的硬件条件(MCU的SPI配置,IO口配置)

(2)上电延时(>74个CLK)

(3)复位卡(CMD0),进入IDLE状态

(4)发送CMD8,检查是否支持2.0协议

(5)根据不同协议检查SD卡(命令包括:CMD55、CMD41、CMD58和CMD1等)

(6)取消片选,发多8个CLK,结束初始化

这样我们就完成了对SD卡的初始化,注意末尾发送的8个CLK是提供SD卡额外的时钟,完成某些操作。通过SD卡初始化,我们可以知道SD卡的类型(V1、V2、V2HC或者MMC),在完成了初始化之后,就可以开始读写数据了。

(2)SD卡读扇区数据

(1)发送CMD17

(2)接收卡响应R1

(3)接收数据起始令牌0XFE

(4)接收数据

(5)接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉

(6)禁止片选之后,发多8个CLK

(3)SD卡写入数据

(1)发送CMD24

(2)接收卡响应R**1**

(3)发送写数据起始令牌0XFE

(4)发送数据

(5)发送2字节的伪CRC

(6)禁止片选之后,发多8个CLK

5.SDIO驱动SD卡实验

打开SDIO

打开中断

打开usart1

打开其中断

关键也就这两个操作,其它操作都很简单,就是配配时钟,这里要提到一个小地方:一定要打开debug当中的Serial,否则程序烧录一次之后就会识别烧录器失败!!!但也不要怕,本人一早到解决方法:BOOT0用杜邦线接3V3,然后按一下开发板上的reset键,亲测有效!!!

生成完工程之后,为了串口调试方便,在usart.c当中加入以下

#include "stdio.h"
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}/*** 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fgetc(FILE *f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1, &ch, 1, 0xffff);return ch;
}

接着在main.c文件声明SD对象

HAL_SD_CardInfoTypeDef pCardInfo;

声明

#define BLOCK_SIZE   512                            //一个块的字节数
#define NUMBERS_PER_CHUNK 512                                           //多少个数据存一次
#define INT_SIZE 1                                                      //一个数值占几个字节
#define BUFFER_SIZE (NUMBERS_PER_CHUNK * INT_SIZE)  //存一次sd卡的数组的大小(其实就是512)uint8_t buffer_TX[NUMBERS_PER_CHUNK];                           // 用于暂时存储需要发送到SD卡的数据
uint8_t buffer_RX[NUMBERS_PER_CHUNK];                           // 用于接收从SD卡中读取来的数据  

插上SD卡 在main当中添加查看SD卡信息

    HAL_SD_GetCardInfo(&hsd,&pCardInfo);printf("SD卡类型:%u\r\n",pCardInfo.CardType);          //卡的类型printf("SD卡版本:%u\r\n",pCardInfo.CardVersion); //卡的版本printf("SD卡块数:%u\r\n",pCardInfo.BlockNbr);    //SD卡块数printf("SD卡每块大小:%u\r\n",pCardInfo.BlockSize);//每一块的大小

(1)读取SD卡中的数据

 
            for(int chunk=0;chunk<1;chunk++){//计算读取的块数量uint32_t blocksToRead = BUFFER_SIZE/BLOCKSIZE;//从SD卡读取数量if(HAL_SD_ReadBlocks(&hsd,(uint8_t *)buffer_RX,blockNum,1,1000)==HAL_OK){while(HAL_SD_GetCardState(&hsd)!=HAL_SD_CARD_TRANSFER);//返回到传输状态退出for(int i=0;i<NUMBERS_PER_CHUNK;i++){printf("%d\t",buffer_RX[i]);}printf("\n读取成功!\n");}else{printf("读取失败!\n");}blockNum +=1;//更新块号读取下一个段}

由于篇幅过长,可以看下一篇文章具体讲解以及更多玩法!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11月第一篇新作,十一月对我好一点:C++之继承(2)

C之继承&#xff08;2&#xff09; 虚继承 很多⼈说C语法复杂&#xff0c;其实多继承就是⼀个体现。有了多继承&#xff0c;就存在菱形继承&#xff0c;有了菱形继承就有 菱形虚拟继承&#xff0c;底层实现就很复杂&#xff0c;性能也会有⼀些损失&#xff0c;所以最好不要设计…

tiktok批量添加达人怎么弄

在 TikTok 上批量添加达人可以借助一些工具或方法&#xff0c;以下是一些常见的途径&#xff1a; 点我达秘免费体验地址注册 使用达人邀约工具&#xff1a; 功能特点&#xff1a;这类工具专为 TikTok 跨境小店和本土小店提供服务&#xff0c;可以实现多国家、多店铺同时私信和…

重塑重工起重行业未来:网关与云平台携手共创价值新篇章

在重工起重这一传统而关键的工业领域中&#xff0c;技术的每一次革新都意味着生产效率与安全标准的飞跃。随着物联网、大数据、云计算等先进技术的不断渗透&#xff0c;重工起重行业正迎来一场前所未有的智能化变革。其中&#xff0c;网关与云平台的深度融合&#xff0c;正成为…

NPOI 操作详解(操作Excel)

目录 1. 安装 NPOI 2. 使用 NPOI 创建新 Excel 文件 3. 设置列宽和行高 1. 设置列宽 2. 设置行高 3. 同时设置列宽和行高 4. 设置统一的行高 5. 设置统一的列宽 6. 应用统一的行高和列宽 4. 合并单元格 5. 设置单元格样式&#xff08;字体、边框、背景色等&#xf…

CMS getshell

进入前台 漏洞为前台任意用户密码修改和前台用户文件上传然后getshell 1. 弱口令进入前台用户admin123/admin123 2. 进入会员用户后点击内容中心 点击发布文章 存在文件上传&#xff0c;发现后缀和MIME类型都是白名单 但是在原文件的基础上继续添加随意后缀&#xff0c;发现成功…

教你用python实现自动化文本识别

目录 步骤1&#xff1a;安装依赖 安装Tesseract 安装pytesseract和Pillow&#xff08;用于图像处理&#xff09; 扩展功能 实现自动化文本识别&#xff08;Optical Character Recognition, OCR&#xff09;通常使用Python的OCR库&#xff0c;例如Tesseract。Tesseract是一个…

逻辑磁盘管理 附实验:逻辑卷的组成与划分

分区类型&#xff1a; 1、系统引导分区 就是存放系统的引导文件和Linux的内核文件 2、swap分区 交换分区&#xff0c;系统的物理内存不足时&#xff0c;从一些长时间未运行的程序当中释放一部分内存释放出来的保存到swap分区&#xff0c;这些未运行的程序一旦运行还要从swap空…

讲讲 kafka 维护消费状态跟踪的方法?

大家好&#xff0c;我是锋哥。今天分享关于【讲讲 kafka 维护消费状态跟踪的方法&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; 讲讲 kafka 维护消费状态跟踪的方法&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Kafka 中&#x…

Flutter-Engine 的定制实践:Text 绘制流程浅析及自定义underline的间距

前言 最近工作中处理的文本相关的内容较多&#xff0c;不论是刁钻的需求还是复杂的问题&#xff0c;最终都会引向一点“Flutter中的文本是如何绘制的&#xff1f;”。 这里我将以“调整下划线与文字的间距”为切入点并结合自定义Engine&#xff0c;记录一下我的个人分析和实践…

[A-14]ARMv8/ARMv9-Memory-内存模型的类型(Device Normal)

ver0.1 [看前序文章有惊喜。] 前言 前面花了很大的精力把ARM构建的VMSA中的几个核心的议题给大家做了介绍,相信大家已经能够理解并掌握ARM的内存子系统的工作原理大致框架。接下来我们会规划一些文章,对ARM内存子系统的一些细节做一下介绍,使ARM的内存子系统更加的丰满。本…

可编辑31页PPT | 智慧业务中台规划建设与应用总体方案

荐言分享&#xff1a;随着数字化转型的深入&#xff0c;企业面临着前所未有的挑战与机遇。为了高效整合内外部资源&#xff0c;快速响应市场变化&#xff0c;提升业务创新能力&#xff0c;智慧业务中台应运而生。智慧业务中台作为企业数字化转型的核心基础设施&#xff0c;旨在…

深入理解Docker,从入门到精通-Part1(基础使用)

一、Docker基本概念 Docker架构 基本组件的介绍 Docker Client 是用户界面&#xff0c;它支持用户与Docker Daemon之间通信 Docker Daemon Docker最核心的后台进程&#xff0c;运行于主机上&#xff0c;处理服务请求 Docker registry是中央registry&#xff0c;支持拥有公有与…

在macOS的多任务处理环境中,如何平衡应用的性能与用户体验?这是否是一个复杂的优化问题?如何优化用户体验|多任务处理|用户体验|应用设计

目录 一 多任务处理与应用性能 1. macOS中的多任务处理机制 2. 性能优化的基本策略 二 用户体验的关键要素 1. 响应速度 2. 界面友好性 3. 功能的直观性 三 平衡性能与用户体验的策略 1. 资源管理 2. 优化数据加载 3. 使用合适的线程模型 4. 实时监测和调整 四 使…

lvm逻辑卷管理

分区类型&#xff1a; 主分区扩展分区逻辑分区系统引导分区&#xff1a;存放系统的引导文件和linux的内核文件swap分区&#xff1a;交换分区&#xff0c;系统的物理内存不足时&#xff0c;从一些长时间未运行的程序当中释放一部分内存&#xff0c;释放出来的内存保存到swap分区…

openai api 文件分析/联网/画图代码示例

目的 使用https://4o.zhangsan.shop的API进行文件分析等功能。 完整代码 # pip install openai0.28 # 注意下方代码必须使用该版本 import openaidef query_gpt4(question):openai.api_key "sk-aQR1wbTsLpySgJDq3fFb026c225a44C8924750C1B67bCeD5"openai.api_ba…

Android编译环境构建(二)(可用于物理机、虚拟机、容器化Jenkins环境)

文章目录 需求环境要求文件下载Gradle Version:7.5cmdline-tools至此普通物理环境的Android编译环境已部署完毕 部署maven(可选)Jenkins配置Android构建环境 说明&#xff1a; 物理环境&#xff1a;物理机、虚拟机等 容器化环境&#xff1a;docker等 需求 Gradle Version:7.5 …

WPF+MVVM案例实战(十)- 水波纹按钮实现与控件封装

文章目录 1、运行效果1、封装用户控件1、创建文件2、依赖属性实现2、使用封装的按钮控件1.主界面引用2.按钮属性设置3 总结1、运行效果 1、封装用户控件 1、创建文件 打开 Wpf_Examples 项目,在 UserControlLib 用户控件库中创建按钮文件 WaterRipplesButton.xaml ,修改 Us…

Spring Boot解决 406 错误之返回对象缺少Getter/Setter方法引发的问题

目录 前言1. 问题背景2. 问题分析2.1 检查返回对象 3. 解决方案3.1 确保Controller返回Result类型3.2 测试接口响应 4. 原理探讨5. 常见问题排查与优化建议结语 前言 在Spring Boot开发中&#xff0c;接口请求返回数据是系统交互的重要环节&#xff0c;尤其在开发RESTful风格的…

FineReport 单元格的特殊应用场景

1、实现鼠标点击的行变色 创建报表 1.1、鼠标点击某行时该行高亮显示 JavaScript 代码如下&#xff1a; _g().addEffect(highlightRow, {color: red,trigger: mousedown, });结果 1.2、鼠标悬浮某行时该行变色&#xff0c;离开时恢复 其他一样&#xff0c;就改代码 JavaScr…

MacOS的powermetrics命令查看macbook笔记本的耗能情况,附带查看ANE的工作情况

什么是 powermetrics&#xff1f; powermetrics 是 macOS 系统自带的一个命令行工具&#xff0c;用于收集和分析系统能源消耗数据。通过它&#xff0c;我们可以深入了解 Mac 的硬件性能、软件行为以及能源使用情况&#xff0c;从而优化系统配置&#xff0c;提高电池续航时间。…