SD卡与STM32

文章转自STM32F103正点原子学习笔记系列——SD卡 - 知乎 (zhihu.com)

1.SD卡介绍

SD卡,Secure Digital Card,成为安全数字卡(安全数码卡)。本质:nand flash+控制芯片。

SD卡系列主要为三种:SD卡(full size)、Mini SD卡以及MicroSD卡。

SD卡

特点:容量大、高安全性、体积小、传输速度快、接口简单。

SD卡存储容量等级分为四个:SDSC(Secure Digital Standard Capacity)、SDHC(Secure Digital High Capacity)、SDXC(Secure Digital eXtended Capacity)、SDUC(Secure Digital Ultra Capacity)。

SD卡分类

文件系统:存储设备上组织文件的方法。

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

假如对SD卡的操作跟EEPROM或者NOR FLASH操作一样,读写数据并验证数据的正确性,不需要FAT文件系统。

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

SD卡速度等级分为:Speed Class、USH Speed Class和Video Speed Class。

SD卡速度分类

SD卡驱动方式

微处理器对SD卡进行操作,可通过SPI接口、SDIO接口。不同接口,SD卡引脚功能不一样。

SD卡引脚

SDIO接口通信线:CLK/CMD/DAT0-3。

CLK:时钟线,SDIO主机产生,由STM32微控制器的SDIO外设输出;

CMD:命令线,SDIO主机通过该线发送命令控制SD卡,若命令要求SD卡响应,SD卡也是通过该线传输响应信息。(类似IIC的应答信号)

DAT0-3:数据线,用于接收或发送数据;SD卡可将DAT0拉低表示处于忙状态。(SPI接口的MISO也有该特性)

SPI接口通信线:CS/CLK/MOSI/MISO。

TF卡

TF卡只比SD卡少一个电源引脚VSS2,其他引脚功能类似。

TF卡引脚

SD卡和TF卡只有引脚和形状大小不同,内部结构类似,操作时序完全相同,可用完全相同的驱动代码

SD卡寄存器

SD卡有8个寄存器,但不能直接进行读写操作,需要通过命令来控制。SD卡协议定义了一些命令用于实现某一特定功能,SD卡根据收到的命令要求对内部寄存器进行修改。

SD卡寄存器

OCR寄存器

OCR寄存器

CSD、SCR寄存器

CSD、SCR寄存器

SDIO模式

SD总线上的通信基于命令和数据位流传输。

SD卡命令

命令:应用相关命令(ACMD)和通用命令(CMD),通过命令线CMD传输,固定长度48位

响应:SD卡接收到命令,会有一个响应,用来反应SD卡状态。有2种响应类型:短响应(48位,格式和命令一样)和长响应(136位)

数据:主机发送的数据/SD发送的数据。SD数据是以块(Block)形式传输,SDHC卡数据块长度一般为512字节。数据块需要CRC保证数据传输成功

SD卡命令格式

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

SD卡命令格式

Byte1:命令字的第一个字节为命令号(如CMD0、CMD1等),格式为“0 1 x x x x x x”;

Byte2-Byte5:命令参数,有些命令参数是保留位,没有定义参数的内容,保留位应设置为0;

Byte6:用于校验命令传输内容正确性,前7位为CRC(循环冗余校验)校验位,最后一位为停止位0。

注意:使用SDIO接口驱动,CRC7校验值必须正确;而SPI接口驱动,CRC7校验默认关闭,即伪CRC。

SDIO模式和SPI模式,可使用的命令和特定类支持的命令有所不同。

SD卡系统的命令被分成多个类:

SD卡命令分类

其中,基本命令Class0、面向块读取命令Class2、面向块写入命令Class4、擦除命令Class5、加锁命令Class7、特定于应用命令Class8是必须有的,其余则是非必须支持的命令。

SDIO模式常用命令

SDIO常用命令

SD卡响应

SD卡和单片机的通信采用发送应答机制。

每发送一个命令,SD卡都会给出应答,告知主机该命令执行情况,或返回主机需要获取的数据。使用SDIO接口,响应会通过CMD线传输。

SD卡响应因使用接口不同,格式也不同。具体响应有R1、R1b、R2、R3、R7。

响应内容大小可分为短响应48bit和长响应136bit。

SD卡响应

R1响应:如果有传输到卡的数据,那么数据线0有busy信号(R1b)。

R1响应

可通过响应内容的command index获知响应哪个命令。

R2响应:CID寄存器内容作为CMD2和CMD10响应,CSM寄存器内容作为CMD9响应。

R2响应

R3响应:OCR寄存器值作为ACMD41的响应。

R3响应

R7响应:专用于命令CMD8的响应,返回卡支持电压范围和检测模式。

R7响应

R6响应:专用于命令CMD3的响应(RCA响应)。

R6响应

这里要注意SPI模式没有RCA寄存器,也不支持CMD3命令,没有R6响应。

SD卡操作模式

在SD卡系统(主机和SD卡)定义了两种操作模式:卡识别模式和数据传输模式

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

卡识别模式:识别总线上SD卡类型;

数据传输模式:读写操作。

SD卡模式与状态

卡识别模式

SD卡卡识别模式

这里就是上电从空闲状态出发,先发送CMD8,主机给卡看电压,有响应就发ACMD41,看SD卡的OCR寄存器,主机看SD卡的电压是否匹配;进入准备状态后发送CMD2看SD卡的CID寄存器,看到SD卡的信息,进入识别状态;发送CMD3,获取SD卡的RCA寄存器,卡会请求新的RCA值,就进入了待机状态。

SDIO模式下SD卡初始化

SD卡SDIO初始化

需要区分4类卡:SDHC卡、SDSC卡(这两个是SD2.0卡)、SD1.x卡、MMC卡。

数据传输模式

SD卡数据传输模式

SD卡单块数据读取流程

  1. 发送CMD16命令,设置数据块大小
  2. 等待CMD16响应(R1)
  3. 发送CMD17指令,开始读数据
  4. 等待CMD17响应(R1)
  5. 读一个数据块数据

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

SD卡多块数据读取流程

  1. 发送CMD16命令,设置数据块大小
  2. 等待CMD16响应(R1)
  3. 等待CMD18命令,开始读数据块
  4. 等待CMD18响应(R1)
  5. 读一个数据块数据
  6. 读第二个数据块数据
  7. ……
  8. 发送CMD12命令,结束数据块读取
  9. 等待CMD12响应(R1)
  10. 结束多块数据块读取

SD卡单块数据写入流程

  1. 发送CMD16命令,设置数据块大小
  2. 发送CMD13命令,查询卡状态
  3. 等待READY_FOR_DATA位=1
  4. 发送CMD24命令,开始写入数据
  5. 写入一个数据块数据

SD卡多块数据写入流程

  1. 发送CMD16命令,设置数据块大小
  2. 发送ACMD23命令,预擦除数据块(ACMD指令仅对SD卡有效,另外需要先发送CMD55指令)
  3. 发送CMD25命令,开始写入数据
  4. 写入第一个数据块
  5. 写入第二个数据块
  6. ……
  7. 发送CMD12命令,结束数据块写入
  8. 发送CMD13命令,查询卡状态
  9. 等待SD卡写入过程
  10. 完成多块数据块写入

SPI模式就直接跳过了,是针对Mini开发板的,我的是精英板,支持SDIO外设。

2.SDIO外设介绍

SDIO接口简介

SDIO,全程Secure Digital Input and Outpt,即安全数字输入输出接口。

SDIO外设

STM32F10x和F4xx系列控制器只支持SD卡规范版本2.0,即只支持标准容量SD卡和高容量SDHC卡,不支持超大容量SDXC标准卡,所以可支持最高卡容量为32G。

SDIO框图介绍

SDIO外设由SDIO适配器和AHC(F1)/APB2(F4)接口两部分组成:

SDIO框图

SDIO外设的三个时钟:

SDIO_CK:由SDIO适配器中的时钟产生器在外部引脚输出的通信时钟信号

不同总线协议,最高时钟频率不同;每个时钟脉冲传输的是命令或数据。

SDIOCLK:SDIO适配器的工作时钟——48MHz,来自主PLL的独立输出,和PLLCLK独立

计算公式:SDIO_CK = SDIOCLK / (2 + CLKDIV)。注意:SD卡初始化,SDIO_CK不能超过400kHz;初始化完成后可设为最大(不可超过SD卡最大操作频率25MHz)并可更改数据总线宽度(默认只用SDIO_D0进行初始化)

HCLK/2或PCLK2:CPU以此时钟访问SDIO外设寄存器,AHB总线接口时钟(HCLK/2)是36MHz,APB2总线接口时钟(PCLK2)是84MHz(F407) / 90(F429)MHz。

SDIO适配器:提供SD卡特有的功能:产生时钟、发送命令、接收响应、双向传输数据。

SDIO适配器

命令通道进入空闲至少8个SDIO_CK后,CPSM进入空闲状态

命令通道状态机CPSM

  1. 置位发送使能,写命令寄存器,命令开始发送
  2. 不需要响应,进入空闲状态
  3. 如果还需响应,进入等待状态,启动命令定时器
  4. 超时未接收到响应,置位超时标志,进入空闲状态
  5. 接收响应完成,根据CRC设置状态寄存器

命令发送完成后设置状态标志:

CMDREND:响应CRC正常

CCRCFAIL:响应CRC失败

CMDSENT:发送不需要响应的命令

CTIMEOUT:响应超时

CMDACT:正在进行命令传输

数据通道状态机(DPSM)

数据通道状态机DPSM

数据FIFO:包括32个字的数据缓冲和发送与接收电路;TXACT和RXACT标志分别表明处于发送还是接收状态,有数据通道子单元对这两个标志互斥的置位。

发送FIFO:SDIO发送数据,由数据通道单元置位TXACT,通过APB2接口(F4)/AHB接口(F1)将数据写入发送FIFO;相关状态——TXFIFOF、TXFIFOE、TXFIFOHE、TXDAVL、TXUNDERRUN。

UNDERRUN就是下溢出,读空FIFO后继续读导致下溢。

接收FIFO:SDIO接收数据,由数据单元置位RXACT,通过接收FIFO存放从数据通道接收到的数据;相关状态——RXFIFOF、RXFIFOE、RXFIFOHF、RXDAVL、RXOVERR。OVERR就是上溢,写满FIFO后继续写就导致上溢。

以上状态均可通过SDIO_STA状态寄存器查询,同时上溢和下溢可由硬件流控解决。

命令格式

命令是用于开始一项操作。命令在CMD线上串行发送,属于半双工模式,命令和响应可分别发送和接收。命令固定长度为48位

SDIO命令

SDIO块数据传输

SDIO和SD卡通信一般以数据块的形式进行传输。

SDIO数据传输

SD卡在收到主机相关命令后,开始发送数据块到主机,所有数据块都带CRC校验(由硬件自动处理);单块数据块读时,在收到1个数据块就停止,不需要发送停止命令。

多块数据块读时,SD卡将一直发送数据给主机,直到接到主机发送的STOP命令。

SDIO多块数据传输

数据块写操作同数据块读操作基本类似,只是数据块写时,多了一个繁忙判断,新的数据块必须在SD卡非繁忙时发送。

这里的繁忙信号由SD卡拉低SDIO_D0表示,SDIO硬件自动控制,不需要软件处理。

SDIO寄存器介绍

SDIO寄存器

SDIO电源控制寄存器(SDIO_POWER)

SDIO_POWER

STM32复位后,PWRCTRL=00,处于掉电状态。首先要给SDIO上电,PWRCTRL设置为11。

SDIO时钟控制寄存器(SDIO_CLKCR)

SDIO_CLKCR

注意:SDIO_CK频率过快可能导致SD卡通信失败,此时可以降低SDIO频率。

SDIO参数寄存器(SDIO_ARG)

SDIO_ARG

这个寄存器就是设置48位短命令时,配置[39:8]位数据的寄存器

SDIO命令寄存器(SDIO_CMD)

SDIO_CMD

首先要CPSMEN置1,然后根据命令需要配置WAITRESP,最后配置命令索引。

SDIO命令响应寄存器(SDIO_RESPCMD)

SDIO_RESPCMD

通过这个寄存器知道响应的是什么命令,而且这个寄存器是只读的。响应内容是另一个寄存器。

SDIO响应1~4寄存器(SDIO_RESP1~4)

SDIO_RESP1~4

短响应只需要看SDIO_RESP1,长响应需要读四个寄存器并重新组合。

SDIO数据定时器寄存器(SDIO_DTIMER)

SDIO_DTIMER

写入数据控制寄存器进行数据传输前,必须先写入数据定时器寄存器和数据长度寄存器

SDIO数据长度寄存器(SDIO_DLEN)

SDIO_DLEN

对于块数据,该寄存器值必须是数据块长度整数倍。

SDIO数据控制寄存器(SDIO_DCTRL)

SDIO_DCTRL

这里就是选择块传输以及控制器至卡。

SDIO状态寄存器(SDIO_STA)

SDIO_STA

主要关注以上圈出的位,来判断数据的传输状态。

SDIO数据FIFO寄存器(SDIO_FIFO)

SDIO_FIFO

收发的FIFO是32位宽度的读/写寄存器,在连续的32个地址上包含32个寄存器,CPU可以使用FIFO读写多个操作数。必须是以4字节对齐的内存进行操作,否则将导致出错

SDIO相关HAL库驱动

HAL库相关

用于发送SDIO_SendCommand函数,用于接收响应sdio_GetResponse函数。

相关结构体:SD_HandleTypeDef(SD_InitTypeDef)、SDIO_CmdInitTypeDef、SDIO_DataInitTypeDef、HAL_SD_CardInfoTypeDef。

SD卡HAL库驱动文件:stm32f1xx_hal_sd.c和stm32f1xx_ll_sdmmc.c。(前者封装了初始化、读写、擦除等驱动接口;后者对接SDIO寄存器与SD卡通讯)。

SDIO_HandleTypeDef

SDIO_HandleTypeDef

SDIO_CmdInitTypeDef

SDIO_CmdInitTypeDef

SDIO_DataInitTypeDef

SDIO_DataInitTypeDef

SDIO_DataInitTypeDef关联的函数SDIO_ConfigData,只有发送/收到数据块才会使用。

注意:SD卡操作是用数据块,MMC卡才是数据流。

HAL_SD_CardInfoTypeDef

HAL_SD_CardInfoTypeDef

通过HAL_SDGetCardInfo函数获取卡信息。

初始化SD卡函数:HAL_SD_Init()

  1. 初始化GPIO功能,SDIO时钟不超过400kHz
  2. 初始化SDIO外设接口(默认配置) (SDIO_Init)
  3. 开启SDIO电源,为卡提供时钟,并延时两毫秒(SDIO_PowerState_ON)
  4. 发送CMD0复位命令,卡到空闲状态
  5. 发送CMD8主机支持电压,询问卡是否支持
  6. 根据响应判断SD卡版本
  7. 反复发送ACMD41,等待OCR回应卡上电完成和卡容量类型(以上为SD_PowerON)
  8. 检查电源状态,进入准备状态
  9. 发送CMD2,获得卡信息(CID)
  10. 发送CMD3,获得卡相对地址(RCA)
  11. 发送CMD9,获得卡数据(CSD)
  12. 发送CMD7,选择卡,切换传输状态(以上为SD_InitCard)

第一步是HAL_SD_MspInit中;之后所有都是HAL_SD_InitCard。

读写函数:

HAL库读写函数

3.编程实战

驱动步骤:

  1. 初始化SD卡相关GPIO口——需要设置为复用推挽模式
  2. SD卡初始化——HAL_SD_Init
  3. 重新设置SDIO总线位宽——HAL_SD_WideBusOperation_config
  4. 数据块写入——HAL_SD_WriteBlocks
  5. 数据块读取——HAL_SD_ReadBlocks

SD卡原理图

TF卡原理图

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值