赞
踩
SD卡有SD、MiniSD和microSD三种类型。可以访问如下链接查看更多规定。https://www.sdcard.org https://www.sdcard.org
最新SD卡规格的参数如下图所示:
其中脚位数对应实卡上的"金手指"数,不同的类型的卡的触点数量不同,访问的速度也不同。
SD卡常见的两种访问接口模式是SDIO模式和SPI模式。
如下图SD卡对于两种模式的引脚功能定义:
microSD卡引脚功能如下图:
注: S: 电源 I: 输入 O: 推挽输出 PP: 推挽
SD卡内部物理结构如下图所示:
SD卡的寄存器信息如下:
SD卡的OCR、CID、CSD、和SCR寄存器保存卡的配置信息。RCA寄存器保存着通信过程中
卡当前暂时分配的地址(只适合SDIO模式,SPI模式下没有)。CSR寄存器表示卡状态(Card Status)
和SSR寄存器SD状态(SD Status)寄存器保存着卡的状态(例如:是否写成功,通信的CRC校验是否
正确等),这两个寄存器的内容与通信模式(SD模式或SPI模式)相关。MMC卡没有SRC和SSR寄存
器。
SD卡所有的命令都是固定长度48bit,6个Byte。格式如下图:
起始位:固定为0。
传输位:表示传输方向(主机 =1,从机=0)
命令号:占6个bit。
参数:占32个bit,4字节。
CRC7:7位CRC校验位。
结束位:占1bit。
SD卡的命令一共被分为了12类,分为Class0~Class11。比较重要的命令如下图:
SD卡系统定义了如下图几个工作模式。
对于开发来说只有卡识别和数据传输两种有效操作模式。
主机在系统复位后,处于卡识别模式。寻找总线上可用的SD卡。同时SD卡也处于卡识别模式,
直到被主机识别到,即SD卡在卡识别状态下收到CDM3(SEND_RCA)命令后,SD卡进入数据
传输模式,主机需在总线上所有卡被识别后进入数据传输模式。
SD卡识别模式状态转换如下图所示:
SD卡有两种数据模式,一种是常规8位宽度,即一次按一字节传输。另一种是512字节传输。本次只使用
第一种单字节传输模式。每次传输从最低字节开始,每字节从最高位(MSB)开始发送。数据传输模式下
SD卡状态转换过程如下图所示:
SPI下SD卡的初始化时序如下图所示:
根据初始化时序图,SPI模式下SD卡的初始化主要有以下几个步骤
1、初始化主机与SD卡连接的硬件条件(MCU的SPI配置,IO配置)
2、主机拉低片选(CS)信号,SD卡上电延时(74个CLK)。
3、复位卡(CMD0),进入IDLE状态。
4、发送CMD8命令,检查是否支持2.0协议。
5、根据不同协议检查SD卡(命令包括:CMD55、ACMD41、CMD58和CMD1等)。
6、取消片选,发多8个CLK信号,结束初始化。
以上步骤就可以完成对SD卡的初始化。接下来就可以对SD卡进行读写数据。
SD卡扇区读取数据,具体过程如下:
1、发送CMD17。
2、接收卡响应R1。
3、接收数据起始令牌0xFE。
4、接收数据。
5、接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉。
6、禁止片选之后,发多8个CLK。
SD卡写数据的过程如下所示:
1、发送CMD24。
2、接收卡响应R1。
3、发送写数据起始令牌0xFE。
4、发送数据。
5、发送2字节的伪CRC。
6、禁止片选之后,发多8个CLK。
更多资料请查看官方资料 https://www.sdcard.org/
ESP32-S3模组支持两个外部卡,但不支持同时工作。其内部连接结构如下图所示:
- void spi2_init(void)
- {
- esp_err_t ret = 0;
- spi_bus_config_t spi_bus_conf = {0};
- /* SPI总线配置 */
- spi_bus_conf.miso_io_num = SPI_MISO_GPIO_PIN; /* SPI_MISO引脚 */
- spi_bus_conf.mosi_io_num = SPI_MOSI_GPIO_PIN; /* SPI_MOSI引脚 */
- spi_bus_conf.sclk_io_num = SPI_CLK_GPIO_PIN; /* SPI_SCLK引脚 */
- spi_bus_conf.quadwp_io_num = -1; /* SPI写保护信号引脚,该引脚未使能 */
- spi_bus_conf.quadhd_io_num = -1; /* SPI保持信号引脚,该引脚未使能 */
- spi_bus_conf.max_transfer_sz = 320 * 240 * 2; /* 配置最大传输大小,以字节为单位 */
-
- /* 初始化SPI总线 */
- ret = spi_bus_initialize(SPI2_HOST, &spi_bus_conf, SPI_DMA_CH_AUTO); /* SPI总线初始化 */
- ESP_ERROR_CHECK(ret); /* 校验参数值 */
- // /* 添加SPI总线设备 */
-
- }
- /*
- *@brief SD卡初始化
- *@param 无
- *retval esp_err_t
- */
- esp_err_t sd_spi_init(void)
- {
- esp_err_t ret = ESP_OK;
- if(Sky_SD_Handle != NULL)
- {
- spi_bus_remove_device(Sky_SD_Handle); /*移除SPI上的SD卡设备*/
-
- if(mount_ret == ESP_OK)
- {
- esp_vfs_fat_sdcard_unmount(mount_point, card); //取消挂载
- }
- }
-
- /*SPI驱动接口配置,SPISD卡时钟是20-25MHZ*/
- spi_device_interface_config_t devcfg = {
- .clock_speed_hz = 20 * 1000 * 1000, //SPI时钟
- .mode = 0, //SPI模式0
- .spics_io_num = SD_NUM_CS, //片选引脚
- .queue_size = 7, //事务队列尺寸7个
- };
-
- ret = spi_bus_add_device(SPI2_HOST, &devcfg, &Sky_SD_Handle); //添加SPI总线设备
-
- esp_vfs_fat_sdmmc_mount_config_t mount_config = {
- .format_if_mount_failed = false, //若挂载失败:true会重新分区和格式化/false不会重新分区和格式化
- .max_files = 5, //打开文件最大数量
- .allocation_unit_size = 4 * 1024 * sizeof(uint8_t) //硬盘分区的大小
- };
-
- /*SD 卡参数配置*/
- sdmmc_host_t host = {0};
- host.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG; //定义主机属性的标志:SPI协议且可调用deinit函数
- host.slot = SPI2_HOST; //使用SPI2端口
- host.max_freq_khz = SDMMC_FREQ_DEFAULT; //主机支持的最大频率: 20000
- host.io_voltage = 3.3f; //控制器使用的I/O电压
- host.init = &sdspi_host_init; //用于初始化驱动程序的主机函数
- host.set_bus_width = NULL; //设置总线宽度的主机功能
- host.get_bus_width = NULL; //取总线宽度的主机函数
- host.set_bus_ddr_mode = NULL; //设置DDR模式的主机功能
- host.set_card_clk = &sdspi_host_set_card_clk; //设置板卡时钟频率的主机函数
- host.do_transaction = &sdspi_host_do_transaction; //执行事务的主机函数
- host.deinit_p = &sdspi_host_remove_device; //用于取消初始化驱动程序的主机函数
- host.io_int_enable = &sdspi_host_io_int_enable; //启用SDIO中断线的主机功能
- host.io_int_wait = &sdspi_host_io_int_wait; //等待SDIO中断线路激活的主机功能
- host.command_timeout_ms = 0; //超时,默认为0
- host.get_real_freq = &sdspi_host_get_real_freq;
- host.set_cclk_always_on = NULL;
-
-
- sdspi_device_config_t slot_config ={0};
- slot_config.host_id = host.slot;
- slot_config.gpio_cs = SD_NUM_CS;
- slot_config.gpio_cd = GPIO_NUM_NC;
- slot_config.gpio_wp = GPIO_NUM_NC;
- slot_config.gpio_int = GPIO_NUM_NC;
-
- mount_ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card); //挂载文件系统
- ret |= mount_ret;
-
- return ret;
-
- }
- /*
- *@brief 获取SD卡相关信息
- *@param out_total_bytes:总大小
- *@param out_free_bytes: 剩余带下
- *@retval 无
- */
-
- void sd_get_fatfs_usage(size_t *total_bytes, size_t *free_bytes)
- {
- FATFS *fs;
- size_t free_clusters;
- int res = f_getfree("0:", (size_t *)&free_clusters, &fs);
- assert(res == FR_OK);
- size_t total_sectors = (fs->n_fatent - 2) * fs->csize;
- size_t free_sectors = free_clusters * fs->csize;
- size_t sd_total = total_sectors / 1024;
- size_t sd_total_KB = sd_total * fs->ssize;
- size_t sd_free = free_sectors / 1024;
- size_t sd_free_KB = sd_free * fs->ssize;
-
- //假设总大小小于4GiB,对于SPI Flash 因该为true
- if(total_bytes != NULL)
- {
- *total_bytes = sd_total_KB;
- }
-
- if(free_bytes != NULL)
- {
- *free_bytes = sd_free_KB;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。