SD卡初始化及读写流程

合集下载

sd卡数据读写流程

sd卡数据读写流程

SD卡数据读写流程引言SD卡(Secure Digital Card)是一种常用的存储设备,通常用于移动设备、相机等电子产品中。

在使用SD卡时,数据的读写是一个非常重要的过程。

本文将详细介绍SD卡的数据读写流程,包括初始化、文件操作和数据传输等环节。

初始化SD卡初始化SD卡是数据读写的第一步,确保SD卡可以被正确地识别和使用。

下面是SD卡数据读写的初始化流程:1.插入SD卡:将SD卡插入目标设备的SD卡插槽中。

2.电源供给:为SD卡提供稳定的电源,通常通过连接电源线或使用内置电池来实现。

3.延时等待:等待SD卡稳定,一般为几毫秒的时间。

4.发送命令:通过SPI或SDIO等接口向SD卡发送特定的命令,以初始化SD卡。

5.接收响应:SD卡将返回初始化成功与否的响应,如果初始化成功,则可以进行后续的数据读写操作。

SD卡文件系统在进行数据读写之前,需要先设置SD卡的文件系统。

常用的文件系统包括FAT16、FAT32和exFAT等。

下面是SD卡文件系统的设置流程:1.格式化SD卡:使用格式化工具对SD卡进行格式化,以清除原有的文件系统和数据。

2.创建分区:根据需求,可以将SD卡分为一个或多个分区,并设置每个分区的大小。

3.创建文件系统:选择合适的文件系统类型,在分区上创建文件系统,并分配文件系统的容量。

4.分配文件表:文件系统会维护一个文件表,记录文件的位置、大小等信息。

在创建文件系统时,会分配一块空间来存储文件表。

5.设置文件权限:根据需要,可以设置文件的读写、执行权限,以保证文件的安全性。

SD卡数据读写操作SD卡的数据读写操作包括文件的创建、打开、读取、写入和关闭等。

下面是SD卡数据读写操作的详细流程:1.创建文件:通过文件系统接口,调用相关函数创建一个新的文件,并指定文件的名称和路径。

2.打开文件:使用文件系统的函数打开已经存在的文件,以便后续的读取和写入操作。

3.读取文件:通过文件系统提供的函数,在已经打开的文件中进行读取操作。

sd卡读写模块的用法

sd卡读写模块的用法

sd卡读写模块的用法
SD卡读写模块是一种用于读写SD卡存储设备的模块。

它通常通过SPI或SDIO接口与主控制器(如单片机、开发板等)连接,并提供读
取和写入SD卡的功能。

使用SD卡读写模块的步骤如下:
1.初始化:通过控制模块的引脚,配置SPI或SDIO接口的工作模
式和相关参数。

2.卡插入检测:通过检测SD卡插槽的接触状态,确定是否插入了SD卡。

3.卡初始化:对SD卡进行初始化操作,包括发送命令和接收响应,以确认SD卡的类型和性能等信息。

4.数据读取:发送读取命令和地址,接收SD卡返回的数据。

5.数据写入:发送写入命令和地址,将数据写入SD卡的指定块位置。

在使用SD卡读写模块时,我们还可以拓展以下几个方面:
1.多线程读写:通过同时使用多个SPI或SDIO接口,实现多个线程同时读写SD卡,提高数据传输速度。

2. SD卡文件系统:在SD卡中创建文件系统(如FAT32),将数据按照文件的形式进行存储和管理,提供更加灵活和高效的数据存储方式。

3.数据加密:将敏感的数据进行加密后再写入SD卡,防止数据泄露和篡改。

4.文件压缩:在将数据写入SD卡之前,使用压缩算法(如ZIP)对数据进行压缩,减小存储空间占用。

5.数据校验:在读取或写入数据时,进行校验(如CRC校验)以确保数据的完整性和准确性。

总之,SD卡读写模块的使用方式可以根据具体需求进行拓展,以实现更多功能和提升性能。

SDMMC卡初始化及读写流程分解

SDMMC卡初始化及读写流程分解

二、MMC/SD卡的模型和工作原理PIN脚、SD卡总线、SD卡结构、SD卡寄存器、上电过程SD卡寄存器:OCR:操作电压寄存器: 只读,32位第31位:表示卡上电的状态位CID: 卡身份识别寄存器只读128位生产厂商、产品ID,生产日期和串号等CSD:部分可写128位卡的容量、擦出扇区大小、读写最大数据块的大小、读操作的电流、电压等等 CSR: 卡配置寄存器64位数据位宽RCA:16位相关的卡地址寄存器,卡识别过程中主控器和卡协商出来的一个地址三、SD卡命令和响应格式命令和相应格式SD卡命令,命令类型,ACMD命令响应类型、卡类型、卡状态转换表命令的格式:48位起始位0 方向位(host to card: 1, card to host: 0)内容CRC7 结束位1·响应的格式:48位或者136位卡命令:命令的类型:bc: broadcast without Response 无响应的广播bcr: broadcast with Response 有响应的广播ac: Address(point-to-point) Command: 点对点,DATA0~DATA3数据线上无数据adtc: Adress(point-to-point) Data Transfer Commands 点对点,DATA0~DATA3数据线上有数据CMD0, CMD2, CMD3, CMD55, ACMD41 命令可能会导致卡的状态发生变化响应类型:R1,R1b, R2, R3,R6(SD2.0扩展了R7)扩展内容:SPI工作模式:要知道的特点:只支持一个卡,没有RCA,命令只是MMC/SD的基本的子集SDHC:(支持2GB~32GB):理解CMD8的作用,命令格式和响应,了解CSDV2.0寄存器做了扩展SDIO WIFI:增加CMD52,CMD53CMD8可以通过重新定义先前保留的位,来扩展一些已经存在的命令的新功能。

SD卡读写操作

SD卡读写操作

SD卡操作一、概述1、简介SD卡是基于flash的存储卡。

SD卡和MMC卡的区别在于初始化过程不同。

SD卡的通信协议包括SD和SPI两类。

SD卡使用卡内智能控制模块进行FLASH操作控制,包括协议、安全算法、数据存取、ECC算法、缺陷处理和分析、电源管理、时钟管理。

2、功能介绍2.1 特点1)主机无关的FLASH内存擦除和编程读或写数据,主机只要发送一个带地址的命令,然后等待命令完成,主机无需关心具体操作的完成。

当采用新型的FLASH时,主机代码无需更新。

2)缺陷管理3)错误恢复4)电源管理Flash每个扇区有大约10万次的写寿命,读没有限制。

擦除操作可以加速写操作,因为在写之前会进行擦除。

3 SD总线模式3.1 Negotiating Operation Conditions当主机定义了SD卡不支持的电压范围时,SD卡将处于非活动状态,将忽略所有的总线传输。

要退出非活动状态唯一的方法就是重新上电。

3.2 SD卡获取和识别SD卡总线采用的是单主多从结构,总线上所有卡共用时钟和电源线。

主机依次分别访问每个卡,每个卡的CID寄存器中已预编程了一个唯一的卡标识号,用来区分不同的卡。

主机通过READ_CID命令读取CID寄存器。

CID寄存器在SD卡生产过程中的测试和格式化时被编程,主机只能读取该号。

DAT3线上内置的上拉电阻用来侦测卡。

在数据传输时电阻断开(使用ACMD42)。

3.3 卡状态卡状态分别存放在下面两个区域:卡状态(Card Status),存放在一个32位状态寄存器,在卡响应主机命令时作为数据传送给主机。

SD状态(SD_Status),当主机使用SD_STATUS(ACMD13)命令时,512位以一个数据块的方式发送给主机。

SD_STATUS还包括了和BUS_WIDTH、安全相关位和扩展位等的扩展状态位。

3.4 内存组织数据读写的基本单元是一个字节,可以按要求组织成不同的块。

Block:块大小可以固定,也可以改变,允许的块大小是实际大小等信息存储在CSD寄存器。

sd卡数据读写流程

sd卡数据读写流程

sd卡数据读写流程一、概述SD卡是一种常用的存储设备,应用广泛。

在进行SD卡数据读写操作时,需要了解其基本流程及相关细节。

本文将详细介绍SD卡数据读写流程。

二、准备工作1. 确认SD卡类型:根据需求选择合适的SD卡类型,如标准SD卡、Mini SD卡、Micro SD卡等。

2. 准备读写设备:需要使用支持SD卡的读写设备,如读卡器、手机、相机等。

3. 系统环境:根据不同操作系统选择相应的驱动程序和开发工具。

三、初始化SD卡1. 电源接口:将SD卡插入读写设备中,并接通电源。

2. 查找CMD线:通过CMD线查找到SD卡,并发送复位命令。

3. 发送初始化命令:发送初始化命令后,等待SD卡响应并返回状态码。

四、读取CID和CSD寄存器信息1. 发送CMD10命令:通过CMD10命令可以获取CID寄存器信息。

2. 发送CMD9命令:通过CMD9命令可以获取CSD寄存器信息。

五、设置Block长度1. 发送CMD16命令:通过CMD16命令设置Block长度,即每次读取或写入的字节数。

六、数据传输1. 读取数据:发送CMD17命令,指定读取的起始地址和读取的Block数量,等待SD卡响应并返回数据。

2. 写入数据:发送CMD24命令,指定写入的起始地址和写入的Block数量,等待SD卡响应并写入数据。

七、结束操作1. 发送CMD12命令:结束操作前需要发送CMD12命令,以停止多块传输。

2. 断开电源:操作完成后需要断开SD卡电源。

八、注意事项1. SD卡在进行读写操作时需要保持稳定的电压和供电。

2. 操作过程中需要注意各种状态码及其含义。

3. 合理选择Block长度可以提高读写速度。

以上就是SD卡数据读写流程的详细介绍。

在实际应用中,还需要根据具体情况进行合理调整和优化。

SD卡的结构原理和基本读写操作方式

SD卡的结构原理和基本读写操作方式

SD卡的结构原理和基本读写操作方式摘要:本文首先介绍了SD Memory Card ( Secure D ig ita l MemoryCard)的基本结构和原理,着重对SD 卡的命令字和操作流程进行介绍。

接着研究了三星32位嵌入式处理器S3C2410与SD 卡硬件接口电路及其对SD卡的基本读写操作方式。

1 引言SD卡( Secure DigitalMemory Card)是一种基于Flash的新一代存储器,它着重数据存储的安全、容量和性能,是许多便携式电子产品如数码相机、手提电话, PDA 等理想的外部存储介质。

2 SD的基本概念2. 1 SD的通信协议SD卡系统可以在两种通信协议下工作: SD协议和SP I协议。

用户可以在硬件初始化时自由选择SD卡系统的通信协议。

对于特定的硬件电路,用户只需使用一种通信协议即可。

本文根据笔者的硬件,仅讨论最常用的SD协议。

2. 2 SD数据传输方式SD支持两种数据传输方式: 1 - bit方式(标准总线)和4- bit方式(宽总线)。

在1 - bit方式下,数据仅仅在数据线0(DAT[ 0 ])上传输。

在4 - bit方式下,数据在4 根数据线(DAT[ 3: 0 ])上同时传输。

在4 - bit数据传输方式下,最高的数据传输速率可达100Mb / sec。

表1列出了在两种方式下SD接口信号的定义。

上电后,缺省状态下系统工作于1 - bit方式。

在SD卡处于传输状态时,用户可以自由地更改为1 - bit或4 - bit方式。

2. 3 SD 通信原理SD总线是一个星型的总线结构,系统中允许有一个主控器,最多可达十个从设备( SD卡)。

在系统初始化时,主控器分别为每一个设备分配一个设备地址,此后主控器就可以根据此设备地址独立操作该设备。

SD总线通信是基于命令和数据位流的,每一个数据流都包括一个起始位和一个结束位。

每一个SD命令表征一个卡操作的开始。

SD命令由命令线(CMD)进行传输。

stm32SPI模式读写SD卡

stm32SPI模式读写SD卡

stm32SPI模式读写SD卡SPI模式读写SD卡SD卡初始化过程:1. 初始化STM32的SPI接口使用低速模式2. 延时至少74clock3. 发送CMD0,需要返回0x01,进入Idle状态4. 循环发送CMD55+ACMD41,直到返回0x00,进入Ready状态5. 设置读写block大小为512byte5. 把STM32的SPI设置为高速模式读一个block块的过程1. 发送CMD17(单块)或CMD18(多块)读命令,返回0x002. 接收数据开始令牌0xfe + 正式数据512Bytes + CRC 校验2Bytes写一个block块的过程1. 发送CMD24(单块)或CMD25(多块)写命令,返回0x002. 发送数据开始令牌0xfe + 正式数据512Bytes + CRC校验2Bytes/******************************************************************* ************* Function Name : SD_MMC_SPI_Init* Description : SD_MMC_SPI_Init* Input : None* Output : None* Return : zero init success, non-zero init error************************************************************************ *******/u8 SD_MMC_SPI_Init(void){GPIO_InitTypeDef GPIO_InitStructure;/* Enable SPI1 and GPIO clocks */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_SD_MMC_SPI_CS, ENABLE);/* Configure SPI1 pins: SCK, MISO and MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Configure SD_MMC_SPI_CS */GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_CS_Pin_CS;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);///////////////////////////////////////////////////////////////////////////////* initialize SPI with lowest frequency */SD_MMC_Low_Speed();/* card needs 74 cycles minimum to start up */for(u8 i = 0; i < 10; ++i) {/* wait 8 clock cycles */ SD_MMC_ReadWrite_Byte(0x00); } /* address card */ SD_MMC_SPI_SELECT();/* reset card */u8 response;for(u16 i = 0; ; ++i){response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE ,0 );if( response == 0x01 ) break;if(i == 0x1ff) {SD_MMC_SPI_DESELECT(); return 1;}}/* wait for card to get ready */ for(u16 i = 0; ; ++i) {response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);if(!(response & (1 << R1_IDLE_STATE)))break;if(i == 0x7fff) {SD_MMC_SPI_DESELECT(); return 1;}}/* set block size to 512 bytes */if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512)) {SD_MMC_SPI_DESELECT();return 1;}/* deaddress card */SD_MMC_SPI_DESELECT();/* switch to highest SPI frequency possible */ SD_MMC_High_Speed();return 0;//////////////////////////////////////////////////////////////////// //////////}/******************************************************************* ************* Function Name : SD_MMC_Read_Single_Block * Description :SD_MMC_Read_Single_Block * Input : sector number and buffer data point * Output : None* Return : zero success, non-zero error************************************************************************ *******/u8 SD_MMC_Read_Single_Block(u32 sector, u8* buffer) {u8 Response;u16 i;u16 Retry = 0;//读命令 send read commandResponse =SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, sector<<9); if(Response != 0x00)return Response;SD_MMC_SPI_SELECT();// start byte 0xfewhile(SD_MMC_ReadWrite_Byte(0xff) != 0xfe) {if(++Retry > 0xfffe){SD_MMC_SPI_DESELECT();return 1; //timeout}}for(i = 0; i < 512; ++i) {//读512个数据*buffer++ = SD_MMC_ReadWrite_Byte(0xff); }SD_MMC_ReadWrite_Byte(0xff); //伪crcSD_MMC_ReadWrite_Byte(0xff); //伪crcSD_MMC_SPI_DESELECT();SD_MMC_ReadWrite_Byte(0xff); // extra 8 CLKreturn 0;}/******************************************************************* ************* Function Name : SD_MMC_Write_Single_Block* Description : SD_MMC_Write_Single_Block * Input : sector number and buffer data point* Output : None* Return : zero success, non-zero error.************************************************************************ *******/u8 SD_MMC_Write_Single_Block(u32 sector, u8* buffer) {u8 Response;u16 i;u16 retry=0;//写命令 send write commandResponse =SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, sector<<9);if(Response != 0x00)return Response;SD_MMC_SPI_SELECT();SD_MMC_ReadWrite_Byte(0xff);SD_MMC_ReadWrite_Byte(0xff);SD_MMC_ReadWrite_Byte(0xff);//发开始符 start byte 0xfeSD_MMC_ReadWrite_Byte(0xfe);//送512字节数据 send 512 bytes datafor(i=0; i<512; i++){SD_MMC_ReadWrite_Byte(*buffer++);}SD_MMC_ReadWrite_Byte(0xff); //dummy crc SD_MMC_ReadWrite_Byte(0xff); //dummy crcResponse = SD_MMC_ReadWrite_Byte(0xff);//等待是否成功 judge if it successfulif( (Response&0x1f) != 0x05){SD_MMC_SPI_DESELECT();return Response;}//等待操作完 wait no busywhile(SD_MMC_ReadWrite_Byte(0xff) != 0x00) {if(retry++ > 0xfffe){SD_MMC_SPI_DESELECT();return 1;}}SD_MMC_SPI_DESELECT();SD_MMC_ReadWrite_Byte(0xff);// extra 8 CLKreturn 0;}if( SD_MMC_SPI_Init() ==1)printf(" _SD_MMC Initialization ERROR\r\n"); else{printf(" _SD_MMC Initialization OK\r\n"); //memset(buffer,0,512); //读取一个扇区的内容这里读的是0扇区SD_MMC_Read_Single_Block( 0 , buffer );Uart1_PutString( buffer , 512 );}。

sdio linux驱动流程图

sdio linux驱动流程图

SD卡的工作原理想了解SD卡的工作原理,首先需要了解的就是SD卡协议了,这个在网上可以轻松的下载到。

在了解协议后,就可以看看下面的一些开发思路了。

首先看下脱离操作系统如何在S3C2410上实现SD卡的读写。

过程可以分为3个大的步骤:初始化sd卡、写sd卡、读sd卡;下面的过程是我通过realview-MDK环境测试过的。

一、初始化sd卡二、写sd卡写sd卡可以分为3种方式:POLL、中断、DMA (1)POLL写三、读sd卡读sd卡也可分为3中方式:POLL、中断、DMA (1)POLL读SD卡linux驱动工作原理,说了下脱离操作系统如何在S3C2410上实现SD卡的读写。

了解了脱离操作系统的工作原理后,现在可以思考linux是如何管理管理SD卡的了。

Linux中SD驱动可以分为3层:块设备层(mmc_block.c ,mmc_sysfs.c,mmc_queue.c)、mmc协议层(mmc.c)、sd驱动层(s3c2410_sdi.c)。

下面从以下几个方面理解驱动:1、s3c2410_sdi.c代码初始化过程;2、SD卡块设备注册过程;3、request及数据传输的实现。

下面介绍的过程参考的代码是内核版本是2.6.8,其它版本过程类似。

一、s3c2410_sdi.c代码初始化过程二、SD卡块设备注册过程三、request及数据传输的实现SD卡调试关键点:1. 上电时要延时足够长的时间给SD卡一个准备过程,在我的程序里是5秒,根据不同的卡设置不同的延时时间。

SD 卡初始化第一步在发送CMD命令之前,在片选有效的情况下首先要发送至少74个时钟,否则将有可能出现SD卡不能初始化的问题。

2. SD卡发送复位命令CMD0后,要发送版本查询命令CMD8,返回状态一般分两种,若返回0x01表示此SD卡接受CMD8,也就是说此SD卡支持版本2;若返回0x05则表示此SD卡支持版本1。

因为不同版本的SD卡操作要求有不一样的地方,所以务必查询SD卡的版本号,否则也会出现SD卡无法正常工作的问题。

SD卡的读写和加解密

SD卡的读写和加解密

查看文章SD卡的读写和加解密2007-06-13 07:04SD卡的读写和加解密一、概述SD卡全称为Secrue Digital Memory Card,具有轻巧、可加密、传输速度高、适用于手持设备使用等优点。

二、总线接口SD需要高速读写,同时也要使手持等嵌入式设备能方便使用,特设有两个访问接口中:SD 模式接口和SPI接口。

SD卡在上电初期,卡主控通过检测引脚1(DA T3)来决定使用SD 模式还是SPI模式。

当此脚接50KOhm上拉电阻时,卡进入SD模式;当此脚为低电平,卡则工作于SPI模式。

SD引脚SD模式SPI模式1 DA T3 CS2 CMD DI3 VSS VSS4 VDD VDD5 CLK SCLK6 VSS VSS7 DA T0 DO8 DA T1 Resvered9 DA T2 Resvered表1:SD卡接口定义1、SPI接口SPI接口是为嵌入式和手持设备准备的,只使用普通的三线制SPI总线,即可对卡进行一般的慢速的读写等操作。

图一:SPI总线如上图,由读卡器到卡的数据,在每个时种的上升沿把DO的数据锁存到卡主控,而卡的数据则在每个CLK的上升沿把DI的数据读入读卡器。

2、SD接口SD接口是为高速专有设备而设计,使设备能对卡进行高速可靠的传输而设计,因SD模式在每个命令及数据转输时,都必须具有正确的CRC校验。

因此,此模式下主机一般需要专门设计的硬件模块以产生CRC校验。

在此模式下,SD卡具有四根数据线,且时种速度最大可达50MHz,所以此模式下数据传输速率比SPI模式快得多。

三、总线协议SD卡命令共分为12类,分别为class0到class11,不同的卡主控根据其功能,支持不同的命令集。

主要如下:class0:卡的识别、初始化命令集。

class2:读卡命令集class4:写卡命令集class7:卡的锁定,解锁功能命令集SD卡只有唯一的主机,所有命令是由主机发出。

总线上可传输三种类型数据,分别是命令帧、响应、数据。

单片机读写SD卡教程

单片机读写SD卡教程

单片机读写SD卡教程引言:SD卡(Secure Digital Card)是广泛应用于各类数字设备上的一种存储介质。

它小巧轻便,可靠性高,容量大,因此在各种嵌入式系统中都广泛使用。

本教程将介绍如何使用单片机读写SD卡,包括初始化SD卡、读写数据等基本操作。

一、硬件准备在开始之前,我们需要准备以下硬件设备:1.一个支持SPI协议的单片机开发板(例如STC89C51、STM32等);2.一个SD卡插槽,或者是一个带有SD卡插槽的扩展板;3.杜邦线、面包板等连接器。

二、软件准备除了硬件设备,我们还需要准备以下软件工具:1. Keil C51、IAR、Keil MDK等单片机编译工具;2. SD卡相关的库文件,例如FatFs;3.一个用于测试的程序(可以是一个简单的读写数据的程序)。

三、连接SD卡插槽将SD卡插入到对应的插槽中,并将插槽与单片机的硬件SPI接口连接。

根据不同的开发板,连接方式可能有所不同,一般SPI接口包括SCK(时钟线)、MOSI(主机输出从机输入线)、MISO(主机输入从机输出线)和CS(片选线)等。

四、编写读写SD卡的程序在开始编写程序之前,我们需要先了解SD卡的工作原理。

SD卡通过SPI总线与单片机进行通信,通过发送特定的命令和参数实现读写操作。

以下是一个简单的读写SD卡的流程:1.初始化SD卡a.发送CMD0命令,将SD卡设置为SPI模式;b.发送CMD8命令,验证SD卡是否支持高速SPI模式;c.发送ACMD41命令,等待SD卡初始化完成。

2.读写数据a.发送CMD17命令,指定要读取的扇区地址;b.等待SD卡回应,确认读取命令执行成功;c.读取数据;d.发送CMD18命令,继续读取下一个扇区;e.重复步骤c和d,直到读取完所有数据;f.发送CMD12命令,停止读取。

g.发送CMD24命令,指定要写入的扇区地址;h.等待SD卡回应,确认写入命令执行成功;i.写入数据;j.发送CMD25命令,继续写入下一个扇区;k.重复步骤i和j,直到写入完所有数据;l.发送CMD12命令,停止写入。

SD卡读写操作详细说明

SD卡读写操作详细说明

51单片机实现对SD卡的读写SD卡SPI模式下与单片机的连接图:22.23.//获得16位的回应24. Read_Byte_SD(); //read the first byte,ignore it.25.do26. { //读取后8位27. tmp = Read_Byte_SD();28. retry++;29. }30.while((tmp==0xff)&&(retry<100));31.return(tmp);32.}2)初始化SD卡的初始化是非常重要的,只有进行了正确的初始化,才能进行后面的各项操作。

在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。

在初始化成功后,应尽量提高SPI的速率。

在刚开始要先发送至少74个时钟信号,这是必须的。

在很多读者的实验中,很多是因为疏忽了这一点,而使初始化不成功。

随后就是写入两个命令CMD0与CMD1,使SD卡进入SPI模式初始化时序图:初始化例程:1.//--------------------------------------------------------------------------2.初始化SD卡到SPI模式3.//--------------------------------------------------------------------------4.unsigned char SD_Init()5.{6.unsigned char retry,temp;7.unsigned char i;8.unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};9. SD_Port_Init(); //初始化驱动端口10.11. Init_Flag=1; //将初始化标志置112.13.for (i=0;i<0x0f;i++)14. {15. Write_Byte_SD(0xff); //发送至少74个时钟信号16. }17.18.//向SD卡发送CMD019. retry=0;20.do21. { //为了能够成功写入CMD0,在这里写200次22. temp=Write_Command_SD(CMD);23. retry++;24.if(retry==200)25. { //超过200次26.return(INIT_CMD0_ERROR);//CMD0 Error!27. }28. }29.while(temp!=1); //回应01h,停止写入30.31.//发送CMD1到SD卡32. CMD[0] = 0x41; //CMD133. CMD[5] = 0xFF;34. retry=0;35.do36. { //为了能成功写入CMD1,写100次37. temp=Write_Command_SD(CMD);38. retry++;39.if(retry==100)40. { //超过100次41.return(INIT_CMD1_ERROR);//CMD1 Error!4.unsigned char Read_CSD_SD(unsigned char *Buffer)5.{6.//读取CSD寄存器的命令7.unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};8.unsigned char temp;9. temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes10.return(temp);11.}4)读取SD卡信息综合上面对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。

SD卡的初始化和读写程序

SD卡的初始化和读写程序

/****************************************************************************** *****SPI模式读写SD卡SD卡初始化过程:1. 初始化STM32的SPI接口使用低速模式2. 延时至少74clock3. 发送CMD0,需要返回0x01,进入Idle状态4. 循环发送CMD55+ACMD41,直到返回0x00,进入Ready状态5. 设置读写block大小为512byte5. 把STM32的SPI设置为高速模式读一个block块的过程1. 发送CMD17(单块)或CMD18(多块)读命令,返回0x002. 接收数据开始令牌0xfe + 正式数据512Bytes + CRC 校验2Bytes写一个block块的过程1. 发送CMD24(单块)或CMD25(多块)写命令,返回0x002. 发送数据开始令牌0xfe + 正式数据512Bytes + CRC校验2Bytes-----------------------------------------------------------------------------* ----------------------------------------------* | STM32F10x | MSD Pin |* ----------------------------------------------* | PE.3 | ChipSelect 1 |* | PA.7 / MOSI | DataIn 2 |* | | GND 3 (0 V) |* | | VDD 4 (3.3 V) |* | PA.5 / SCLK | Clock 5 |* | | GND 6 (0 V) |* | PA.6 / MISO | DataOut 7 |* -----------------------------------------------******************************************************************************* ****//* Includes ------------------------------------------------------------------*///#include "stm32f10x_lib.h"#include "stm32f10x.h"#include "hardwareinit.h"/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*/#define sd_cs_1 GPIO_SetBits(GPIOB,GPIO_Pin_12)#define sd_cs_0 GPIO_ResetBits(GPIOB,GPIO_Pin_12)#define sd_check GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15)/* Select MSD Card: ChipSelect pin low *///#define MSD_CS_LOW() GPIO_ResetBits(GPIOE, GPIO_Pin_3)/* Deselect MSD Card: ChipSelect pin high *///#define MSD_CS_HIGH() GPIO_SetBits(GPIOE, GPIO_Pin_3)//SD传输数据结束后是否释放总线宏定义#define NO_RELEASE 0#define RELEASE 1// SD卡类型定义#define SD_TYPE_MMC 0#define SD_TYPE_V1 1#define SD_TYPE_V2 2#define SD_TYPE_V2HC 4// SD卡指令表#define CMD0 0 //卡复位#define CMD1 1#define CMD9 9 //命令9 ,读CSD数据#define CMD10 10 //命令10,读CID数据#define CMD12 12 //命令12,停止数据传输#define CMD16 16 //命令16,设置SectorSize 应返回0x00#define CMD17 17 //命令17,读sector#define CMD18 18 //命令18,读Multi sector#define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block #define CMD24 24 //命令24,写sector#define CMD25 25 //命令25,写Multi sector#define ACMD41 41 //命令41,应返回0x00#define CMD55 55 //命令55,应返回0x01#define CMD58 58 //命令58,读OCR信息#define CMD59 59 //命令59,使能/禁止CRC,应返回0x00//数据写入回应字意义#define MSD_DATA_OK 0x05#define MSD_DATA_CRC_ERROR 0x0B#define MSD_DATA_WRITE_ERROR 0x0D#define MSD_DATA_OTHER_ERROR 0xFF//SD卡回应标记字#define MSD_RESPONSE_NO_ERROR 0x00#define MSD_IN_IDLE_STA TE 0x01#define MSD_ERASE_RESET 0x02#define MSD_ILLEGAL_COMMAND 0x04#define MSD_COM_CRC_ERROR 0x08#define MSD_ERASE_SEQUENCE_ERROR 0x10#define MSD_ADDRESS_ERROR 0x20#define MSD_PARAMETER_ERROR 0x40#define MSD_RESPONSE_FAILURE 0xFF#define Dummy_Byte 0xA5 //0xff/* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*///u8 Dummy_Byte = 0xa5; //0xff;u8 SD_Type; //SD卡的类型u8 buf[512];/* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*/FlagStatus sd_insert_check(void);u8 SD_WaitReady(void); //等待SD卡就绪u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc); //SD卡发送一个命令u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);u8 SD_Init(void); //SD卡初始化u8 SD_Idle_Sta(void); //设置SD卡到挂起模式u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据u8 SD_GetCID(u8 *cid_data); //读SD卡CIDu8 SD_GetCSD(u8 *csd_data); //读SD卡CSDu32 SD_GetCapacity(void); //取SD卡容量//USB 读卡器SD卡操作函数//u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite);//u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);u8 SD_ReadSingleBlock(u32 sector, u8 *buffer); //读一个sectoru8 SD_WriteSingleBlock(u32 sector, const u8 *buffer); //写一个sectoru8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count); //读多个sectoru8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count);//写多个sectoru8 SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes);//读取一byte//--------------------------------spi speed setting-------------------------/****************************************************************************** ** Function Name : SPI_Config* Description : Initializes the SPI1 and CS pins.* Input : None* Output : None* Return : None******************************************************************************* /void SPI_Config(u16 BaudRatePrescaler){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;/* GPIOA and GPIOC Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);/* SPI1 Periph clock enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);/* Configure SPI2 pins: SCK, MISO and MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure PE3 pin: CS pin */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_12);/* SPI1 Config */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = BaudRatePrescaler;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI2, &SPI_InitStructure);/* SPI1 enable */SPI_Cmd(SPI2, ENABLE);}void spi_high_speed(void){//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//SPI_BaudRatePrescaler_256;//SPI_Init(SPI2, &SPI_InitStructure);SPI_Config(SPI_BaudRatePrescaler_4);}void spi_low_speed(void){//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//SPI_BaudRatePrescaler_4;//SPI_Init(SPI2, &SPI_InitStructure);SPI_Config(SPI_BaudRatePrescaler_256);}//---------------sd_insert_check---------------------------FlagStatus sd_insert_check(void){FlagStatus card_exist_state;if(!sd_check){card_exist_state = SET;}else{card_exist_state = RESET;}return card_exist_state;}//-------------------------------------------------------------------------/****************************************************************************** ** Function Name : SPI_FLASH_SendByte* Description : Sends a byte through the SPI interface and return the byte* received from the SPI bus.* Input : byte : byte to send.* Output : None* Return : The value of the received byte.******************************************************************************* /u8 SPIx_ReadWriteByte(u8 byte){/* Loop while DR register in not emplty */while ((SPI2->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);/* Send byte through the SPI1 peripheral *///SPI_I2S_SendData(SPI2, byte);SPI2->DR = byte;/* Wait to receive a byte */while((SPI2->SR &SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);/* Return the byte read from the SPI bus *///return SPI_I2S_ReceiveData(SPI2);return SPI2->DR;}//u8 SPIx_ReadWriteByte(u8 byte)//{/* Loop while DR register in not emplty *///while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)/* Send byte through the SPI1 peripheral *///SPI_I2S_SendData(SPI2, byte);/* Wait to receive a byte *///while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);/* Return the byte read from the SPI bus *///return SPI_I2S_ReceiveData(SPI2);//}/****************************************************************************** ** Function Name : SPI_FLASH_ReadByte* Description : Reads a byte from the SPI Flash.* This function must be used only if the Start_Read_Sequence* function has been previously called.* Input : None* Output : None* Return : Byte Read from the SPI Flash.******************************************************************************* /u8 SPI_ReadByte(void){return (SPIx_ReadWriteByte(Dummy_Byte));}//-----------------------------------------------------------------------------------------------------------------------------------//等待SD卡回应//Response:要得到的回应值//返回值:0,成功得到了该回应值// 其他,得到回应值失败u8 SD_GetResponse(u8 Response){u16 Count=0xFFF;//等待次数while ((SPIx_ReadWriteByte(0XFF)!=Response)&&Count) Count--;//等待得到准确的回应if (Count==0){return MSD_RESPONSE_FAILURE;//得到回应失败}else{return MSD_RESPONSE_NO_ERROR;//正确回应}}//------------------------------------------------------------------------//等待SD卡写入完成//返回值:0,成功;// 其他,错误代码;u8 SD_WaitDataReady(void){u8 r1=MSD_DATA_OTHER_ERROR;u32 retry;retry=0;do{r1=SPIx_ReadWriteByte(0xFF)&0X1F; //读到回应if(retry==0xfffe)return 1;retry++;switch (r1){case MSD_DATA_OK: //数据接收正确了r1=MSD_DATA_OK;break;case MSD_DATA_CRC_ERROR: //CRC校验错误return MSD_DATA_CRC_ERROR;case MSD_DATA_WRITE_ERROR: //数据写入错误return MSD_DATA_WRITE_ERROR;default: //未知错误r1=MSD_DATA_OTHER_ERROR;break;}}while(r1==MSD_DATA_OTHER_ERROR); //数据错误时一直等待retry=0;while(SPIx_ReadWriteByte(0XFF)==0) //读到数据为0,则数据还未写完成{retry++;//delay_us(10); //SD卡写等待需要较长的时间if(retry>=0XFFFFFFFE)return 0XFF; //等待失败了};return 0; //成功了}//-----------------------------------------------------------------//向SD卡发送一个命令//输入: u8 cmd 命令// u32 arg 命令参数// u8 crc crc校验值//返回值:SD卡返回的响应u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc){u8 r1;u8 Retry=0;sd_cs_1;SPIx_ReadWriteByte(0xff); //高速写命令延时SPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//片选端置低,选中SD卡sd_cs_0;//发送SPIx_ReadWriteByte(cmd | 0x40); //分别写入命令SPIx_ReadWriteByte(arg >> 24);SPIx_ReadWriteByte(arg >> 16);SPIx_ReadWriteByte(arg >> 8);SPIx_ReadWriteByte(arg);SPIx_ReadWriteByte(crc);//等待响应,或超时退出while((r1=SPIx_ReadWriteByte(0xFF))==0xFF){Retry++;if(Retry>200)break;}//关闭片选sd_cs_1;//在总线上额外增加8个时钟,让SD卡完成剩下的工作SPIx_ReadWriteByte(0xFF);//返回状态值return r1;}//-----------------------------------------------------------//向SD卡发送一个命令(结束是不失能片选,还有后续数据传来)//输入:u8 cmd 命令// u32 arg 命令参数// u8 crc crc校验值//返回值:SD卡返回的响应u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc){u8 Retry=0;u8 r1;SPIx_ReadWriteByte(0xff);//高速写命令延时SPIx_ReadWriteByte(0xff);sd_cs_0;//片选端置低,选中SD卡//发送SPIx_ReadWriteByte(cmd | 0x40); //分别写入命令SPIx_ReadWriteByte(arg >> 24);SPIx_ReadWriteByte(arg >> 16);SPIx_ReadWriteByte(arg >> 8);SPIx_ReadWriteByte(arg);SPIx_ReadWriteByte(crc);//等待响应,或超时退出while((r1=SPIx_ReadWriteByte(0xFF))==0xFF){Retry++;if(Retry>200)break;}//返回响应值return r1;}//------------------------------------------------------------//把SD卡设置到挂起模式//返回值:0,成功设置// 1,设置失败u8 SD_Idle_Sta(void){u16 i;u8 retry;for(i=0;i<0xf00;i++); //纯延时,等待SD卡上电完成//先产生>74个脉冲,让SD卡自己初始化完成for(i=0;i<10;i++)SPIx_ReadWriteByte(0xFF);//-----------------SD卡复位到idle开始-----------------//循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态//超时则直接退出retry = 0;do{//发送CMD0,让SD卡进入IDLE状态i = SD_SendCommand(CMD0, 0, 0x95);retry++;}while((i!=0x01)&&(retry<200));//跳出循环后,检查原因:初始化成功?or 重试超时?if(retry==200)return 1; //失败return 0; //成功}//---------------------------------------------------------------//初始化SD卡//如果成功返回,则会自动设置SPI速度为18Mhz//返回值:0:NO_ERR// 1:TIME_OUT// 99:NO_CARDu8 SD_Init(void){u8 r1; // 存放SD卡的返回值u16 retry; // 用来进行超时计数u8 buff[6];/*//设置硬件上与SD卡相关联的控制引脚输出//避免NRF24L01/W25X16等的影响RCC->APB2ENR|=1<<2; //PORTA时钟使能GPIOA->CRL&=0XFFF000FF;GPIOA->CRL|=0X00033300;//PA2.3.4 推挽GPIOA->ODR|=0X7<<2; //PA2.3.4上拉SPIx_Init();SPIx_SetSpeed(SPI_SPEED_256);//设置到低速模式*/spi_low_speed();sd_cs_1;if(SD_Idle_Sta()) return 1;//超时返回1 设置到idle 模式失败//-----------------SD卡复位到idle结束-----------------//获取卡片的SD版本信息sd_cs_0;r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);//如果卡片版本信息是v1.0版本的,即r1=0x05,则进行以下初始化if(r1 == 0x05){//设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC SD_Type = SD_TYPE_V1;//如果是V1.0卡,CMD8指令后没有后续数据//片选置高,结束本次命令sd_cs_1;//多发8个CLK,让SD结束后续操作SPIx_ReadWriteByte(0xFF);//-----------------SD卡、MMC卡初始化开始-----------------//发卡初始化指令CMD55+ACMD41// 如果有应答,说明是SD卡,且初始化完成// 没有回应,说明是MMC卡,额外进行相应初始化retry = 0;do{//先发CMD55,应返回0x01;否则出错r1 = SD_SendCommand(CMD55, 0, 0);if(r1 == 0XFF)return r1;//只要不是0xff,就接着发送//得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次r1 = SD_SendCommand(ACMD41, 0, 0);retry++;}while((r1!=0x00) && (retry<400));// 判断是超时还是得到正确回应// 若有回应:是SD卡;没有回应:是MMC卡//----------MMC卡额外初始化操作开始------------if(retry==400){retry = 0;//发送MMC卡初始化命令(没有测试)do{r1 = SD_SendCommand(1,0,0);retry++;}while((r1!=0x00)&& (retry<400));if(retry==400)return 1; //MMC卡初始化超时//写入卡类型SD_Type = SD_TYPE_MMC;}//----------MMC卡额外初始化操作结束------------//设置SPI为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();SPIx_ReadWriteByte(0xFF);//禁止CRC校验r1 = SD_SendCommand(CMD59, 0, 0x95);if(r1 != 0x00)return r1; //命令错误,返回r1//设置Sector Sizer1 = SD_SendCommand(CMD16, 512, 0x95);if(r1 != 0x00)return r1;//命令错误,返回r1//-----------------SD卡、MMC卡初始化结束-----------------}//SD卡为V1.0版本的初始化结束//下面是V2.0卡的初始化//其中需要读取OCR数据,判断是SD2.0还是SD2.0HC卡else if(r1 == 0x01){//V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令buff[0] = SPIx_ReadWriteByte(0xFF); //should be 0x00buff[1] = SPIx_ReadWriteByte(0xFF); //should be 0x00buff[2] = SPIx_ReadWriteByte(0xFF); //should be 0x01buff[3] = SPIx_ReadWriteByte(0xFF); //should be 0xAAsd_cs_1;SPIx_ReadWriteByte(0xFF);//the next 8 clocks//判断该卡是否支持2.7V-3.6V的电压范围//if(buff[2]==0x01 && buff[3]==0xAA) //不判断,让其支持的卡更多{retry = 0;//发卡初始化指令CMD55+ACMD41do{r1 = SD_SendCommand(CMD55, 0, 0);if(r1!=0x01)return r1;r1 = SD_SendCommand(ACMD41, 0x40000000, 0);if(retry>200)return r1; //超时则返回r1状态}while(r1!=0);//初始化指令发送完成,接下来获取OCR信息//-----------鉴别SD2.0卡版本开始-----------r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);if(r1!=0x00){sd_cs_1;//释放SD片选信号return r1; //如果命令没有返回正确应答,直接退出,返回应答}//读OCR指令发出后,紧接着是4字节的OCR信息buff[0] = SPIx_ReadWriteByte(0xFF);buff[1] = SPIx_ReadWriteByte(0xFF);buff[2] = SPIx_ReadWriteByte(0xFF);buff[3] = SPIx_ReadWriteByte(0xFF);//OCR接收完成,片选置高sd_cs_1;SPIx_ReadWriteByte(0xFF);//检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC //如果CCS=1:SDHC CCS=0:SD2.0if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC; //检查CCSelse SD_Type = SD_TYPE_V2;//-----------鉴别SD2.0卡版本结束-----------//设置SPI为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();}}return r1;}//---------------------------------------------------------------------//从SD卡中读回指定长度的数据,放置在给定位置//输入: u8 *data(存放读回数据的内存>len)// u16 len(数据长度)// u8 release(传输完成后是否释放总线CS置高0:不释放1:释放)//返回值:0:NO_ERR// other:错误信息u8 SD_ReceiveData(u8 *data, u16 len, u8 release){// 启动一次传输sd_cs_0;if(SD_GetResponse(0xFE)) //等待SD卡发回数据起始令牌0xFE {sd_cs_1;return 1;}while(len--)//开始接收数据{*data=SPIx_ReadWriteByte(0xFF);data++;}//下面是2个伪CRC(dummy CRC)SPIx_ReadWriteByte(0xFF);SPIx_ReadWriteByte(0xFF);if(release==RELEASE)//按需释放总线,将CS置高{sd_cs_1;//传输结束SPIx_ReadWriteByte(0xFF);}return 0;}//-----------------------------------------------------------------//获取SD卡的CID信息,包括制造商信息//输入: u8 *cid_data(存放CID的内存,至少16Byte)//返回值:0:NO_ERR// 1:TIME_OUT// other:错误信息u8 SD_GetCID(u8 *cid_data){u8 r1;//发CMD10命令,读CIDr1 = SD_SendCommand(CMD10,0,0xFF);if(r1 != 0x00)return r1; //没返回正确应答,则退出,报SD_ReceiveData(cid_data,16,RELEASE);//接收16个字节的return 0;}//-------------------------------------------------------------------//获取SD卡的CSD信息,包括容量和速度信息//输入:u8 *cid_data(存放CID的内存,至少16Byte)//返回值:0:NO_ERR// 1:TIME_OUT// other:错误信息u8 SD_GetCSD(u8 *csd_data){u8 r1;r1=SD_SendCommand(CMD9,0,0xFF);//发CMD9命令,读CSD if(r1)return r1; //没返回正确应答,则退出,报错SD_ReceiveData(csd_data, 16, RELEASE);//接收16个字节的数据return 0;}//------------------------------------------------------------------------ //获取SD卡的容量(字节)//返回值:0:取容量出错// 其他:SD卡的容量(字节)u32 SD_GetCapacity(void){u8 csd[16];u32 Capacity;u8 r1;u16 i;u16 temp;//取CSD信息,如果期间出错,返回0if(SD_GetCSD(csd)!=0) return 0;//如果为SDHC卡,按照下面方式计算if((csd[0]&0xC0)==0x40){Capacity=((u32)csd[8])<<8;Capacity+=(u32)csd[9]+1;Capacity = (Capacity)*1024;//得到扇区数Capacity*=512;//得到字节数}else{i = csd[6]&0x03;i<<=8;i += csd[7];i<<=2;i += ((csd[8]&0xc0)>>6);//C_SIZE_MULTr1 = csd[9]&0x03;r1<<=1;r1 += ((csd[10]&0x80)>>7);r1+=2;//BLOCKNRtemp = 1;while(r1){temp*=2;r1--;}Capacity = ((u32)(i+1))*((u32)temp);// READ_BL_LENi = csd[5]&0x0f;//BLOCK_LENtemp = 1;while(i){temp*=2;i--;}//The final resultCapacity *= (u32)temp;//字节为单位}return (u32)Capacity;}//--------------------------------------------------------------------//读SD卡的一个block//输入:u32 sector 取地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)//返回值:0:成功// other:失败u8 SD_ReadSingleBlock(u32 sector, u8 *buffer){u8 r1;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);//spi_high_speed();//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type!=SD_TYPE_V2HC){sector = sector<<9;}r1 = SD_SendCommand(CMD17, sector, 0);//读命令if(r1 != 0x00)return r1;r1 = SD_ReceiveData(buffer, 512, RELEASE);if(r1 != 0)return r1; //读数据出错!else return 0;}/*u8 SD_ReadSingleBlock(u32 sector, u8 *buffer){u8 r1;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type!=SD_TYPE_V2HC){sector = sector<<9;}r1 = SD_SendCommand(CMD17, sector, 0);//读命令if(r1 != 0x00)return r1;r1 = SD_ReceiveData(buffer, 512, RELEASE);if(r1 != 0)return r1; //读数据出错!else return 0;}*///----------------------------------------------------------------------//写入SD卡的一个block(未实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)//返回值:0:成功// other:失败u8 SD_WriteSingleBlock(u32 sector, const u8 *data){u8 r1;u16 i;u16 retry;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type!=SD_TYPE_V2HC){sector = sector<<9;}r1 = SD_SendCommand(CMD24, sector, 0x00);if(r1 != 0x00){return r1; //应答不正确,直接返回}//开始准备数据传输sd_cs_0;//先放3个空数据,等待SD卡准备好SPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//放起始令牌0xFESPIx_ReadWriteByte(0xFE);//放一个sector的数据for(i=0;i<512;i++){SPIx_ReadWriteByte(*data++);}//发2个Byte的dummy CRCSPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//等待SD卡应答r1 = SPIx_ReadWriteByte(0xff);if((r1&0x1F)!=0x05){sd_cs_1;return r1;}//等待操作完成retry = 0;while(!SPIx_ReadWriteByte(0xff)){retry++;if(retry>0xfffe) //如果长时间写入没有完成,报错退出{sd_cs_1;return 1; //写入超时返回1}}//写入完成,片选置1sd_cs_1;SPIx_ReadWriteByte(0xff);return 0;}//-------------------------------------------------------------------//读SD卡的多个block(实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)// u8 count 连续读count个block//返回值:0:成功// other:失败u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count) {u8 r1;//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式//如果不是SDHC,将sector地址转成byte地址if(SD_Type!=SD_TYPE_V2HC)sector = sector<<9;//SD_WaitDataReady();//发读多块命令r1 = SD_SendCommand(CMD18, sector, 0);//读命令if(r1 != 0x00)return r1;do//开始接收数据{if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)break;buffer += 512;} while(--count);//全部传输完毕,发送停止命令SD_SendCommand(CMD12, 0, 0);//释放总线sd_cs_1;SPIx_ReadWriteByte(0xFF);if(count != 0)return count; //如果没有传完,返回剩余个数else return 0;}//------------------------------------------------------------------------//写入SD卡的N个block(未实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)// u8 count 写入的block数目//返回值:0:成功// other:失败u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count){u8 r1;u16 i;//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式if(SD_Type != SD_TYPE_V2HC)sector = sector<<9;//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count, 0x00);//如果目标卡不是MMC卡,启用ACMD23指令使能预擦除r1 = SD_SendCommand(CMD25, sector, 0x00);//发多块写入指令if(r1 != 0x00)return r1; //应答不正确,直接返回sd_cs_0;//开始准备数据传输SPIx_ReadWriteByte(0xff);//先放3个空数据,等待SD卡准备好SPIx_ReadWriteByte(0xff);//--------下面是N个sector写入的循环部分do{//放起始令牌0xFC 表明是多块写入SPIx_ReadWriteByte(0xFC);//放一个sector的数据for(i=0;i<512;i++){SPIx_ReadWriteByte(*data++);}//发2个Byte的dummy CRCSPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//等待SD卡应答r1 = SPIx_ReadWriteByte(0xff);if((r1&0x1F)!=0x05){sd_cs_1; //如果应答为报错,则带错误代码直接退出return r1;}//等待SD卡写入完成if(SD_WaitDataReady()==1){sd_cs_1; //等待SD卡写入完成超时,直接退出报错return 1;}}while(--count);//本sector数据传输完成//发结束传输令牌0xFDr1 = SPIx_ReadWriteByte(0xFD);if(r1==0x00){count = 0xfe;}if(SD_WaitDataReady()) //等待准备好{sd_cs_1;return 1;}//写入完成,片选置1sd_cs_1;SPIx_ReadWriteByte(0xff);return count; //返回count值,如果写完则count=0,否则count=1 }//-----------------------------------------------------------------------------//在指定扇区,从offset开始读出bytes个字节//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buf 数据存储地址(大小<=512byte)// u16 offset 在扇区里面的偏移量// u16 bytes 要读出的字节数//返回值:0:成功// other:失败u8 SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes){u8 r1;u16 i=0;r1=SD_SendCommand(CMD17,address<<9,0);//发送读扇区命令if(r1)return r1; //应答不正确,直接返回sd_cs_0;//选中SD卡if(SD_GetResponse(0xFE))//等待SD卡发回数据起始令牌0xFE{sd_cs_1; //关闭SD卡return 1;//读取失败}for(i=0;i<offset;i++)SPIx_ReadWriteByte(0xff);//跳过offset位for(;i<offset+bytes;i++)*buf++=SPIx_ReadWriteByte(0xff);//读取有用数据for(;i<512;i++) SPIx_ReadWriteByte(0xff); //读出剩余字节SPIx_ReadWriteByte(0xff);//发送伪CRC码SPIx_ReadWriteByte(0xff);sd_cs_1;//关闭SD卡return 0;}。

sd初始化流程

sd初始化流程

sd初始化流程SD card initialization process is a crucial step in setting up a device that relies on external memory for data storage. It involves preparing the SD card for use by configuring it to work with the specific device it will be used in. This process ensures compatibility and optimal performance between the SD card and the device it is being used with. Without proper initialization, the SD card may not work correctly or may not be recognized by the device at all. Therefore, it is important to follow the required steps to initialize an SD card properly.SD卡初始化过程是设置依赖外部存储器进行数据存储的设备的关键步骤。

它涉及准备SD卡以便通过配置使其与将要使用的特定设备配合使用。

这个过程确保了SD卡和设备之间的兼容性和最佳性能。

如果没有正确初始化,SD卡可能无法正常工作,或者甚至可能被设备识别。

因此,必须按照要求的步骤正确初始化SD卡。

The first step in the SD card initialization process is to insert the SD card into the device's SD card slot. This simple action is crucial to physically connect the SD card to the device and prepare it for theinitialization process. It is important to insert the SD card correctly to avoid damaging the device or the card itself. Once the SD card is securely inserted, the device will detect the presence of the card and initiate the initialization process.SD卡初始化过程的第一步是将SD卡插入设备的SD卡插槽中。

stm32SPI模式读写SD卡

stm32SPI模式读写SD卡

stm32SPI模式读写SD卡SPI模式读写SD卡SD卡初始化过程:1. 初始化STM32的SPI接口使用低速模式2. 延时至少74clock3. 发送CMD0,需要返回0x01,进入Idle状态4. 循环发送CMD55+ACMD41,直到返回0x00,进入Ready状态5. 设置读写block大小为512byte5. 把STM32的SPI设置为高速模式读一个block块的过程1. 发送CMD17(单块)或CMD18(多块)读命令,返回0x002. 接收数据开始令牌0xfe + 正式数据512Bytes + CRC 校验2Bytes写一个block块的过程1. 发送CMD24(单块)或CMD25(多块)写命令,返回0x002. 发送数据开始令牌0xfe + 正式数据512Bytes + CRC校验2Bytes/******************************************************************* ************* Function Name : SD_MMC_SPI_Init* Description : SD_MMC_SPI_Init* Input : None* Output : None* Return : zero init success, non-zero init error************************************************************************ *******/u8 SD_MMC_SPI_Init(void){GPIO_InitTypeDef GPIO_InitStructure;/* Enable SPI1 and GPIO clocks */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_SD_MMC_SPI_CS, ENABLE);/* Configure SPI1 pins: SCK, MISO and MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Configure SD_MMC_SPI_CS */GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_CS_Pin_CS;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);///////////////////////////////////////////////////////////////////////////////* initialize SPI with lowest frequency */SD_MMC_Low_Speed();/* card needs 74 cycles minimum to start up */for(u8 i = 0; i < 10; ++i) {/* wait 8 clock cycles */ SD_MMC_ReadWrite_Byte(0x00); } /* address card */ SD_MMC_SPI_SELECT();/* reset card */u8 response;for(u16 i = 0; ; ++i){response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE ,0 );if( response == 0x01 ) break;if(i == 0x1ff) {SD_MMC_SPI_DESELECT(); return 1;}}/* wait for card to get ready */ for(u16 i = 0; ; ++i) {response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);if(!(response & (1 << R1_IDLE_STATE)))break;if(i == 0x7fff) {SD_MMC_SPI_DESELECT(); return 1;}}/* set block size to 512 bytes */if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512)) {SD_MMC_SPI_DESELECT();return 1;}/* deaddress card */SD_MMC_SPI_DESELECT();/* switch to highest SPI frequency possible */ SD_MMC_High_Speed();return 0;//////////////////////////////////////////////////////////////////// //////////}/******************************************************************* ************* Function Name : SD_MMC_Read_Single_Block * Description :SD_MMC_Read_Single_Block * Input : sector number and buffer data point * Output : None* Return : zero success, non-zero error************************************************************************ *******/u8 SD_MMC_Read_Single_Block(u32 sector, u8* buffer) {u8 Response;u16 i;u16 Retry = 0;//读命令 send read commandResponse =SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, sector<<9); if(Response != 0x00)return Response;SD_MMC_SPI_SELECT();// start byte 0xfewhile(SD_MMC_ReadWrite_Byte(0xff) != 0xfe) {if(++Retry > 0xfffe){SD_MMC_SPI_DESELECT();return 1; //timeout}}for(i = 0; i < 512; ++i) {//读512个数据*buffer++ = SD_MMC_ReadWrite_Byte(0xff); }SD_MMC_ReadWrite_Byte(0xff); //伪crcSD_MMC_ReadWrite_Byte(0xff); //伪crcSD_MMC_SPI_DESELECT();SD_MMC_ReadWrite_Byte(0xff); // extra 8 CLKreturn 0;}/******************************************************************* ************* Function Name : SD_MMC_Write_Single_Block* Description : SD_MMC_Write_Single_Block * Input : sector number and buffer data point* Output : None* Return : zero success, non-zero error.************************************************************************ *******/u8 SD_MMC_Write_Single_Block(u32 sector, u8* buffer) {u8 Response;u16 i;u16 retry=0;//写命令 send write commandResponse =SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, sector<<9);if(Response != 0x00)return Response;SD_MMC_SPI_SELECT();SD_MMC_ReadWrite_Byte(0xff);SD_MMC_ReadWrite_Byte(0xff);SD_MMC_ReadWrite_Byte(0xff);//发开始符 start byte 0xfeSD_MMC_ReadWrite_Byte(0xfe);//送512字节数据 send 512 bytes datafor(i=0; i<512; i++){SD_MMC_ReadWrite_Byte(*buffer++);}SD_MMC_ReadWrite_Byte(0xff); //dummy crc SD_MMC_ReadWrite_Byte(0xff); //dummy crcResponse = SD_MMC_ReadWrite_Byte(0xff);//等待是否成功 judge if it successfulif( (Response&0x1f) != 0x05){SD_MMC_SPI_DESELECT();return Response;}//等待操作完 wait no busywhile(SD_MMC_ReadWrite_Byte(0xff) != 0x00) {if(retry++ > 0xfffe){SD_MMC_SPI_DESELECT();return 1;}}SD_MMC_SPI_DESELECT();SD_MMC_ReadWrite_Byte(0xff);// extra 8 CLKreturn 0;}if( SD_MMC_SPI_Init() ==1)printf(" _SD_MMC Initialization ERROR\r\n"); else{printf(" _SD_MMC Initialization OK\r\n"); //memset(buffer,0,512); //读取一个扇区的内容这里读的是0扇区SD_MMC_Read_Single_Block( 0 , buffer );Uart1_PutString( buffer , 512 );}。

sd卡数据读写流程

sd卡数据读写流程

sd卡数据读写流程SD卡是一种常见的存储媒介,它具有轻便、易携带、容量大、存储速度快等优势。

SD卡数据读写流程是指将数据从SD卡中读取出来或将数据写入SD卡中的整个过程。

一、SD卡的物理结构SD卡主要由控制器、记忆芯片和接口组成。

控制器负责管理SD卡的读写操作;记忆芯片是存储数据的核心部件,它采用闪存技术,可存储数据并保持数据不易丢失;接口是SD卡与主控制器进行通信的桥梁,一般采用SPI(串行外设接口)或SDIO(SD输入输出)接口。

二、SD卡读写流程1.初始化SD卡当主控制器接通SD卡电源时,首先要进行初始化操作。

初始化操作主要包括向SD卡发送复位命令、读取SD卡的OCR(操作条件寄存器)以及设置SPI或SDIO接口的工作参数等操作。

2.读取SD卡信息在SD卡初始化成功后,主控制器通过SPI或SDIO接口向SD 卡发送命令,读取SD卡ID信息、SD卡容量、SD卡速度等重要参数。

这些信息将在数据读写时起到重要作用。

3.读取文件SD卡上的文件存储在文件系统中,主控制器需要先读取文件系统,找到要读取的文件所在的位置。

一般情况下,文件系统采用FAT32格式,主控制器需要读取文件系统启动区扇区信息,从而找到文件所在扇区及其起始地址。

4.读取数据在找到文件所在位置后,主控制器就可以根据文件系统的信息,向SD卡发送读操作指令,读取文件数据。

读取数据时,主控制器需要根据SD卡的速度、数据传输模式等参数设置接口波特率、时序等参数。

5.写入数据SD卡写数据流程与读数据基本相同,只是主控制器需要向SD卡发送写操作指令,将数据写入SD卡中。

写入数据时,主控制器需要根据SD卡的容量、速度等参数设置写入数据的起始位置、写入数据的长度、写入数据的校验和等参数。

6.关闭SD卡当读写操作完成后,主控制器需要向SD卡发送停止指令,将SD卡彻底关闭。

关闭SD卡可以避免SD卡数据丢失、损坏等问题。

三、SD卡的数据保护SD卡存储的数据非常重要,因此在SD卡的读写过程中,需要采取一定的措施保护数据。

SDMMC卡初始化及读写流程讲述

SDMMC卡初始化及读写流程讲述

二、MMC/SD卡的模型和工作原理PIN脚、SD卡总线、SD卡结构、SD卡寄存器、上电过程SD卡寄存器:OCR:操作电压寄存器: 只读,32位第31位:表示卡上电的状态位CID: 卡身份识别寄存器只读128位生产厂商、产品ID,生产日期和串号等CSD:部分可写128位卡的容量、擦出扇区大小、读写最大数据块的大小、读操作的电流、电压等等 CSR: 卡配置寄存器64位数据位宽RCA:16位相关的卡地址寄存器,卡识别过程中主控器和卡协商出来的一个地址三、SD卡命令和响应格式命令和相应格式SD卡命令,命令类型,ACMD命令响应类型、卡类型、卡状态转换表命令的格式:48位起始位0 方向位(host to card: 1, card to host: 0)内容CRC7 结束位1·响应的格式:48位或者136位卡命令:命令的类型:bc: broadcast without Response 无响应的广播bcr: broadcast with Response 有响应的广播ac: Address(point-to-point) Command: 点对点,DATA0~DATA3数据线上无数据adtc: Adress(point-to-point) Data Transfer Commands 点对点,DATA0~DATA3数据线上有数据CMD0, CMD2, CMD3, CMD55, ACMD41 命令可能会导致卡的状态发生变化响应类型:R1,R1b, R2, R3,R6(SD2.0扩展了R7)扩展内容:SPI工作模式:要知道的特点:只支持一个卡,没有RCA,命令只是MMC/SD的基本的子集SDHC:(支持2GB~32GB):理解CMD8的作用,命令格式和响应,了解CSDV2.0寄存器做了扩展SDIO WIFI:增加CMD52,CMD53CMD8可以通过重新定义先前保留的位,来扩展一些已经存在的命令的新功能。

SD卡初始化流程

SD卡初始化流程

SD卡初始化流程SD卡SDIO接⼝读写流程(SD2.0协议)⼀、简述SD卡(Secure Digital Memory Card)是⼀种基于半导体快闪记忆器的新⼀代记忆设备,SD卡具有⼤容量、⾼性能、读写速度快、安全等多种特点,它被⼴泛地于便携式装置上使⽤。

SD存储卡的技术是从MMC卡格式上发展⽽来,在兼容SD存储卡基础上发展了SDIO( SD Input/ Output)卡,此兼容性包括机械,电⼦,电⼒,信号和软件,通常将SD、SDIO卡俗称SD存储卡。

SD卡作为⼀种新型的存储设备,具有以下特点:●⾼存储容量,最常⽤的容量:8GB、16GB、32GB、128GB、256GB等。

●内置加密技术,适应基于SDMI协议的著作版权保护功能。

●⾼速数据传送;最⼤读写速率为100MB/s。

●体积轻⼩,便于携带,具有很强的抗冲击能⼒。

随着技术的发展,SD卡演变出了体积⼤⼤缩⼩的Mini SD卡和Micro SD卡,其中MicroSD卡是⽬前应⽤最为⼴泛的SD卡,特别是在⼿机、MP3\MP4、相机中。

本⽂是对对SDIO接⼝的SD卡的初始化及数据读写中设置到的问题进⾏讲解。

主要包括SD 卡通讯接⼝、命令及应答格式、初始化配置流程、数据读写流程等⽅⾯内容的讲解,具体包括以下内容:SD卡通讯接⼝:SDIO接⼝和SPI接⼝SD卡命令格式:命令及应答类型、格式、字段含义SD卡初始化流程:命令发送流程、命令含义SD卡数据读写:数据传输格式、命令含义⼆、SD卡通讯接⼝Micro SD卡具有8个引脚结构如图1所⽰。

图1 Micro SD卡接⼝Micro SD卡⽀持SPI和SDIO两种⼯作模式,两种模式下引脚的功能是不同的,SDIO 和SPI模式下的引脚功能如表1所⽰。

表1 SD卡接⼝引脚功能在SDIO模式下,采⽤4根数据线,并且命令及其应答接收使⽤单独的CMD线;在SPI 模式下,数据线输⼊和数据输出都只有⼀根数据线;因此,相对具有DTA0-DTA4 四根数据线的SDIO模式,SPI模式在牺牲了⼀定通讯速度,但是提⾼了兼容性,使⼀些不具有SDIO 接⼝的微处理能够通过SPI进⾏SD卡数据的读写。

SD卡初始化及读取程序

SD卡初始化及读取程序

uint8 SPI_SendByte(uint8 val) {
SPI0DAT = val; while(TXBSY); return SPI0DAT; }
// uint8= uchar
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ // 函数名:MMC_SD_SendCmd // 功 能:发送卡命令
if(r1 == 0x00) type = 0x10; // 激活成功就是 SD 卡
}
else { }
// 如果发送 Cmd55 无反应,改发送 Cmd1 r1 = MMC_SD_SendCmd(1,0); if(r1 == 0x00) type = 0x20; // 激活成功就是 MMC 卡
retry++;
} while(r1 != 0x01);
// MMC、SD 卡成功转到 SPI 模式
retry = 0;
//****** SD 卡在进入 SPI 模式后,激活命令和 MMC 卡一样为 Cmd1,同时 Cmd55+Cmd41 仍 然有效******//
/* do
{
r1 = MMC_SD_SendCmd(1, 0); //发 Cmd1(active 激活)命令
//分别写入命令 //仅本次有效的 CRC 值
while((r1 = SPI_SendByte(0xFF)) == 0xFF) //等待响应 if(retry++ > 8) break; //超时退出
return r1; }
//返回状态值
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ // 函数名:MMC_SD_ReadSingleBlock // 功 能:读一个扇区 // 参 数:扇区,数据缓冲区 // 返回值: //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

SD卡读写操作详细说明

SD卡读写操作详细说明

SD卡读写操作详细说明SD卡(Secure Digital Card)是一种常见的存储设备,广泛应用于各种数码设备,如相机、手机、音乐播放器等。

SD卡读写操作是指对SD卡进行数据的读取和写入操作。

本文将详细介绍SD卡的读写操作流程和相关细节。

一、SD卡读写操作的基本原理SD卡采用了Flash存储技术,数据的读写是通过对存储芯片中的电荷进行控制实现的。

每个存储单元可以存储一个位(0或1),多个存储单元可以组成字节、块等不同大小的数据单元。

二、SD卡的初始化在进行SD卡的读写操作之前,首先需要对SD卡进行初始化。

SD卡的初始化包括以下几个步骤:1.插入SD卡:将SD卡插入到SD卡插槽中。

2.电源供给:给SD卡供电,使其可以正常工作。

3.寻卡:通过命令与SD卡进行通信,找到SD卡并识别其属性和参数。

三、SD卡的读操作SD卡的读操作是指从SD卡中读取数据。

SD卡的读操作流程如下:1.发送读命令:通过控制器向SD卡发送读命令,告知SD卡要读取的数据的起始地址和长度。

2.接收应答:SD卡接收到读命令后,会返回一个应答信号,确认是否接收到了读命令。

3.读取数据:当SD卡接收到读命令后,在指定的地址范围内读取数据,并将数据传输给控制器。

4.数据传输:控制器接收到SD卡传输的数据后,将数据转发给主机或其他设备进行处理。

四、SD卡的写操作SD卡的写操作是指向SD卡中写入数据。

SD卡的写操作流程如下:1.发送写命令:通过控制器向SD卡发送写命令,告知SD卡要写入的数据的起始地址和长度。

2.接收应答:SD卡接收到写命令后,会返回一个应答信号,确认是否接收到了写命令。

3.写入数据:当SD卡接收到写命令后,在指定的地址范围内写入数据。

4.数据传输:控制器向SD卡传输要写入的数据,SD卡接收到数据后进行存储。

五、SD卡的块操作SD卡的读写操作是以块为单位进行的,一个块的大小一般为512字节。

SD卡的块操作流程如下:1.发送块命令:通过控制器向SD卡发送块命令,告知SD卡要进行块操作的起始块号和块数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SD卡初始化及读写流程
默认分类2010-03-03 21:03:00 阅读264 评论0 字号:大中小
SD卡调试关键点:
1. 上电时要延时足够长的时间给SD卡一个准备过程,在我的程
序里是5秒,根据不同的卡设置不同的延时时间。

SD卡初始化第一步在发送CMD命令之前,在片选有效的情况下首先要发送至少74个时钟,否则将有可能出现SD卡不能初始化的问题。

2. SD卡发送复位命令CMD0后,要发送版本查询命令CMD8,
返回状态一般分两种,若返回0x01表示此SD卡接受CMD8,也就是说此SD卡支持版本2;若返回0x05则表示此SD卡支持版本1。

因为不同版本的SD卡操作要求有不一样的地方,所以务必查询SD卡的版本号,否则也会出现SD卡无法正常工作的问题。

3. 理论上要求发送CMD58获得SD卡电压参数,但实际过程中
由于事先都知道了SD卡的工作电压,因此可省略这一步简化程序。

协议书上也建议尽量不要用这个命令。

4. SD卡读写超时时间要按照协议说明书书上的给定值(读超时:
100ms;写超时:250ms),这个值要在程序中准确计算出来,否
则将会出现不能正常读写数据的问题。

我自己定义了一个计算公
式:超时时间=(8/clk)*arg。

5. 2GB以内的SD卡(标准卡)和2GB以上的SD卡(大容量卡)在
地址访问形式上不同,这一点尤其要注意,否则将会出现无法读写数据的问题。

如标准卡在读写操作时,对读或写命令令牌当中的地址域符初值0x10,表示对第16个字节以后的地址单元进行操作(前提是此SD卡支持偏移读写操作),而对大容量卡读或写命令令牌当中的地址域符初值0x10时,则表示对第16块进行读写操作,而且大容量卡只支持块读写操作,块大小固定为512字节,
对其进行字节操作将会出错。

6. 对某一块要进行写操作时最好先执行擦出命令,这样写入的速
度就能大大提高。

进行擦除操作时不管是标准卡还是大容量卡都按块操作执行,也就是一次擦除至少512字节。

7. 对标准卡进行字节操作时,起始和终止必须在一个物理扇区
内,否则将不能进行读写操作。

实际操作过程中建议用块操作以提高效率。

不管是标准卡还是大容量卡一个读写命令只能对一个块进行操作,不允许跨物理层地址操作。

8. 在写数据块前要先写入若干个dummy data字节,写完一个块
数据时,主机要监测MISO数据线,如果从机处于忙状态这根数据线会保持低电平,这样主机就可以根据这根数据线的状态以决定是否发送下一个命令,在从机没有释放MISO数据线之前,主机绝对不能执行其他命令,否则将会导致写入的数据出错,而且
从机也不会响应主机的命令。

9. 在SPI模式下,CRC校验是被忽略的,但依然要求主从机发
送CRC码,只是数值可以是任意值,一般主机的CRC码通常设
为0x00或0xFF。

读多块操作和写多块操作的传输停止形式不一样,读多块操作时用用命令CMD12终止传输,而写多块操作时用Stop Tran Token(停止传
输令牌,值为0xFD)终止传输。

----------------------------------------------------------------------------------------
1、
初始化步骤:
(1)
延时至少74clock,等待SD卡内部操作完成,在MMC协议中有明
确说明。

(2)CS低电平选中SD卡。

(3)发送CMD0,需要返回0x01,进入Idle状态
(4)为了区别SD卡是2.0还是1.0,或是MMC卡,这里根据协议向上兼容的原理,首先发送只有SD2.0才有的命令CMD8,如果CMD8返回无错误,则初步判断为2.0卡,进一步发送命令循环发送CMD55+ACMD41,直到返回0x00,确定SD2.0卡初始化成功,进入Ready状态,再发送CMD58命令来判断是HCSD还是SCSD,到此SD2.0卡初始化成功。

如果CMD8返回错误则进一步判断为1.0卡还是MMC 卡,循环发送CMD55+ACMD41,返回无错误,则为SD1.0卡,到此SD1.0卡初始成功,如果在一定的循环次数下,返回为错误,则进一步发送CMD1进行初始化,如果返回无错误,则确定为MMC卡,如果在一定的次数下,返回为错误,则不能识别该卡,初始结束。

(5)CS拉高。

2、
读步骤:
(1)
发送CMD17(单块)或CMD18(多块)读命令,返回0x00
(2)
接收数据开始令牌0xfe(或0xfc)+正式数据512Bytes + CRC
校验2Bytes
默认正式传输的数据长度是512Bytes,可用CMD16设置块长度。

3、
写步骤:
(1)
发送CMD24(单块)或CMD25(多块)写命令,返回0x00
(2)
发送数据开始令牌0xfe(或0xfc)+正式数据512Bytes + CRC
校验2Bytes
4、
擦除步骤:
(1)
发送CMD32,跟一个参数来指定首个要擦除的起始地址(SD手册上
说是块号)
(2)
发送CMD33,,指定最后的地址
(3)
发送CMD38,擦除指定区间的内容
此3步顺序不能颠倒。

最后说一下我的一点体会:SD卡就是一个存储器,只不过用命令的方式来进行操作,我们只要掌握了各条命令及操作方式,就可以灵活的操作SD卡了,另外我所了解的IC卡也是类似的原理,还有就是建议开始看MMC的协议,简单明了易懂些,有了对MMC卡的一些了解后
看SD卡协议就容易多了。

SD卡命令共分为12类,分别为class0到class11,不同的SDd卡,主控根据其功能,支持不同的命令集如下
Class0 :(卡的识别、初始化等基本命令集)
CMD0:复位SD 卡.
CMD1:读OCR寄存器.
CMD9:读CSD寄存器.
CMD10:读CID寄存器.
CMD12:停止读多块时的数据传输
CMD13:读Card_Status 寄存器
Class2 (读卡命令集):
CMD16:设置块的长度
CMD17:读单块.
CMD18:读多块,直至主机发送CMD12为止 .
Class4(写卡命令集) :
CMD24:写单块.
CMD25:写多块.
CMD27:写CSD寄存器 .
Class5 (擦除卡命令集):
CMD32:设置擦除块的起始地址.
CMD33:设置擦除块的终止地址.
CMD38: 擦除所选择的块.
Class6(写保护命令集):
CMD28:设置写保护块的地址.
CMD29:擦除写保护块的地址.
CMD30: Ask the card for the status of the write protection bits class7:卡的锁定,解锁功能命令集
class8:申请特定命令集。

class10 -11 :保留
其中class1,class3,class9:SPI模式不支持。

相关文档
最新文档