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卡存储设备的模块。
它通常通过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卡读写模块的使用方式可以根据具体需求进行拓展,以实现更多功能和提升性能。
基于stm32f103对sd卡底层的基本操作方法
基于stm32f103对sd卡底层的基本操作方法基于STM32F103的SD卡底层操作方法是指通过STM32F103系列微控制器来对SD卡进行读写操作的一组基本方法。
本文将详细介绍如何配置STM32F103的SPI接口和相关寄存器,以及如何使用SPI接口与SD卡进行通信和文件操作。
一、硬件连接首先,需要连接STM32F103与SD卡之间的硬件接口。
STM32F103的SPI接口包括四根引脚,分别是NSS(片选信号)、SCK(时钟信号)、MISO(数据输入信号)和MOSI(数据输出信号)。
通常,可以将SD卡的NSS引脚连接到STM32F103的任一GPIO引脚上作为片选信号,并通过软件控制片选信号的高低电平来选择SD卡进行读写操作。
此外,还需要将SD卡的SCK、MISO和MOSI引脚分别连接到STM32F103的SPI接口的SCK、MISO和MOSI引脚上。
为了方便起见,可以直接使用STM32F1的SPI中的SPI1进行配置。
二、SPI接口配置在STM32F103中,SPI接口由SPI1、SPI2和SPI3三个外设实现,其中SPI1位于APB2总线上,SPI2和SPI3位于APB1总线上。
在本文中,我们将使用SPI1进行SD卡的底层操作。
首先,需要在CubeMX中将SPI1的NSS、SCK、MISO和MOSI引脚分别配置为GPIO输出、SPI时钟、SPI数据输入和SPI数据输出功能。
然后,需要配置SPI1的时钟分频系数、数据位数、传输模式等参数。
SPI1的时钟分频系数由BDIV和BR两个参数决定,其中BDIV位于SPI1->CR1寄存器的位6-7位,用于设定SPI1主频的1/2、1/4、1/8还是1/16,BR位于SPI1->CR1寄存器的位3-5位,用于设定SPI1的分频系数。
根据SD卡的时钟特性,一般选择SPI1的分频系数为sclk/32,其中sclk为主控芯片时钟。
在SPI接口配置完成之后,需要打开SPI1外设时钟使能,并设置SPI1的工作模式、数据位数等参数。
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 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)进行传输。
SD卡实现TXT文本读写
SD卡实现TXT文本读写SD卡是一种常见的存储设备,可以通过它来实现TXT文本的读写操作。
下面是一个实现的示例代码:```#include <SD.h>//定义SD卡引脚const int chipSelect = 4;void setu//初始化串口通信Serial.begin(9600);//初始化SD卡if (!SD.begin(chipSelect))Serial.println("SD卡初始化失败!");return;}Serial.println("SD卡初始化成功!");// 在SD卡根目录创建一个名为test.txt的文件,并将一段示例文本写入文件中File dataFile = SD.open("test.txt", FILE_WRITE);if (dataFile)dataFile.println("这是一个示例文本"); dataFile.println("Hello, World!"); dataFile.close(;Serial.println("文本写入成功!");} elseSerial.println("打开文件失败!");}//读取文件内容并打印在串口终端上dataFile = SD.open("test.txt");if (dataFile)while (dataFile.available()Serial.write(dataFile.read();}dataFile.close(;} elseSerial.println("打开文件失败!");}void loo//程序循环执行,如果有其他的任务可以在这里添加代码```以上代码首先使用`SD.begin(`函数初始化SD卡,并通过`SD.open(`函数创建一个名为"test.txt"的文件,并以写入方式打开。
sd卡识别流程
sd卡识别流程SD卡是一种常见的存储设备,广泛应用于移动设备、数码相机等电子产品中。
本文将从SD卡的识别流程入手,介绍SD卡的工作原理和识别过程。
一、SD卡的工作原理SD卡是一种闪存存储卡,采用了非易失性存储技术,可以长期保存数据。
它由存储芯片、控制器和外壳等组成。
存储芯片负责数据的存储,控制器负责控制数据的读写和传输。
SD卡通过与设备的接口连接,实现数据的读取和写入。
二、SD卡的识别流程1. 插卡检测:当将SD卡插入设备的SD卡槽时,设备会通过插卡检测电路检测SD卡的插入状态。
如果检测到插卡动作,设备会进入下一步的识别流程。
2. 供电和时钟:设备会为SD卡提供电源,并发送时钟信号给SD 卡,以确保SD卡的正常运行。
同时,设备还会发送复位信号给SD 卡,使其回到初始状态。
3. 发送命令:设备会通过SD卡接口向SD卡发送命令,以控制SD 卡的工作。
常见的命令有初始化命令、读取命令、写入命令等。
4. 响应命令:SD卡接收到设备发送的命令后,会进行相应的处理并返回响应结果。
响应结果包括命令执行状态、数据传输状态等。
5. 初始化:设备会向SD卡发送初始化命令,以对SD卡进行初始化设置。
初始化过程中,设备会向SD卡发送一系列的命令和参数,以便建立设备与SD卡之间的通信和数据传输。
6. 容量识别:设备会向SD卡发送容量识别命令,以获取SD卡的容量信息。
SD卡会返回容量信息给设备,设备根据这些信息来判断SD卡的容量大小和可用空间。
7. 文件系统识别:设备会读取SD卡的文件系统信息,以确定SD 卡的文件系统类型和目录结构。
常见的文件系统类型有FAT32、exFAT等。
8. 数据读写:设备通过命令和参数,向SD卡发送读写命令,以读取或写入数据。
SD卡接收到命令后,会执行相应的操作,并返回读取或写入的数据给设备。
9. 结束操作:设备在完成数据读写或其他操作后,会发送结束命令给SD卡,以结束与SD卡的通信和数据传输。
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可以通过重新定义先前保留的位,来扩展一些已经存在的命令的新功能。
FAT文件系统的SD卡单片机读写方法详解
FAT文件系统的SD卡单片机读写方法详解FAT(File Allocation Table)文件系统是一种常用的文件系统,被广泛应用于存储设备如SD卡上。
在单片机中使用SD卡进行读写操作时,需要使用FAT文件系统进行文件的管理和操作。
下面将详细介绍FAT文件系统的SD卡单片机读写方法。
1.SD卡初始化:在进行SD卡读写操作之前,首先需要初始化SD卡。
初始化SD卡的步骤如下:1.1硬件上电及等待稳定。
将SD卡模块供电,并等待SD卡电压稳定,通常需要几十毫秒的时间。
1.2发送复位命令。
向SD卡发送复位命令,命令的格式如下:CMD0:0x400x000x000x000x000x95发送这个命令后,SD卡会返回R1响应,其中bit 0为0表示复位成功。
1.3发送检测版本命令。
向SD卡发送检测版本命令,命令的格式如下:CMD8:0x480x000x000x010xAA0x87发送这个命令后,SD卡会返回R7响应,其中bit 0为0表示命令执行成功。
1.4判断SD卡类型。
根据R7响应中的数据,判断SD卡的类型,如果是SDHC卡或SDXC卡,需要进行额外的操作。
1.5发送初始化命令。
向SD卡发送初始化命令,命令的格式如下:CMD55:0x770x000x000x000x000xFFACMD41:0x690x400x000x000x000xFF循环发送这两个命令,直到SD卡返回R1响应的bit 0为0,表示初始化完成。
1.6发送读取OCR命令。
向SD卡发送读取OCR命令,命令的格式如下:CMD58:0x7A0x000x000x000x000xFF发送这个命令后,SD卡会返回R3响应,其中包含卡的OCR寄存器的内容。
2.FAT文件系统格式化:在SD卡上创建FAT文件系统之前,需要对SD卡进行格式化操作。
格式化操作会将SD卡分为引导扇区、FAT表、根目录区和数据区。
2.1创建引导扇区。
在SD卡的第一个扇区创建引导扇区,引导扇区包含引导记录和磁盘参数表。
sd卡读写模块的用法
SD卡读写模块是一种使单片机能够读写SD卡/TF卡的模块,它可以帮助单片机实现大容量存储方案。
该模块内置文件系统,可直接进行文件读写操作,适用于单片机系统。
使用SD卡读写模块时,需要了解其用法和操作。
1. 连接SD卡:将SD卡插入SD卡读写模块的卡槽中,确保卡槽与SD卡之间的接触良好。
2. 连接单片机:将SD卡读写模块与单片机相连接。
通常,SD卡读写模块会提供标准的SPI接口或MMC接口与单片机相连。
根据单片机的接口类型和SD卡读写模块的接口类型,选择合适的连接方式。
3. 初始化模块:在程序中调用SD卡读写模块的初始化函数,对模块进行初始化。
初始化过程中,模块会自动检测SD卡的类型和容量,并配置相应的操作模式。
4. 文件操作:通过调用SD卡读写模块的文件操作函数,实现文件的创建、删除、读取、写入等操作。
例如,可以使用open()函数打开一个文件,使用read()函数读取文件内容,使用write()函数写入文件内容,使用close()函数关闭文件。
5. 目录操作:通过调用SD卡读写模块的目录操作函数,实现目录的创建、删除、遍历等操作。
例如,可以使用mkdir()函数创建一个目录,使用rmdir()函数删除一个目录,使用opendir()函数打开一个目录,使用readdir()函数读取目录下的一个文件,使用closedir()函数关闭目录。
6. 卡操作:通过调用SD卡读写模块的卡操作函数,实现SD卡的格式化、挂载、卸载等操作。
例如,可以使用format()函数格式化SD卡,使用mount()函数挂载SD卡,使用umount()函数卸载SD卡。
需要注意的是,不同的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卡读写操作详细说明
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卡的信息,以下程序可以获取这些信息。
android手机SD卡读写操作(以txt文本为例)实现步骤
android⼿机SD卡读写操作(以txt⽂本为例)实现步骤要说明⼀下,我这⾥没有⽤MainActivity.class作为软件⼊⼝复制代码代码如下:AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="/apk/res/android"package="com.tes.textsd"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="16" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.tes.textsd.FileOperateActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="UNCHER" /></intent-filter></activity></application></manifest>复制代码代码如下:FileHelper.java/*** @Title: FileHelper.java* @Package com.tes.textsd* @Description: TODO(⽤⼀句话描述该⽂件做什么)* @author Alex.Z* @date 2013-2-26 下午5:45:40* @version V1.0*/package com.tes.textsd;import java.io.DataOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import android.content.Context;import android.os.Environment;public class FileHelper {private Context context;/** SD卡是否存在**/private boolean hasSD = false;/** SD卡的路径**/private String SDPATH;/** 当前程序包的路径**/private String FILESPATH;public FileHelper(Context context) {this.context = context;hasSD = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED);SDPATH = Environment.getExternalStorageDirectory().getPath(); FILESPATH = this.context.getFilesDir().getPath();}/*** 在SD卡上创建⽂件** @throws IOException*/public File createSDFile(String fileName) throws IOException { File file = new File(SDPATH + "//" + fileName);if (!file.exists()) {file.createNewFile();}return file;}/*** 删除SD卡上的⽂件** @param fileName*/public boolean deleteSDFile(String fileName) {File file = new File(SDPATH + "//" + fileName);if (file == null || !file.exists() || file.isDirectory())return false;return file.delete();}/*** 写⼊内容到SD卡中的txt⽂本中* str为内容*/public void writeSDFile(String str,String fileName){try {FileWriter fw = new FileWriter(SDPATH + "//" + fileName);File f = new File(SDPATH + "//" + fileName);fw.write(str);FileOutputStream os = new FileOutputStream(f); DataOutputStream out = new DataOutputStream(os);out.writeShort(2);out.writeUTF("");System.out.println(out);fw.flush();fw.close();System.out.println(fw);} catch (Exception e) {}}/*** 读取SD卡中⽂本⽂件** @param fileName* @return*/public String readSDFile(String fileName) {StringBuffer sb = new StringBuffer();File file = new File(SDPATH + "//" + fileName);try {FileInputStream fis = new FileInputStream(file);int c;while ((c = fis.read()) != -1) {sb.append((char) c);}fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return sb.toString();}public String getFILESPATH() {return FILESPATH;}public String getSDPATH() {return SDPATH;}public boolean hasSD() {return hasSD;}}复制代码代码如下:main.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android" android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/hasSDTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/SDPathTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/FILESpathTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/createFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /><TextViewandroid:id="@+id/readFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /><TextViewandroid:id="@+id/deleteFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /></LinearLayout>复制代码代码如下:FileOperateActivity.class/*** @Title: FileOperateActivity.java* @Package com.tes.textsd* @Description: TODO(⽤⼀句话描述该⽂件做什么)* @author Alex.Z* @date 2013-2-26 下午5:47:28* @version V1.0*/package com.tes.textsd;import java.io.IOException;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class FileOperateActivity extends Activity {private TextView hasSDTextView;private TextView SDPathTextView;private TextView FILESpathTextView;private TextView createFileTextView;private TextView readFileTextView;private TextView deleteFileTextView;private FileHelper helper;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);hasSDTextView = (TextView) findViewById(R.id.hasSDTextView); SDPathTextView = (TextView) findViewById(R.id.SDPathTextView); FILESpathTextView = (TextView) findViewById(R.id.FILESpathTextView); createFileTextView = (TextView) findViewById(R.id.createFileTextView); readFileTextView = (TextView) findViewById(R.id.readFileTextView); deleteFileTextView = (TextView) findViewById(R.id.deleteFileTextView); helper = new FileHelper(getApplicationContext()); hasSDTextView.setText("SD卡是否存在:" + helper.hasSD()); SDPathTextView.setText("SD卡路径:" + helper.getSDPATH()); FILESpathTextView.setText("包路径:" + helper.getFILESPATH());try {createFileTextView.setText("创建⽂件:"+ helper.createSDFile("test.txt").getAbsolutePath());} catch (IOException e) {e.printStackTrace();}deleteFileTextView.setText("删除⽂件是否成功:"+ helper.deleteSDFile("xx.txt"));helper.writeSDFile("1213212", "test.txt");readFileTextView.setText("读取⽂件:" + helper.readSDFile("test.txt"));}}看看运⾏的效果:。
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卡数据读写流程是指将数据从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卡的读写过程中,需要采取一定的措施保护数据。
linux 读写 sd卡 方法
linux 读写 sd卡方法
在Linux系统中,要读写SD卡,你可以按照以下步骤进行操作:
1. 插入SD卡,首先,在Linux系统中插入SD卡。
插入SD卡后,系统通常会自动挂载SD卡,如果没有自动挂载,你可以手动挂
载SD卡。
2. 确认SD卡挂载点,在Linux系统中,挂载SD卡后,系统会
将SD卡挂载到某个目录下,你可以使用命令“df -h”或者“lsblk”来查看SD卡的挂载点。
3. 读取SD卡数据,一旦SD卡被挂载到系统中,你就可以通过
文件管理器或者命令行来访问SD卡中的数据。
在文件管理器中,你
可以直接点击SD卡的挂载点来访问SD卡中的文件;在命令行中,
你可以使用“cd”命令切换到SD卡的挂载点,然后使用“ls”命令
来列出SD卡中的文件和目录。
4. 写入SD卡数据,如果你想向SD卡中写入数据,你可以直接
在文件管理器中拖拽文件到SD卡的挂载点,或者在命令行中使用“cp”命令或者“mv”命令来复制或移动文件到SD卡中。
5. 安全移除SD卡,在完成读写操作后,你应该安全地移除SD 卡,以免损坏数据。
你可以在文件管理器中右键点击SD卡的挂载点
并选择“安全移除”,或者在命令行中使用“umount”命令来卸载
SD卡。
总的来说,在Linux系统中,读写SD卡的方法主要涉及到挂载SD卡、访问SD卡中的数据、以及安全地移除SD卡。
通过以上步骤,你应该能够在Linux系统中成功读写SD卡。
SD卡读写操作详细说明
SD卡读写操作详细说明
一、SD卡的读取
1、安装SD卡:在使用SD卡之前,首先要将SD卡放入SD卡插槽,然后把开关拉到ON位置,表明SD卡装载完成。
2、打开IO口:在使用SD卡之前,需要在正确的地址上打开该SD卡的IO口,这样才能进行SD卡的读写操作。
3、初始化SD卡:在SD卡装载完成并打开IO口后,就可以进行SD 卡的初始化操作了。
SD卡的初始化是必须的,只有在SD卡的初始化操作成功后,才能进行下一步的读写操作。
4、发送CMD命令:发送CMD命令是SD卡的read操作的前提,必须发送CMD命令,才能获得SD卡中指定的数据,进而实现SD卡的读取。
5、读取数据:在发送CMD命令之后,就可以对SD卡中指定的数据进行读取,可以读取文本文件,二进制文件,BMP图片等等。
二、SD卡的写入
1、打开IO口:在使用SD卡之前,需要在正确的地址上打开该SD卡的IO口,这样才能进行SD卡的读写操作。
2、初始化SD卡:在SD卡装载完成并打开IO口后,就可以进行SD 卡的初始化操作了。
SD卡的初始化是必须的,只有在SD卡的初始化操作成功后,才能进行下一步的读写操作。
3、格式化SD卡:在连接SD卡后,需要进行格式化操作,必须格式化SD卡,才能进行SD卡的写入操作。
4、发送CMD命令:写入操作也需要发送CMD命令,发送CMD命令的目的是为了定位写入数据的位置。
5、写入数据:在发送CMD命令之后。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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寄存器。
Sector:和擦除命令相关,由几个块组成。
Sector的大小对每个设备是固定的,大小信息存储在CSD寄存器。
WP Group:写保护单位。
大小包括几个group,写保护由一位决定,对每个设备大小是固定的,存储在CSD寄存器。
3.5 读写操作Single Block Mode:主机根据事先定义的长度读写一个数据块。
由发送模块产生一个16位的CRC校验码,接受端根据校验码进行检验。
读操作的块长度受设备sector大小(512 bytes)的限制,但是可以最小为一个字节。
不对齐的访问是不允许的,每个数据块必须位于单个物理sector内。
写操作的大小必须为sector大小,起始地址必须与sector边界对齐。
Multiple Block Mode:主机可以读写多个数据块(相同长度),根据命令中的地址读取或写入连续的内存地址。
操作通过一个停止传输命令结束。
写操作必须地址对齐。
3.6 数据传输速率SD卡可以通过单数据线(DAT0)或四根数据线(DAT0-DAT3)进行数据传输。
单根数据线传输最大传输速率为25 Mbit/s,四根数据线最大传输速率为100 Mbit/s。
3.7 数据保护每个sector的数据通过Error Correction Code (ECC)进行保护。
在写sector时生成ECC,在读sector时检验ECC。
如果发现错误,在传输前进行纠正。
3.8数据擦除SD卡数据擦除的最小单位是sector。
为了加速擦除操作,多个sector可以同时擦除。
为了方便选择,第一个指令包含起始地址,第二个指令包含结束地址,在地址范围内的所有sector将被擦除。
3.9 写保护两种写保护方式可供选择,永久保护和临时保护,两种方式都可以通过PROGRAM_CSD指令进行设置。
永久保护位一旦设置将无法清除。
3.10 拷贝位通过CSD寄存器中的拷贝位(copy bit)设置SD卡中的数据是原始数据还是拷贝数据。
拷贝位一旦设置,将无法清除,在测试和格式化时使用。
3.11 CSD寄存器所有SD卡的配置信息存储在CSD寄存器。
通过SEND_CSD读取,PROGRAM_CSD修改。
4 SPI模式二、S D卡接口描述1 引脚和寄存器主机通过9个引脚和SD卡相连1.1 SD模式引脚扩展数据线(DAT1-DAT3)上电后为输入,SET_BUS_WIDTH命令执行后作为数据线。
即使只有DAT0使用,所有数据线都和外部上拉电阻连接,否则DAT1 & DAT2(如果未被使用)的振荡输入将引起非期望的高电流损耗。
上电后,数据线输入50K(+/-20K)欧姆的上拉(用来进行卡侦测和SPI模式选择)。
用户可以在常规数据传输时,通过SET_CLR_CARD_DETECT (ACMD42)命令分离上拉。
1.2 SPI模式引脚1.3 寄存器主机通过重新上电来重置(reset)卡。
卡有它自身检测上电的电路,当上电后卡状态切换到idle状态。
也可以通过GO_IDLE (CMD0)指令来重置。
2SD卡总线拓扑SD总线有6根通信线和三根电源供应线:✧CMD——命令线是双向信号线。
主机和卡通过push pull 模式工作。
✧DAT0-3——数据线是双向信号线。
主机和卡通过push pull 模式工作。
✧CLK——时钟是从主机到卡的信号。
CLK通过push pull 模式操作。
✧VDD—VDD是所有卡的电源供应线。
✧VSS[1:2]—VSS是2根地线。
在初始化的时候,向每个卡分别发送命令,允许应用检测卡并给物理槽(physical slot)分配逻辑地址。
数据通常分别传输给每个卡。
然后,为了方便处理卡堆栈,初始化后所有命令同时发送给所有卡,在命令数据包中包含了操作地址。
SD总线允许动态配置数据线数目。
上电后默认SD卡只用DAT0作为数据传输线。
初始化后,主机可以改变总线宽度。
这个特性使得在硬件开销和系统性能间取得平衡。
3SPI总线拓扑4电气接口4.1 上电上电后,包括热插入,卡进入idle状态。
在该状态SD卡忽略所有总线操作直到接收到ACMD41命令。
ACMD41命令是一个特殊的同步命令,用来协商操作电压范围,并轮询所有的卡。
除了操作电压信息,ACMD41的响应还包括一个忙标志,表明卡还在power-up过程工作,还没有准备好识别操作,即告诉主机卡还没有就绪。
主机等待(继续轮询)直到忙标志清除。
单个卡的最大上电时间不能操作1秒。
上电后,主机开始时钟并在CMD线上发送初始化序列,初始化序列由连续的逻辑“1”组成。
序列长度为最大1毫秒,74个时钟或supply-ramp-up时间。
额外的10个时钟(64个时钟后卡已准备就绪)用来实现同步。
每个总线控制器必须能执行ACMD41和CMD1。
CMD1要求MMC卡发送操作条件。
在任何情况下,ACMD41或CMD1必须通过各自的CMD线分别发送给每个卡。
5寄存器5.1 OCR(Operating Conditions Register)32位的操作条件寄存器存储了V DD电压范围。
SD卡操作电压范围为2~3.6V。
然而从内存中访问数据的电压是2.7~3.6V。
OCR显示了卡数据访问电压范围,结构如下表所示。
表3-8 OCR寄存器定义OCR结构如下图所示。
如果第32位(busy bit)置位,表明卡上电过程已结束。
5.2 CID(Card Identification)CID寄存器长度为16个字节的卡唯一标识号,该号在卡生产厂家编程后无法修改。
SD 和MMC卡的CID寄存器结构不一样。
1、格式为“n.m”,如“6.2”表示为0110 00105.3 CSD(Card Specific Data)CSD寄存器包含访问卡数据所需的配置信息。
SD卡和MMC卡的CSD不同。
6数据交互格式和卡容量通常,SD卡分为2个区:✧用户区—用户通过读写命令存储安全和非安全数据。
✧安全保护区(Security Protected Area)—版权保护应用程序用来保存安全相关数据,通过SD安全规范中定义的条件验证后,由主机使用安全的读写指令完成操作。
安全保护区的大小大概是总大小的1%。
三、S D卡协议1 SD总线协议SD总线通信是基于命令和数据位流方式的,由一个起始位开始,以一个停止位结束:命令——命令是开始开始操作的标记。
命令从主机发送一个卡(寻址命令)或所有连接的卡(广播命令)。
命令在CMD线上串行传送。
响应——响应是从寻址卡或所有连接的卡(同步)发送给主机用来响应接受到的命令的标记。
命令在CMD线上串行传送。
数据——数据可以通过数据线在卡和主机间双向传送。
卡寻址通过会话地址方式实现,地址在初始化的时候分配给卡。
SD总线上的基本操作是command/response。
数据传送采用块方式,数据块后接CRC校验位,操作包括单数据块和多数据块。
多数据块更适合快速写操作,多数据块传输当在CMD线出现停止命令时结束。
数据传输可以在主机端设置采用单数据线或多数据线方式。
块写操作在DAT0数据线写操作期间使用忙信号,无论用来传输的信号线数目是多少。
命令格式如下所示:响应标记(token)根据内容不同具有四种格式,标记长度。
长度为48位或136位。
数据块的CRC算法采用16位的CCITT多项式。
在命令行中,MSB位首先传送,LSB位最后传送。
当使用宽总线模式时,数据同时在4根数据线上传输。
开始位、结束位和CRC在每根数据线上传送。
CRC对每根数据线单独计算。
CRC状态响应和Busy信号只通过DAT0由卡发送给主机。
2 协议功能描述所有主机和SD卡间的通信由主机控制。
主机发送下述两类命令:●广播命令——广播命令发送给所有SD卡,有些命令需要响应。
●寻址(点对点)命令——寻址命令只发送给具有相应地址的卡,并需要从卡返回一个响应。
对卡而言也有两类操作:●卡识别模式——在重置(reset)后当主机查找总线上的新卡时,处于卡识别模式。
重置后SD卡将始终处于该模式,直到收到SEND_RCA命令(CMD3)。
●数据传输模式——一旦卡的REC发布后,将进入数据传输模式。
主机一旦识别了所有总线上的卡后,将进入数据传输模式。
操作模式与卡状态关系:3 卡识别模式在卡识别模式,主机重置所有处于卡识别模式的SD卡,检验操作电压范围,识别卡并请求卡发送相对卡地址RCA。
操作对每个卡在各自的CMD线上单独进行,所有的数据传送只使用CMD线。
3.1 重置GO_IDLE_STATE(CMD0)是软件重置命令,设置每个SD卡进入Idle状态。
处于Inactive 状态的卡不受此命令影响。
主机上电后,所有SD卡进入Idle状态,包括处于Inactive状态的卡。