ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

F429-HAL-SD卡简介及框图(2026/8/13)

F429-HAL-SD卡简介及框图(2026/8/13) 目录一SD卡简介1SDIO设备分类2SD 卡物理结构3SD卡8个重要寄存器464条命令二SD卡总线1总线拓扑2总线协议SD 总线通信格式SD卡写和读数据规则SD卡数据包有两种格式1普通数据格式Normal Data2宽位数据格式Wide Bus Data3数据包格式3总线命令命令格式命令类型命令描述4总线响应三SD 卡的操作模式及切换1 SD 卡的操作模式总览2卡识别模式3卡数据传输模式四STM32 的 SDIO 功能框图一整体框图和时钟来源1整体框图2时钟来源二SDIO 适配器框图1 控制单元2命令路径3数据路径4 数据 FIFO5适配器寄存器五SD卡地址和写入规则一SD卡简介1SDIO设备分类SDIOSecure Digital Input Output安全数字输入输出是基于SD存储卡标准扩展而来的一种外设接口规范。它的核心特点是不仅兼容传统的存储卡还定义了通用的I/O通信协议使得主设备如手机、平板的SoC主控、单板计算机等可以通过SD卡槽来连接和控制各种功能模块。在实际应用中SDIO设备主要分为以下四大类1SD I/O卡输入/输出卡这类设备不以数据存储为主要目的而是利用SDIO接口提供的I/O通道来实现特定的通信或控制功能。它们通常集成了相应的通信芯片常见于嵌入式系统中。Wi-Fi Card无线网络通信模块是移动设备中非常常见的SDIO外设。GPS Card全球定位系统接收模块用于接收卫星信号并计算位置信息。以太网 Card...以太网控制器模块用于通过SD卡槽扩展有线网络连接功能。2SD存储卡存储设备这是大众最熟悉的类别主要用于数据的持久化存储如保存照片、视频、文件等。它们按照推出的时间和容量上限分为三个主要等级SDSCStandard Capacity普通 SD 卡容量≤2GB为早期产品现在基本淘汰。SDHCHigh Capacity高容量 SD 卡容量2GB ~ 32GB遵循SD 2.0协议使用FAT32文件系统是目前应用最广泛的规格之一。SDXCExtended Capacity扩展容量容量32GB ~ 2TB 遵循SD 3.0协议采用exFAT文件系统主要面向需要存储超大文件如4K/8K视频的高端设备如手机相机。SDUC 超大容量2TB ~ 128TB目前比较少见。3MMC卡多媒体卡MMCMultiMediaCard是SD卡的技术前身。SD卡在物理和协议上很大程度上兼容并取代了MMC卡。早期的智能手机、MP3播放器和数码相机中经常能看到MMC卡的身影如今在新的消费电子产品中已经较为少见但在一些特定的工业或老旧设备中仍有应用。4CE-ATA设备CE-ATAConsumer Electronics - Advanced Technology Attachment消费电子高级技术附件是一种专门为手持设备和便携式消费电子产品中的微型硬盘设计的高速通信接口标准。技术背景在早期的智能手机和平板电脑中为了在保证大容量存储的同时降低成本和功耗厂商会使用体积微小的机械硬盘如1.8英寸硬盘。CE-ATA标准基于MMC 4.0的物理层规范采用了精简后的ATA指令集旨在减少接口引脚数量、降低功耗与成本以适应手持设备紧凑的空间需求。现状随着NAND闪存技术即前面提到的各类SD卡和大容量eMMC芯片的飞速发展闪存的容量、速度和成本优势逐渐显现微硬盘逐渐退出市场。因此CE-ATA接口目前在主流消费电子产品中已基本被淘汰目前情况stm32f4xx系列控 制器只支持SD卡规范版本2.0即只支持标准容量SD和高容量SDHC标准卡不支持超大容量 SDXC标准卡所以可以支持的最高卡容量是32GB。2SD 卡物理结构一张SD卡包括有1存储单元、2存储单元接口、3电源检测、4卡及接口控制器5接口驱动器 5个部分流程①存储单元是存储数据部件存储单元通过存储单元接口与卡控制单元进行 数据传输②电源检测单元保证SD卡工作在合适的电压下如出现掉电或上状态时它会使控制 单元和存储单元接口复位③卡及接口控制单元控制SD卡的运行状态它包括有8个寄存器④接口驱动器控制SD卡引脚的输入输出。3SD卡8个重要寄存器SD卡内部不是只有8个寄存器SD卡内部实际上还有很多控制、状态、缓存、协议相关的寄存器/寄存器区域只是从主机STM32的角度来看SD规范开放给外部访问、并且软件开发最关注的是这几个。SD 卡的 8 个和STM32通讯用的寄存器SD 卡不能直接读写寄存器因为 SD 卡是外部设备STM32根本看不到它内部地址所以必须通过通信协议。需用通过命令来控制SD卡64条命令。464条命令SD 卡协议定义的是 CMD0~CMD63 共64个命令编号但不是所有编号都有实际命令。其中分为标准 SD Memory 命令CMD0~CMD63应用专用命令 ACMD通过CMD55开启保留命令ReservedSDIO扩展命令CMD52、CMD53等CMD0 ~ CMD63 ​ SD卡命令空间 ​ ┌────────────────┐ │ SD Memory CMD │ │ CMD0~CMD63 │ └────────────────┘ ​ ┌────────────────┐ │ SDIO CMD │ │ CMD52 CMD53 │ └────────────────┘ ​ ┌────────────────┐ │ Reserved │ │ 未定义 │ └────────────────┘二SD卡总线1总线拓扑SD卡一般都支持SDIO和SPI这两种接口SD 卡支持两种通信方式STM32 有两种对应外设SD 卡通信方式 STM32 外设 速度 ─────────── ────────── ──── SPI 模式 ─────────→ SPI 外设 慢你用过的 SPI5 SDIO 模式 ─────────→ SDIO 外设 快4 线并行 ​ 注意STM32F42x 的 SDIO 外设只能跑 SDIO 模式不支持 SPI 模式。本章用 SDIO 外设操作 SD 卡速度快。如果你非要用 SPI 方式操作 SD 卡得用独立的 SPI 外设比如你的 SPI5但不能用 SDIO 来模拟 SPI。STM32F42x 的 SDIO 不支持 SPI 模式。我们有SDIO 外设直接用就行又快又方便谁会吃饱了撑着用慢的 SPI 去操作 SD 卡。一个 SDIO 总线只接一张 SD 卡别挂多个。 虽然协议上允许一根总线上挂多张卡但实际工程中没人这么干——速度慢、卡之间互相干扰。你的板子就一个 TF 卡槽一根总线对一张卡不管它。SD 卡使用9-pin接口通信其中3根电源线、1根时钟线、1根命令线和4根数据线CLK时钟线由SDIO主机产生即由STM32控制器输出CMD命令控制线SDIO主机通过该线发送命令控制SD卡如果命令要求SD卡提供应 答(响应)SD卡也是通过该线传输应答信息D0-3数据线4根0123传输读写数据SD卡可将D0拉低表示忙状态VDD、VSS1、VSS2电源和地信号。三点总结时序比 SPI/I2C 简单——只认上升沿不像 SPI 有 4 个模式、I2C 有起始位/应答位。就一根 CLK同步时钟上升沿采样。两种时钟速度——上电识别用低速 400kHz兼容最差的老卡识别完后切高速 25MHz默认或 50MHz高速模式。板子上 SD 卡和 WiFi 冲突——你板子只有一套 SDIO 外设但槽里插了 SD 卡 焊了 SDIO WiFi 模块。用 SD 卡前得先把 WiFi 模块禁掉拉对应 GPIO 断电。你的板子有没有 WiFi 模块没有就不用管这句。2总线协议SD 总线通信格式主机发命令 [起始位 0] [CMDxx 命令内容] [CRC7 校验] [停止位 1] ​ SD卡回响应 [起始位 0] [响应内容] [CRC7] [停止位 1] ​ 有数据读/写 [起始位 0] [数据块] [CRC16] [停止位 1]对比你之前学的外设通信模型SPI Flash发命令码(0x9F) → 收数据简单粗暴I2C EEPROM发设备地址 → 发内存地址 → 收/发数据SDIO发命令 → 收响应 → (可选)传数据块最规范SD 卡也是发命令-收响应-传数据跟你之前玩的 SPI Flash 核心逻辑一样只是多了一个响应环节确认卡收到命令了。SD卡写和读数据规则数据传输以 512 字节为单位块/Block——跟 SPI Flash 的 4096 字节扇区一个概念。你读写 SD 卡时传的是一个或多个 512 字节块不是任意长度字节流。硬件自动 CRC——每块数据后面带 CRC 校验码STM32 SDIO 硬件自动算、自动验你代码里不用管。4 线比 1 线快 4 倍——4 根数据线同时传一个 CLK 周期搬 4 个 bit。你的板子硬件接了 4 根线D0-D3所以后面HAL_SD_Init配置时会自动用 4 线模式。单块 vs 多块——单块 一次读写一个 512 字节块。多块 一次性连续读写 N 个块快但写完要发CMD12停止。*写入前要等卡不忙——卡收到数据后要写到内部 Flash这个时间不等你。忙的时候 D0 线拉低HAL 库内部会等SDMMC_GetFlagStatus(SDMMC_FLAG_BUSY)。读不用等——读出数据直接发不像写需要后台编程时间。跟 SPI Flash 一样——读直接读写要先擦再写然后等忙。4 线模式下每根线独立 CRC——4 根线各自算 CRC结果汇总通过 D0 返回给主机。全硬件自动做你不管。字节序——先发低字节每字节内先发高位。硬件自动处理你只管HAL_SD_ReadBlocks(buf, addr, 512)出来就是对的。跟你 SPI Flash 的经验对比操作SPI FlashSD 卡最小读写单位任意字节512 字节块多块加速不限多块读写命令 CMD12 停止写入后的等待WaitBusy()D0 硬件忙检测数据校验无硬件 CRC自动SD卡数据包有两种格式1普通数据格式Normal Data规定字节之间低字节优先字节内部高位优先SD协议内部按照8bit一个字节组织数据也就是一个ByteD7 D6 D5 D4 D3 D2 D1 D0发送顺序先发送低字节再发送高字节比如一个16位数据0x1234 拆成高字节0x12 低字节 0x34SD发送0x34先发后再发0x12低位地址先传。字节内部是先发高位再发低位D7 → D0比如发送0x34先转为二进制0011 0100高位先发所以发的是D7 D6 D5 D4 D3 D2 D1 D0 对应 0011 01002宽位数据格式Wide Bus Data这个就是SDIO高速模式的核心。普通数据格式一次只能传1bit4bit模式一次同时发送4 bit 一个时钟一次完成4bit的传送以4bit为例一个字节D7 D6 D5 D4 D3 D2 D1 D0发送第一个CLKDAT3 DAT2 DAT1 DAT0 ​ D7 D6 D5 D4第二个CLKDAT3 DAT2 DAT1 DAT0 ​ D3 D2 D1 D0所以8bit数据只需要两个CLK。例如发送0xA5对应二进制1010 0101高4bit1010低四位0101第一个CLKDAT3 DAT2 DAT1 DAT0 ​ 1 0 1 0第二个CLKDAT3 DAT2 DAT1 DAT0 ​ 0 1 0 1部分SDIO设备支持一次传8bit效率最高。不过普通SD卡一般不支持F429 芯片的 SDIO 外设支持 8 线但不是给 SD 卡用的——是给 eMMC 用的手机里那种焊死的存储芯片。TF/SD 卡物理上就 4 根数据线多画也没用。F429 SDIO 外设 → 支持 1/4/8 线 │ ├── 4 线 → TF 卡/SD 卡你用的 └── 8 线 → eMMC焊在板子上的存储芯片不是你板子省了是 TF 卡插座压根没 D4-D7 这几个引脚。4线传输示意如图8位宽数据包传输。DAT3: bit6 bit7 bit14 bit15 ... ← 高位 DAT2: bit4 bit5 bit12 bit13 ... DAT1: bit2 bit3 bit10 bit11 ... DAT0: bit0 bit1 bit8 bit9 ... ← 低位 ↑ ↑ 第1个CLK 第2个CLK → 每个 CLK 搬 4 bit一个字节 2 个 CLK 搬完3数据包格式不是大小数据的区别是两种不同用途数据格式用途什么时候用常规数据包8bit 宽读写文件数据f_read/f_write时每次 512 字节数据块宽位数据包读 SSR 寄存器主机发ACMD13查询 SD 卡状态512 个 bit常规数据包你读写文件时 DAT3: bit6 bit7 bit14 bit15 ... ← 高位 DAT2: bit4 bit5 bit12 bit13 ... DAT1: bit2 bit3 bit10 bit11 ... DAT0: bit0 bit1 bit8 bit9 ... ← 低位 ↑ ↑ 第1个CLK 第2个CLK → 每个 CLK 搬 4 bit一个字节 2 个 CLK 搬完 宽位数据包SSR 寄存器专用 ACMD13 命令 → 卡把整个 512 bit SSR 通过 DAT 线一次性吐出来至于 1/4/8 bit模式一个 CLK 搬多少你的板子1 bit1 bit只用 D0支持初始化识别阶段用的4 bit4 bitD0-D3✅ 日常用8 bit8 bit❌ TF 卡物理上没有这就是 HAL_SD_Init 自动做的事情开机先用 1 bit 低速 400kHz 识别卡识别完自动切 4 bit 高速 25MHz。3总线命令命令格式SD 命令格式固定为48bit都是通过CMD线连续传输的数据线不参与SD 命令的组成如下起始位和终止位命令的主体包含在起始位与终止位之间它们都只包含一个数据位起 始位为0终止位为1。传输标志用于区分传输方向该位为1时表示命令方向为主机传输到SD卡该位为0 时表示响应方向为SD卡传输到主机。命令主体命令 地址信息/参数 和CRC校验 三个部分命令号它固定占用6bit所以总共有64个命令(代号CMD0~CMD63)每个命令都有特 定的用途部分命令不适用于SD卡操作只是专门用于MMC卡或者SDI/O卡。地址/参数每个命令有32bit地址信息/参数用于命令附加内容例如广播命令没有地址 信息这32bit用于指定参数而寻址命令这32bit用于指定目标SD卡的地址。CRC7 校验长度为7bit的校验位用于验证命令传输内容正确性如果发生外部干扰导致 传输数据个别位状态改变将导致校准失败也意味着命令传输失败SD卡不执行命令。命令类型SD 命令有4种类型• 无响应广播命令(bc)发送到所有卡不返回任务响应• 带响应广播命令(bcr)发送到所有卡同时接收来自所有卡响应• 寻址命令(ac)发送到选定卡DAT线无数据传输• 寻址数据传输命令(adtc)发送到选定卡DAT线有数据传输。SD 卡命令分两种ACMD 需要解锁码普通命令CMD0 / CMD8 / CMD17 → 直接发就行 特殊命令ACMD6 / ACMD13 / ACMD41 → 先发 CMD55再发 ACMDxx ↑ ↑ 钥匙 真正的命令 只对紧接着的下一条有效CMD55 → SD卡被通知下一个是特殊命令 ACMD41 → SD卡执行特定功能比如初始化 CMD55 → 通知 CMD0 → 这不是 ACMDCMD55 白发了SD卡退回普通模式CMD55就像权限开关发完后面的那个命令才有效。HAL 库里HAL_SD_Init内部已经帮你处理好了你不用手动发CMD55。命令描述64 个命令按功能分成了不同的类比如 Class 0 是基础命令、Class 2 是块读写命令发命令时参数里没用的位必须写 0。没有必须完全记住每个命令详细信息但越熟悉命令对后面编程理解非常有帮助。4总线响应响应由SD卡向主机发出部分命令要求SD卡作出响应这些响应多用于反馈SD卡的状态。SDIO 总共有7个响应类型(代号R1~R7)其中SD卡没有R4、R5类型响应。你发命令 → SD 卡回响应就跟一问一答一样。响应 卡告诉你收到了状态怎么样 短响应R1/R3/R6/R748 bit 长度大多数命令回这个 长响应R2 唯一136 bit 长度读 CID/CSD 寄存器时用类型长度什么命令触发R148 bit普通命令的OK回复R2136 bitCMD9 读 CSD、CMD10 读 CID寄存器数据量大需要长响应R348 bit无 CRCACMD41 回 OCR 寄存器内容CRC 字段用来放数据了R648 bitCMD3 返回 RCA 地址R748 bitCMD8 电压检查对比 SPI Flash你发0x9FFlash 回 3 字节 ID。SD 卡不过是把回 3 字节换成了回 48 bit 响应包CRC 校验也带上确保数据没传错。还是一样的一问一答。三SD 卡的操作模式及切换1 SD 卡的操作模式总览这是介绍总览SD卡操作就两种模式第一种是上电后stm32和sd卡进行识别第二种模式就是SD卡和stm32之间进行传输SD 卡上电后的状态切换流程上电/复位 │ ▼ ┌─────────────┐ │ 卡识别模式 │ ← 主机和卡都在这互相找 │ (Identification)│ 卡等主机发命令来认领自己 └──────┬──────┘ │ 主机发 CMD3给卡分配 RCA 地址 ▼ ┌─────────────┐ │ 数据传输模式 │ ← 卡被认领了可以读写数据了 │ (Data Transfer)│ 后面所有读写操作都在这个模式下 └─────────────┘识别模式下主机做的事CMD0复位 →CMD8问电压 →ACMD41问容量类型 →CMD2读 CID →CMD3发 RCA 地址。CMD3 就是分界线——收到 CMD3 后卡从无名变成有地址进入数据传输模式。之后才能CMD7选中卡 →CMD17/CMD18读 →CMD24/CMD25写。HAL_SD_Init内部一次性帮你跑完这整条链路你调完HAL_SD_Init返回 OK 后卡就已经在数据传输模式了直接HAL_SD_ReadBlocks就行。在每个操作模式下SD卡都有几种状态并且可以通过命令实现卡状态的切换。2卡识别模式就是HAL_SD_Init内部做的事——一条命令链主机发 CMD0 → 所有卡复位进入空闲状态 (都给我归位) 主机发 CMD8 → 问你支持 3.3V 吗 有响应V2.0卡没响应老卡或不存在 主机发 CMD55 → 解锁 ACMD 权限 主机发 ACMD41 → 问你多大容量 CCS位1→SDHC(2~32GB)0→SDSC(≤2GB) 没响应 → 卡不可用进入无效状态 主机发 CMD2 → 把所有卡的 CID (128bit 唯一ID) 要过来 主机发 CMD3 → 给卡分配一个短地址 RCA (16bit)卡进入待机状态 ★ 卡从此进入数据传输模式 主机也进入数据传输模式状态流转 空闲 ──CMD0──→ 空闲 ──ACMD41──→ 准备 ──CMD2──→ 识别 ──CMD3──→ 待机数据传输模式 后面就是 CMD7 选中这张卡 → CMD17/CMD18 读 → CMD24/CMD25 写。一条链到底HAL_SD_Init 全包了这一串命令你不用写——HAL_SD_Init 一行搞定 命令链就是开机自检——插卡→问你是谁→问你多大→给你地址→可以用了 你真正要写的只有两个HAL_SD_ReadBlocks读和 HAL_SD_WriteBlocks写跟 SPI Flash 的 BufferRead/BufferWrite 一个味3卡数据传输模式只有SD卡系统处于数据传输模式下才可以进行数据读写操作。数据传输模式下可以将主机SD 时钟频率设置为FPP默认最高为25MHz频率切换可以通过CMD4命令来实现。数据传输模式下卡的状态 待机 ──CMD7(选中)──→ 传输 ←── 可以读写了 传输 ──CMD7(取消)──→ 待机CMD7 点名选中这张卡总线上可能有多张叫谁谁回答 CMD12 多块读写时的刹车安全停 CMD0/15 强制复位/暂停数据可能损坏别乱用跟 I2C 对比——I2C 发设备地址选中从机再读写SD 卡用 CMD7 选中目标卡再 CMD17/24 读写一个套路。HAL 库一样封装好了你没特殊需求不用手动发这些。四STM32 的 SDIO 功能框图一整体框图和时钟来源1整体框图SDIO 由两部分组成● SDIO 适配器块提供特定于 MMC/SD/SD I/O 卡的所有功能如时钟生成单元、命令和数据传输。● APB2 接口访问 SDIO 适配器寄存器并且生成中断和 DMA 请求信号。APB2 总线 (PCLK2) ──→ SDIO 适配器寄存器 ←── 你写代码读写的寄存器 │ ▼ SDIO 适配器核心引擎 ┌──────────────────┐ │ 时钟生成器 │ → SDIO_CK给卡的时钟 │ 命令发送响应接收 │ → SDIO_CMD命令线 │ 数据收发FIFODMA │ → SDIO_D0~D3数据线 └──────────────────┘ │ ▼ SD 卡槽要点项值SDIO 外设时钟源SDIOCLK 48MHz来自 PLL48CK给卡的时钟SDIO_CK最大 25MHzSD 卡/ 48MHzMMC数据线模式上电先用 D0 单线400kHz初始化后切换 D0~D325MHz都推挽输出CMD 线模式初始化阶段开漏之后切推挽硬件自动时钟限制PCLK2 ≥ 3/8 × SDIO_CK即 PCLK290MHz 时 SDIO_CK 最大约 24MHz2时钟来源HSE (25MHz 外部晶振) │ ├─→ STCK (WWDG 看门狗)—~几十KHz │ ÷ PLLM (25) │ PLL 输入 1MHz │ ┌───────────────┼───────────────┐ │ │ │ 主 PLL PLLI2S PLLSAI ×N(360) (音频用) ×N(192) │ │ │ PLLCLK360M 不碰这个 PLLSAICLK192M │ │ ┌────┼────┐ ┌──────┼──────┐ │ │ │ │ │ ÷P ÷Q ÷R ÷R ÷Q (2) (7) (无关) (5) (无关) │ 48MHz │ SYSCLK PLLLCDCLK 180MHz (USB) 38.4MHz │ │ │ ÷DIV (4) │ │ ┌───┴────┐ LCD_CLK │ │ 9.6MHz → PG7 HCLK SYSTICK 给屏用 180MHz (10us中断) │ ├── PCLK2 (APB2) 90MHz — GPIO/USART1/SPI1/TIM1/TIM8 │ └── PCLK1 (APB1) 45MHz — USART2-8/SPI2-5/I2C/TIM2-7 PLLCLK 360MHz │ ├── ÷ P(2) → SYSCLK 180MHz ← 系统主时钟 │ ├── ÷1 → HCLK 180MHz │ ├── ÷4 → PCLK1 45MHz │ └── ÷2 → PCLK2 90MHz │ └── ÷ Q(7) → PLL48CK ≈ 51.4MHz ← 给 USB 和 SDIO 的独立时钟 │ ├── USB OTG (48MHz, 误差 ~7% 可接受) └── SDIO 引擎 → 分频器 → SDIO_CK 给卡 SYSCLK 是 ÷P 出来的 180MHz÷Q 出来的才是给 SDIO/USB 的 48MHz。两条路别搞混。两个时钟名容易搞混分开看PCLK2 (90MHz, 来自 APB2) └── CPU 读写 SDIO 寄存器的速度 比如 *(volatile uint32_t *)SDIO_BASE xxx; 不直接给 SD 卡 SDIOCLK (48MHz, 来自 PLL48CK) └── SDIO 外设内部自己用的时钟 经过分频器后 → 变成 SDIO_CK → 供给 SD 卡时钟来源作用PCLK2APB2 总线90MHzCPU 访问 SDIO 寄存器SDIOCLKPLL48CK48MHzSDIO 内部引擎分频后生成 SDIO_CK 给卡读 STM32 自己的 SDIO 寄存器 → PCLK2 (90MHz, APB2) 比如 *(volatile uint32_t *)(SDIO_BASE 0x34) 读 SDIO_STA 读 SD 卡内部的寄存器 → 通过 CMD 线发命令CLK SDIO_CK (24MHz) 比如发 CMD9 → 卡回 CSD 内容走响应通道不是 APB2同一个寄存器名叫 CSD——但 STM32 的 SDIO_CMD/SDIO_STA 在芯片这边90MHz 访问卡的 CID/CSD/OCR 在卡那边24MHz 发命令问它要协议 V2.0 最高 25MHz。48MHz ÷ 2 24MHz刚好在协议上限以内。HAL_SD_Init 内部自动配分频器选合适的值你不用手动算。二SDIO 适配器框图SDIO 适配器是一个多媒体卡/安全数字存储卡总线主设备提供与多媒体卡堆栈或安全数字 存储卡的接口。该适配器由五个子单元组成● 适配器寄存器块 ● 控制单元 ● 命令路径 ● 数据路径 ● 数据 FIFOAPB2 时钟域 (PCLK2 90MHz) ├── 适配器寄存器你写 SDIO_CLKCR/SDIO_CMD/SDIO_DCTRL 等寄存器 → CPU 通过 APB2 访问 └── FIFO32 字深的 DMA 数据缓冲区CPU/DMA 读写 FIFO 走 APB2 SDIO 适配器时钟域 (SDIOCLK 48MHz) ├── 控制单元产生 SDIO_CK 时钟给卡、管理电源状态 ├── 命令路径发 48bit 命令包、收响应包、CRC 校验 └── 数据路径4 线收发、CRC 生成/校验、串并转换SD 卡内部 Flash └── D0-D3 线 (SDIO_CK 24MHz) → 数据从卡搬到 SDIO 数据路径 │ ▼ 串并转换 CRC 校验48MHz 引擎做 │ └── FIFO (32字缓冲, PCLK2 90MHz) → 数据暂存 │ ▼ DMA (PCLK2 90MHz) │ └── 内存 (SDRAM/SRAM) → 你的 readbuf[512]环节用的时钟干的事卡 → SDIO 数据路径SDIO_CK 24MHz4 线串行接收CRC 校验 串转并SDIOCLK 48MHz硬件自动存入 FIFOPCLK2 90MHz暂存 32 个字DMA → 内存PCLK2 90MHz搬到你的数组底层慢24MHz 从卡拉数据上层快90MHz DMA 存到内存。FIFO 就是个速度桥——卡那边还在慢慢发DMA 这边已经可以同时往内存搬了。因为SDIO是stm32的一个外设FIFO是stm32的缓存数据区适配器寄存器和FIFO 都可以用上我们APB2的高速时钟90MHZ。而在SD卡内部它V2版本规定最高是25MHZ我们时钟给的24MHZ像个老人控制单元命令路径数据路径都使用的低俗时钟24MHZ.1 控制单元SDIO适配器框图有5个内容控制单元命令路径数据路径数据 FIFO适配器寄存器这是其中控制单元的框图控制单元由 电源管理子单元 和 时钟管理子单元组成。控制单元就是 SDIO 的总闸——管电 管钟。控制单元 ├── 电源管理子单元 → 上电/断电时禁止卡总线输出保护卡防止半压状态下乱发数据 └── 时钟管理子单元 → 产生 SDIO_CK三种情况下自动关钟 ① 复位后还没配好 ② 上电/断电过程中电压不稳不通信 ③ 节电模式 总线空闲 8 个周期后省电跟 WFI 一样道理就是 SDIO 外设自带的一个安全开关——没准备好之前不发时钟卡不会收到半截命令。不用你代码管硬件自动。2命令路径一句话发命令 → 等响应 → 超时或收到全自动你写 SDIO_CMD 寄存器 → CPSM 状态机自动跑 空闲 ─→ 发送命令 ─→ 收到响应──→ CRC 校验通过──→ 完成置标志 │ │ │ │ │ └─ 不通过 → CRC 失败标志 │ │ │ └─ 不需要响应→ 直接完成 │ └─ 超时 (64 个 SDIO_CK ≈ 2.6μs)→ 超时标志 空闲至少 8 个 CLK → 才发下一条命令硬件强制等待协议要求名词什么CPSM命令路径状态机——硬件自动跑不用管64 个 CLK 超时发完命令 2.6μs 没响应 → 卡不在了或坏了中断/挂起高级功能允许 CPSM 等卡中断请求或等数据路径信号基本不用NCC两个命令之间最小 8 个 CLK 间隙NRC命令到响应之间最小 8 个 CLK 间隙你只管调HAL_SD_ReadBlocksCPSM 全自动。继续看数据路径。3数据路径数据发送/接收全由 DPSM 状态机自动跑你只管往 FIFO 里塞数据或从 FIFO 取数据。发送数据 空闲 → Wait_S ─→ 发送 ─→ 忙碌(等CRC确认) ─→ Wait_S (继续) 或 空闲(完成) ↑ │ │ │ │ └─ CRC 错误 → 空闲 │ └─ FIFO 空了还没发完 → 下溢错误 → 空闲 └─ FIFO 为空? → 等待 DMA 往 FIFO 填数据 接收数据 空闲 → Wait_R ─→ 接收 ─→ CRC 校验通过? ─→ Wait_R (继续) 或 空闲(完成) ↑ │ │ │ │ └─ CRC 错误 → 空闲 │ └─ 超时没收到 → 空闲 (卡没响应) └─ FIFO 满了 → 溢出错误 → 空闲 超时保护硬件自动 收数据超时 卡半天没发来起始位 发数据超时 卡 busy 太久4 数据 FIFOFIFO 就是个 32 格 × 4 字节的快递中转站。写卡时 DMA → FIFO (90MHz) → DPSM (24MHz) → 卡 DMA 把货卸到 FIFODPSM 慢慢发给卡 读卡时 卡 → DPSM (24MHz) → FIFO → DMA (90MHz) DPSM 从卡收数据放 FIFODMA 一口气搬到内存 TXACT1 正在往卡发 → 你往 FIFO 填数据 RXACT1 正在从卡收 → DMA 从 FIFO 取数据 不会同时为 1半双工同一时刻只能发或收FIFO 空 → DMA 赶快补货。FIFO 满 → DMA 快取走。全是硬件自动触发你只管配好 DMA 然后等完成标志。5适配器寄存器适配器寄存器包含了控制SDIO外设的各种控制寄存器及状态寄存器内容较多可以通过SDIO 提供的各种结构体来了解这些寄存器的功能都被整合到了结构体或ST标准库之中。typedef struct { __IO uint32_t POWER; // 电源控制 __IO uint32_t CLKCR; // 时钟分频 总线宽度 __IO uint32_t ARG; // 命令参数 __IO uint32_t CMD; // 命令 CPSM 使能 __IO uint32_t RESPCMD; // 响应命令号 __IO uint32_t RESP[4]; // 4×32bit 128bit 响应 __IO uint32_t DTIMER; // 数据超时 __IO uint32_t DLEN; // 数据长度 __IO uint32_t DCTRL; // 数据传输控制 __IO uint32_t DCOUNT; // 剩余数据计数 __IO uint32_t STA; // 状态标志 __IO uint32_t ICR; // 清中断标志 __IO uint32_t MASK; // 中断屏蔽 __IO uint32_t FIFOCNT; // FIFO 剩余字数 __IO uint32_t FIFO; // 数据出入口32bit宽 } SDIO_TypeDef;就是你把HAL_SD_Init往这个结构体里帮你填值。你看到的那些SDIO-CLKCR、SDIO-CMD宏展开就是这个结构体的成员。后面用到的HAL_SD_ReadBlocks内部就操作这些寄存器。五SD卡地址和写入规则SD 卡是纯块地址SD 卡寻址逻辑块号 LBA 块 0 块 1 块 2 ... 块 N-1 ┌────┐ ┌────┐ ┌────┐ ┌────┐ │512B│ │512B│ │512B│ ... │512B│ └────┘ └────┘ └────┘ └────┘ ↑ ReadAddr0 想读第 3 块→ ReadAddr2 SPI Flash 寻址字节地址 字节 0 字节 1 ... 字节 16MB ┌──┐ ┌──┐ ┌──┐ │ 1B│ │ 1B│ ... │ 1B│ └──┘ └──┘ └──┘ ↑ 想读 0x1000 处的数据→ addr0x1000SPI FlashSD 卡寻址方式字节地址任意偏移块号512 字节为单位最小访问1 字节1 块 512 字节要读 1KB 数据传字节地址 长度传起始块号 块数(2)没有基地址寄存器——块 0 就是第一块。你传ReadAddr0就是从头读ReadAddr100就是从第 100 块开始。跟硬盘的 LBA逻辑块寻址完全一样我们买的16GB16GB ≈ 31,250,000 块每块 512 字节。精算16 × 10^9 ÷ 512 ≈ 31,250,000。实际可用略少保留区 FAT 区 厂商标 16GB 是按十进制算的。想知道精确值调BSP_SD_GetCardInfo打印info.LogBlockNbr。那写东西进sd卡就是指定第几块写咯那我们怎么知道哪块写了剩多少这就是 FatFs 干的活——你刚学的文件系统。裸 SD 卡实验 1 挂 FatFs 后实验 2 你写块 0自己记住存了啥 f_open(test.txt) 你写块 5自己拿本子记ID 在块 5 f_write(data) → FatFs 自己找空闲块 你写块 100问这块用过了没 f_read(buf) → FatFs 自己查目录找到块号 全手工账本 你只管文件名 裸卡操作就像没有文件系统的空白硬盘 数据存第 100 号扇区 ← 你记 哪些扇区用过了 ← 你开本子记 FatFs 挂上后就像电脑插 U 盘 数据存 test.txt ← 你只记文件名 还剩多少空间 ← f_getfree 告诉你 数据在哪个块 ← FatFs 通过 FAT 表自动算所以实验 1 的裸块读写只是验证硬件通路——确认SDIO → DMA → 卡这条链路没问题。实验 2 挂上 FatFs 才是你真正用 SD 卡的方式——跟之前 SPI Flash 文件系统一模一样f_open/f_write/f_read/f_getfree全不变。
返回列表