如何使用外部储存、如何使用标准文件系统读写信息,是比较大的课题,我想用几篇文章的幅度详细介绍自己写驱动程序、移植文件系统库,在不依赖ESP官方库的情况下完成ESP32S3对SD卡的控制,此过程解剖了SD卡操作和文件系统操作的核心。
这是系列文章,链接如下:
【ESP-IDF】ESP32S3用SPI读写 MicroSD/TF卡(二)读写正文数据_spi读写sd卡驱动需要自己写吗-CSDN博客
【ESP-IDF】ESP32S3用SPI读写 MicroSD/TF卡(三)移植FATFS文件系统-CSDN博客
【ESP-IDF】ESP32S3用SPI读写 MicroSD/TF卡(四-用ESPIDF官方库)_esp32 tf卡引脚-CSDN博客 此篇先解决物理驱动层,就是如何用SPI协议操控SD卡的寄存器。重点与硬件和SD卡数据手册交涉。
我用 ESPIDF自带的sdspi库失败,失败定位在SD卡初始化过程,发送多次ACMD41仍无法接收SD卡0x00回复,超时(主程序返回0x107错误),初始化失败。于是自己写了SD卡SPI模式的通讯协议查看究竟。
一、硬件
SD卡、MicroSD、TF卡都是用一样的代码一样的协议。MMC卡的协议流程略有不同。SD卡里面还有细分为超大容量SDXC、大容量SDHC和小容量SDSC(2GB以下)三种,接线一样,代码上略有区别,而这些区别挺致命的。


一开始用图1的MicroSD卡模块,有弹簧自锁的,还有3.3v稳压器,电路设计比图二稳当,但到了ACMD41初始化时尝试5000次都总是失败,CMD0和CMD8倒是正常。换过其他sd卡试过,耗了我好多天后,终于下单换了图二的模块,简陋一点,但原代码测试ACMD41就通过了,R1返回0x00。
我用这种256MB的便宜小卡,属于SDSC。
SD卡结构分为控制寄存器和储存单元,我们的指令就是操作控制寄存器。
二、SD卡手册关于指令、参数、response的说明
2.1 指令和参数
#define pin_CS 9
#define pin_MOSI 10
#define pin_MISO 12
#define pin_CLK 11
/*CMD type,包含从命令到CRC共48bits*/
#define CMD0 0x400000000095
#define CMD1 0x4100000000FF
#define CMD8 0x48000001AA87
#define CMD55 0x770000000065
#define ACMD41 0x694000000077
#define CMD58 0x7A00000000FF
#define CMD10 0x4A00000000FF //接收CID信息
#define CMD12 0x4C00000000FF //中止读写
#define CMD17 0x5100000000FF //读1个block 512bytes
#define CMD18 0x5200000000FF //读多个blocks
#define CMD24 0x5800000000FF //写1block
#define CMD25 0x5900000000FF //写多blocks
#define CMD13 0x4D00000000FF //写存储后查看卡status,R2响应
#define CMD32 0x6000000000FF //erase start addr
#define CMD33 0x6100000000FF //erase end addr
#define CMD38 0x6600000000FF //erase all
/*response type, the figure indicates length in bytes*/
typedef enum _response_t{R1=1,R7=5,R2=17,R3=5}response_t;
以上就是SD卡常用操作指令,而本篇需要用到的指令到CMD58为止,就能完成SD卡物理初始化过程,指令按出场顺序排好了。
说一下指令的数值构成。CMD0的数值就是0,CMD8就是8,CMD10就是十进制的10。以CMD10为例,10转变成十六进制就是0x0A,加上0x40就是0x4A了。所有指令都是从0x40开始加上去,看CMD0就知道了。
ACMD41也是跟普通CMD命令一样计算。十进制的41就是十六进制的0x29,加到0x40上等于0x69。ACMD41的第三位可以是4也可以是0,小容量卡用0也可,大容量卡用4,其实无论你用什么都不影响SD卡回复你的消息。
注意主机发出的所有指令,SD卡都会在后面回复一个response。
2.2 CRC计算
从CMD0至ACMD41都要强调CRC计算准确,ACMD41之后的指令随意填个CRC就可,SD卡手册这样说的。因为SPI模式下,SD卡不检查CRC。但是ACMD41之前卡片都没完成初始化,SD卡不清楚主机采用哪种方式来沟通,因此要正确的CRC。
计算CRC的工具在这个网址:
command用CRC7的模式,计算工具使用过程如下:
我这是用CMD55、0x77000000006