STM32F4X SDIO(八) 例程讲解 设置SD卡 SDIO 总线宽度

2023-11-07 14:12

本文主要是介绍STM32F4X SDIO(八) 例程讲解 设置SD卡 SDIO 总线宽度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32F4X SDIO(八) 例程讲解 设置SD卡 & SDIO 总线宽度

  • 设置SD卡 & SDIO 总线宽度
    • 设置SDIO_CK时钟
    • CMD7:SELECT/DESELECT_CARD
      • 命令发送程序
      • 命令响应程序
    • 设置SD卡总线宽度
      • CMD55:APP_CMD
      • ACMD51:SEND_SCR
        • 命令发送
        • 命令响应
    • 设置SDIO控制器数据传输模式
    • 读取SCR寄存器
        • SCR寄存器数据解析
    • 设置SD卡总线宽度
      • CMD55:APP_CMD
      • ACMD6:SET_BUS_WIDTH
      • 命令响应
    • 步骤

设置SD卡 & SDIO 总线宽度

在上一节中我们已经初始化了SD卡,并获取了SD卡的CID、CSD和RCA地址,接下来就可以对SD卡进行读写操作了,但是在进行读写操作时,还需要提高SD卡的总线宽度和SDIO_CK时钟,加快传输速度。

设置SDIO_CK时钟

在SD卡刚上电的时候,SD卡默认的时钟是400KHz,总线宽度是1位,所以在进行SD卡读写操作前,需要提高SD卡的时钟速率。首先需要先设置SDIO_CK时钟。

 SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV; // 时钟分频系数0SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;SDIO_Init(&SDIO_InitStructure);

根据STM32F4X的SDIO_CK时钟计算公式
SDIO_CK 频率 = SDIOCLK / [CLKDIV + 2]
SDIO_CK = 48MHz / (0 + 2) = 24MHz
上面的代码就将SDIO_CK的频率设置成24MHz

CMD7:SELECT/DESELECT_CARD

CMD7的作用是通常传入RCA地址,将对应的RCA地址的SD卡进入传输模式,同一时刻只能有一张卡处于传输状态。

在这里插入图片描述

命令发送程序

 SDIO_CmdInitStructure.SDIO_Argument =  rca << 16; // SD卡的RCA地址SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEL_DESEL_CARD; // 命令索引 CMD7SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; // 短响应SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; // 不等待SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; // 使能CPSM状态机SDIO_SendCommand(&SDIO_CmdInitStructure);

在这里插入图片描述

命令响应程序

CMD7的响应类型是R1b,R1b会返回一个32位的卡状态给主机,主机需要通过卡状态判断SD卡是否准备完毕。

在这里插入图片描述

static SD_Error CmdResp1Error(uint8_t cmd)
{SD_Error errorstatus = SD_OK;uint32_t status;uint32_t response_r1;status = SDIO->STA;while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))){status = SDIO->STA;}if (status & SDIO_FLAG_CTIMEOUT){errorstatus = SD_CMD_RSP_TIMEOUT;SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);return(errorstatus);}else if (status & SDIO_FLAG_CCRCFAIL){errorstatus = SD_CMD_CRC_FAIL;SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);return(errorstatus);}/*!< Check response received is of desired command */if (SDIO_GetCommandResponse() != cmd){errorstatus = SD_ILLEGAL_CMD;return(errorstatus);}/*!< Clear all the static flags */SDIO_ClearFlag(SDIO_STATIC_FLAGS);/*!< We have received response, retrieve it for analysis  */response_r1 = SDIO_GetResponse(SDIO_RESP1);if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO){return(errorstatus);}if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE){return(SD_ADDR_OUT_OF_RANGE);}if (response_r1 & SD_OCR_ADDR_MISALIGNED){return(SD_ADDR_MISALIGNED);}if (response_r1 & SD_OCR_BLOCK_LEN_ERR){return(SD_BLOCK_LEN_ERR);}if (response_r1 & SD_OCR_ERASE_SEQ_ERR){return(SD_ERASE_SEQ_ERR);}if (response_r1 & SD_OCR_BAD_ERASE_PARAM){return(SD_BAD_ERASE_PARAM);}if (response_r1 & SD_OCR_WRITE_PROT_VIOLATION){return(SD_WRITE_PROT_VIOLATION);}if (response_r1 & SD_OCR_LOCK_UNLOCK_FAILED){return(SD_LOCK_UNLOCK_FAILED);}if (response_r1 & SD_OCR_COM_CRC_FAILED){return(SD_COM_CRC_FAILED);}if (response_r1 & SD_OCR_ILLEGAL_CMD){return(SD_ILLEGAL_CMD);}if (response_r1 & SD_OCR_CARD_ECC_FAILED){return(SD_CARD_ECC_FAILED);}if (response_r1 & SD_OCR_CC_ERROR){return(SD_CC_ERROR);}if (response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR){return(SD_GENERAL_UNKNOWN_ERROR);}if (response_r1 & SD_OCR_STREAM_READ_UNDERRUN){return(SD_STREAM_READ_UNDERRUN);}if (response_r1 & SD_OCR_STREAM_WRITE_OVERRUN){return(SD_STREAM_WRITE_OVERRUN);}if (response_r1 & SD_OCR_CID_CSD_OVERWRIETE){return(SD_CID_CSD_OVERWRITE);}if (response_r1 & SD_OCR_WP_ERASE_SKIP){return(SD_WP_ERASE_SKIP);}if (response_r1 & SD_OCR_CARD_ECC_DISABLED){return(SD_CARD_ECC_DISABLED);}if (response_r1 & SD_OCR_ERASE_RESET){return(SD_ERASE_RESET);}if (response_r1 & SD_OCR_AKE_SEQ_ERROR){return(SD_AKE_SEQ_ERROR);}return(errorstatus);
}

在这里插入图片描述
上面的逻辑分析仪解析出来的CMD7响应不知道外什么会解析成R6,在这里我们忽略逻辑分析仪的解析结果。通过上述的波形可以看到,SD卡返回的卡状态数据位0x700,通过SD卡状态表分析可知
在这里插入图片描述
当前SD卡已经处于standby状态,并且已经准备就绪。

设置SD卡总线宽度

程序经过上面的步骤之后,SD卡就进入了准备状态,此时我们需要将SD卡设置成4位总线的模式,但是并不是所有的SD卡都支持4位总线模式,所以我们需要通过查询SD卡的SCR寄存器,查看SD卡是否支持4线模式。

CMD55:APP_CMD

查询SD卡的SCR寄存器的命令是ACMD51,该命令是特殊应用命令,所以在发送ACMD51前需要先发送CMD55。有关CMD55命令的使用在前面的章节已经讲过了,这里就不细讲了。不过需要注意的是,这里的CMD55命令需要带上查询的SD卡的RCA地址

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; // SD卡的RCASDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; // CMD55SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; // 短响应SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; // 不等待SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; // 使能CPSM状态机SDIO_SendCommand(&SDIO_CmdInitStructure);errorstatus = CmdResp1Error(SD_CMD_APP_CMD); // 判断命令是否发送成功

在这里插入图片描述
在这里插入图片描述

ACMD51:SEND_SCR

CMD51的作用是读取SCR寄存器,查看需要操作的SD卡是否支持4线模式。
在这里插入图片描述

命令发送
SDIO_CmdInitStruct.SDIO_Argument = 0x0; // 不带参数
SDIO_CmdInitStruct.SDIO_CmdIndex = SD_CMD_SEND_SCR; // 命令索引 ACMD51
SDIO_CmdInitStruct.SDIO_CPSM = SDIO_CPSM_Enable; // 使能CPSM状态机
SDIO_CmdInitStruct.SDIO_Response = SDIO_Response_Short; //短响应
SDIO_CmdInitStruct.SDIO_Wait = SDIO_Wait_No; // 不等待
SDIO_SendCommand(&SDIO_CmdInitStruct);

在这里插入图片描述

命令响应

ACMD51的响应类型是R1,主机需要判断SD卡的状态是否准备就绪。
在这里插入图片描述

	
static SD_Error CmdResp1Error(uint8_t cmd)
{SD_Error errorstatus = SD_OK;uint32_t status;uint32_t response_r1;status = SDIO->STA;while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))){status = SDIO->STA;}if (status & SDIO_FLAG_CTIMEOUT){errorstatus = SD_CMD_RSP_TIMEOUT;SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);return(errorstatus);}else if (status & SDIO_FLAG_CCRCFAIL){errorstatus = SD_CMD_CRC_FAIL;SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);return(errorstatus);}/*!< Check response received is of desired command */if (SDIO_GetCommandResponse() != cmd){errorstatus = SD_ILLEGAL_CMD;return(errorstatus);}/*!< Clear all the static flags */SDIO_ClearFlag(SDIO_STATIC_FLAGS);/*!< We have received response, retrieve it for analysis  */response_r1 = SDIO_GetResponse(SDIO_RESP1);if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO){return(errorstatus);}if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE){return(SD_ADDR_OUT_OF_RANGE);}if (response_r1 & SD_OCR_ADDR_MISALIGNED){return(SD_ADDR_MISALIGNED);}if (response_r1 & SD_OCR_BLOCK_LEN_ERR){return(SD_BLOCK_LEN_ERR);}if (response_r1 & SD_OCR_ERASE_SEQ_ERR){return(SD_ERASE_SEQ_ERR);}if (response_r1 & SD_OCR_BAD_ERASE_PARAM){return(SD_BAD_ERASE_PARAM);}if (response_r1 & SD_OCR_WRITE_PROT_VIOLATION){return(SD_WRITE_PROT_VIOLATION);}if (response_r1 & SD_OCR_LOCK_UNLOCK_FAILED){return(SD_LOCK_UNLOCK_FAILED);}if (response_r1 & SD_OCR_COM_CRC_FAILED){return(SD_COM_CRC_FAILED);}if (response_r1 & SD_OCR_ILLEGAL_CMD){return(SD_ILLEGAL_CMD);}if (response_r1 & SD_OCR_CARD_ECC_FAILED){return(SD_CARD_ECC_FAILED);}if (response_r1 & SD_OCR_CC_ERROR){return(SD_CC_ERROR);}if (response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR){return(SD_GENERAL_UNKNOWN_ERROR);}if (response_r1 & SD_OCR_STREAM_READ_UNDERRUN){return(SD_STREAM_READ_UNDERRUN);}if (response_r1 & SD_OCR_STREAM_WRITE_OVERRUN){return(SD_STREAM_WRITE_OVERRUN);}if (response_r1 & SD_OCR_CID_CSD_OVERWRIETE){return(SD_CID_CSD_OVERWRITE);}if (response_r1 & SD_OCR_WP_ERASE_SKIP){return(SD_WP_ERASE_SKIP);}if (response_r1 & SD_OCR_CARD_ECC_DISABLED){return(SD_CARD_ECC_DISABLED);}if (response_r1 & SD_OCR_ERASE_RESET){return(SD_ERASE_RESET);}if (response_r1 & SD_OCR_AKE_SEQ_ERROR){return(SD_AKE_SEQ_ERROR);}return(errorstatus);
}

在这里插入图片描述
从波形图上可知,SD卡返回的卡状态是0x920,根据SD卡状态表可知,当前SD卡已经接收到ACMD命令并解析成功,总线上可以接收数据,并且已经进入传输模式。
在这里插入图片描述

设置SDIO控制器数据传输模式

当主机发送ACMD51命令并且SD卡响应正常时,下一步就可以开始在数据线上读取SCR寄存器数据了,但是在读取数据之前,我们需要将配置SDIO控制器的数据传输模式。

/* 因为SCR寄存器是64位,所以这里的数据长度设置为8字节
*/
SDIO_DataInitStruct.SDIO_DataBlockSize = SDIO_DataBlockSize_8b; // 数据块8字节
SDIO_DataInitStruct.SDIO_DataLength = 8;  // 数据长度8字节
SDIO_DataInitStruct.SDIO_DataTimeOut = SD_DATATIMEOUT; // 超时时间
SDIO_DataInitStruct.SDIO_DPSM = SDIO_DPSM_Enable; // 使能DPSM状态机
SDIO_DataInitStruct.SDIO_TransferDir = SDIO_TransferDir_ToSDIO; // 数据传输方向为SD卡到SDIO控制器
SDIO_DataInitStruct.SDIO_TransferMode = SDIO_TransferMode_Block; // 传输模式为块传输
SDIO_DataConfig(&SDIO_DataInitStruct);

读取SCR寄存器

设置好SDIO的数据传输模式之后,下一步就可以开始读取SD卡的SCR寄存器了。

SDIO_ReadData这个函数是用来读取SD卡数据线上的数据,返回的一个32位的数据,因为SCR寄存器是64位的寄存器,所以我们需要连续读取两次。

while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR))){if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET){tempscr[index] = SDIO_ReadData(); // 连续读取两次index++;if(index >= 2)break;}}

读取到的数据还需要对其进行处理

pscr[0] =  ((tempscr[0] & 0xFF) << 24) | (((tempscr[0] >> 8) & 0xFF) << 16) | (((tempscr[0] >> 16) & 0xFF) << 8) | (((tempscr[0] >> 24) & 0xFF));
pscr[1] =  ((tempscr[1] & 0xFF) << 24) | (((tempscr[1] >> 8) & 0xFF) << 16) | (((tempscr[1] >> 16) & 0xFF) << 8) | (((tempscr[1] >> 24) & 0xFF));

最后从SD卡读取到的SCR寄存器数据是0x0205808301000000

SCR寄存器数据解析

SCR寄存器的数据解析如下
在这里插入图片描述

NameFieldWidthCID-sliceValue
SCR StructureSCR_STRUCTURE4[63:60]0x0
SD Memory Card - Spec. VersionSD_SPEC4[59:56]0x2
data_status_after erasesDATA_STAT_AFTER_ERASE1[55:55]0x0
CPRM Security SupportSD_SECURITY3[54:52]0x0
DAT Bus widths supportedSD_BUS_WIDTHS4[51:48]0x5
Spec. Version 3.00 or higherSD_SPEC31[47:47]1
Extended Security SupportEX_ SECURITY4[46:43]0x0
Spec. Version 4.00 or higherSD_SPEC41[42:42]0x0
Spec. Version 5.00 or higherSD_SPECX4[41:38]0x2
ReservedX2[37:36]0x0
Command Support bitsCMD_SUPPORT4[35:32]0x3
reserved for manufacturer usageX32[31:0]0x01000000

在这里插入图片描述
从上面表格的SD_BUS_WIDTHS可知,读出来的SD_BUS_WIDTHS为0x5,也就是bit2为1,说明该SD卡支持4位总线模式。

设置SD卡总线宽度

通过上述的操作,我们知道操作的SD卡支持4线模式,所以下一步我们就需要将SD卡设置成4线模式

CMD55:APP_CMD

因为设置SD卡总线宽度的命令是特殊应用命令,所以在发送设置总线宽度命令前,需要发送CMD55命令

SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);errorstatus = CmdResp1Error(SD_CMD_APP_CMD);

ACMD6:SET_BUS_WIDTH

ACMD6命令的作用是设置SD卡总线宽度,支持设置1位总线宽度和4位总线宽度。当传入参数为0时设置1位总线,传入参数为2时设置4位总线

在这里插入图片描述

SDIO_CmdInitStructure.SDIO_Argument = 0x2; // 参数为2,设置4位总线宽度
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH; // 命令索引,ACMD16
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; // 短响应
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

在这里插入图片描述

命令响应

ACMD16的响应类型是R1响应,同样需要判断响应是否正常

static SD_Error CmdResp1Error(uint8_t cmd)
{SD_Error errorstatus = SD_OK;uint32_t status;uint32_t response_r1;status = SDIO->STA;while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))){status = SDIO->STA;}if (status & SDIO_FLAG_CTIMEOUT){errorstatus = SD_CMD_RSP_TIMEOUT;SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);return(errorstatus);}else if (status & SDIO_FLAG_CCRCFAIL){errorstatus = SD_CMD_CRC_FAIL;SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);return(errorstatus);}/*!< Check response received is of desired command */if (SDIO_GetCommandResponse() != cmd){errorstatus = SD_ILLEGAL_CMD;return(errorstatus);}/*!< Clear all the static flags */SDIO_ClearFlag(SDIO_STATIC_FLAGS);/*!< We have received response, retrieve it for analysis  */response_r1 = SDIO_GetResponse(SDIO_RESP1);if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO){return(errorstatus);}if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE){return(SD_ADDR_OUT_OF_RANGE);}if (response_r1 & SD_OCR_ADDR_MISALIGNED){return(SD_ADDR_MISALIGNED);}if (response_r1 & SD_OCR_BLOCK_LEN_ERR){return(SD_BLOCK_LEN_ERR);}if (response_r1 & SD_OCR_ERASE_SEQ_ERR){return(SD_ERASE_SEQ_ERR);}if (response_r1 & SD_OCR_BAD_ERASE_PARAM){return(SD_BAD_ERASE_PARAM);}if (response_r1 & SD_OCR_WRITE_PROT_VIOLATION){return(SD_WRITE_PROT_VIOLATION);}if (response_r1 & SD_OCR_LOCK_UNLOCK_FAILED){return(SD_LOCK_UNLOCK_FAILED);}if (response_r1 & SD_OCR_COM_CRC_FAILED){return(SD_COM_CRC_FAILED);}if (response_r1 & SD_OCR_ILLEGAL_CMD){return(SD_ILLEGAL_CMD);}if (response_r1 & SD_OCR_CARD_ECC_FAILED){return(SD_CARD_ECC_FAILED);}if (response_r1 & SD_OCR_CC_ERROR){return(SD_CC_ERROR);}if (response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR){return(SD_GENERAL_UNKNOWN_ERROR);}if (response_r1 & SD_OCR_STREAM_READ_UNDERRUN){return(SD_STREAM_READ_UNDERRUN);}if (response_r1 & SD_OCR_STREAM_WRITE_OVERRUN){return(SD_STREAM_WRITE_OVERRUN);}if (response_r1 & SD_OCR_CID_CSD_OVERWRIETE){return(SD_CID_CSD_OVERWRITE);}if (response_r1 & SD_OCR_WP_ERASE_SKIP){return(SD_WP_ERASE_SKIP);}if (response_r1 & SD_OCR_CARD_ECC_DISABLED){return(SD_CARD_ECC_DISABLED);}if (response_r1 & SD_OCR_ERASE_RESET){return(SD_ERASE_RESET);}if (response_r1 & SD_OCR_AKE_SEQ_ERROR){return(SD_AKE_SEQ_ERROR);}return(errorstatus);
}

在这里插入图片描述
当到了这一步之后,SD的初始化就算是成功了,后面就可以对SD卡进行擦除和读写测试了。

步骤

  1. 设置SDIO_CK时钟为24MHz
  2. 选中需要操作的SD卡
  3. 设置SDIO控制器的数据传输模式,准备读取SCR寄存器
  4. 读取SCR寄存器,判断是否支持4位总线模式
  5. 如果SD卡支持4位总线模式,则设置SD卡为4位总线模式,否则设置1位总线模式
  6. SD卡初始化完成,准备擦除、读写测试

这篇关于STM32F4X SDIO(八) 例程讲解 设置SD卡 SDIO 总线宽度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/364176

相关文章

Java实现为PDF设置背景色和背景图片

《Java实现为PDF设置背景色和背景图片》在日常的文档处理中,PDF格式因其稳定性和跨平台兼容性而广受欢迎,本文将深入探讨如何利用Spire.PDFforJava库,以简洁高效的方式为你的PDF文档... 目录库介绍与安装步骤Java 给 PDF 设置背景颜色Java 给 PDF 设置背景图片总结在日常的

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

Java利用Spire.XLS for Java设置Excel表格边框

《Java利用Spire.XLSforJava设置Excel表格边框》在日常的业务报表和数据处理中,Excel表格的美观性和可读性至关重要,本文将深入探讨如何利用Spire.XLSforJava库... 目录Spire.XLS for Java 简介与安装Maven 依赖配置手动安装 JAR 包核心API介

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

MySQL连表查询之笛卡尔积查询的详细过程讲解

《MySQL连表查询之笛卡尔积查询的详细过程讲解》在使用MySQL或任何关系型数据库进行多表查询时,如果连接条件设置不当,就可能发生所谓的笛卡尔积现象,:本文主要介绍MySQL连表查询之笛卡尔积查... 目录一、笛卡尔积的数学本质二、mysql中的实现机制1. 显式语法2. 隐式语法3. 执行原理(以Nes

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多