SD卡读写包括两种模式

合集下载

SD卡读写

SD卡读写

SD卡读写前言长期以来,以Flash Memory为存储体的SD卡因具备体积小、功耗低、可擦写以及非易失性等特点而被广泛应用于消费类电子产品中。

特别是近年来,随着价格不断下降且存储容量不断提高,它的应用范围日益增广。

当数据采集系统需要长时间地采集、记录海量数据时,选择SD卡作为存储媒质是开发者们一个很好的选择。

在电能监测以及无功补偿系统中,要连续记录大量的电压、电流、有功功率、无功功率以及时间等参数,当单片机采集到这些数据时可以利用SD 作为存储媒质。

本文主要介绍了SD卡在电能监测及无功补偿数据采集系统中的应用方案。

设计方案应用AT89C52读写SD卡有两点需要注意。

首先,需要寻找一个实现AT89C52单片机与SD卡通讯的解决方案;其次,SD卡所能接受的逻辑电平与AT89C52提供的逻辑电平不匹配,需要解决电平匹配问题。

通讯模式SD卡有两个可选的通讯协议:SD模式和SPI模式。

SD 模式是SD卡标准的读写方式,但是在选用SD模式时,往往需要选择带有SD 卡控制器接口的MCU,或者必须加入额外的SD卡控制单元以支持SD卡的读写。

然而,AT89C52单片机没有集成SD卡控制器接口,若选用SD模式通讯就无形中增加了产品的硬件成本。

在SD卡数据读写时间要求不是很严格的情况下,选用SPI模式可以说是一种最佳的解决方案。

因为在SPI模式下,通过四条线就可以完成所有的数据交换,并且目前市场上很多MCU都集成有现成的SPI接口电路,采用SPI模式对SD卡进行读写操作可大大简化硬件电路的设计。

虽然AT89C52不带SD卡硬件控制器,也没有现成的SPI 接口模块,但是可以用软件模拟出SPI总线时序。

本文用SPI 总线模式读写SD卡。

电平匹配SD卡的逻辑电平相当于3.3V TTL电平标准,而控制芯片AT89C52的逻辑电平为5V CMOS电平标准。

因此,它们之间不能直接相连,否则会有烧毁SD卡的可能。

出于对安全工作的考虑,有必要解决电平匹配问题。

SD卡模式分析

SD卡模式分析

∙浅谈SD/MMC卡的SD模式和SPI模式
∙HANNY 发表于2009-10-24 15:15 | 分类:嵌入芯得| 浏览:7164
SD/MMC卡的读写模式分两种。

一种是利用SD总线来进行数据传输,这里称为SD模式;
另外一种是利用SPI总线来进行数据传输,这里称之为SPI模式。

最初接触SD/MMC卡时,Hanny一直觉得很奇怪,为什么SD/MMC卡要提供两种模式进行访问呢?比较完这两种模式的区别,分析其运用场合,就会明白答案了。

SD卡主要工作于4BIT SD模式下(MMC可能工作在8BIT SD模式下)。

其读写最高时钟可达50MHz,因此,市面上的卡的读取速度能到达20MB/s以上,已经算极限了。

SD模式也是SD卡的主要工作模式。

而SPI模式只有1BIT的带宽,而且时钟最高只能到25MHz,因此读取速度通常低于3MB/s。

但是SPI模式对硬件要求较低,一般广泛用于MP3等对读卡速度要求不高的低端场合。

Hanny当时还有一个疑问:SD模式不是也同样支持1BIT模式吗?为什么不直接用SD的1BIT 模式呢?
后来才明白:1、SPI总线是一个通用总线,大部份芯片都用硬件模块;2、SPI模式支持不带CRC校验的传输方式,可以降低硬件要求;3、SD的CMD线与DATA线之间有可能同时产生数据,对没有SD硬件模块的主机支持起来难度较高
CDMO对应MCU_MOSI第28个腿PB15,CDMI对应MCU_MISO第27个腿PB14。

SD卡读写操作 SD卡电路

SD卡读写操作  SD卡电路

SD卡在现在的日常生活与工作中使用非常广泛,时下已经成为最为通用的数据存储卡。

在诸如MP3、数码相机等设备上也都采用SD卡作为其存储设备。

SD卡之所以得到如此广泛的使用,是因为它价格低廉、存储容量大、使用方便、通用性与安全性强等优点。

既然它有着这么多优点,那么如果将它加入到单片机应用开发系统中来,将使系统变得更加出色。

这就要求对SD卡的硬件与读写时序进行研究。

对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的存储器结构、存储单元组织方式等内容。

要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写,并对其读写速度进行了评估。

下面先来讲解SD卡的读写时序。

(1)SD卡的引脚定义:SD卡引脚功能详述:SD卡SPI模式下与单片机的连接图:SD卡支持两种总线方式:SD方式与SPI方式。

其中SD方式采用6线制,使用CLK、CMD、DAT0~DAT3进行数据通信。

而SPI 方式采用4线制,使用CS、CLK、DataIn、DataOut进行数据通信。

SD方式时的数据传输速度与SPI方式要快,采用单片机对SD卡进行读写时一般都采用SPI模式。

采用不同的初始化方式可以使SD卡工作于SD方式或SPI方式。

这里只对其SPI方式进行介绍。

(2) SPI方式驱动SD卡的方法SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。

从应用的角度来看,采用SPI接口的好处在于,很多单片机内部自带SPI控制器,不光给开发上带来方便,同时也见降低了开发成本。

然而,它也有不好的地方,如失去了SD卡的性能优势,要解决这一问题,就要用SD方式,因为它提供更大的总线数据带宽。

SPI接口的选用是在上电初始时向其写入第一个命令时进行的。

以下介绍SD卡的驱动方法,只实现简单的扇区读写。

1)命令与数据传输1. 命令传输SD卡自身有完备的命令系统,以实现各项操作。

命令格式如下:命令的传输过程采用发送应答机制,过程如下:每一个命令都有自己命令应答格式。

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卡的读取(SPI)

SD卡的读取(SPI)

SPI模式下MCU对SD卡的控制及操作命令一、前言SD 卡有两个可选的通讯协议:SD 模式和 SPI模式 SD 模式是SD 卡标准的读写方式,但是在选用SD 模式时,往往需要选择带有SD 卡控制器接口的 MCU,或者必须加入额外的SD卡控制单元以支持SD 卡的读写然而,大多数MCU都没有集成SD 卡控制器接口,若选用SD 模式通讯就无形中增加了产品的硬件成本。

在SD卡数据读写时间要求不是很严格的情况下,选用 SPI模式可以说是一种最佳的解决方案因为在 SPI模式下,通过四条线就可以完成所有的数据交换,并且目前市场上很多MCU都集成有现成的SPI接口电路,采用 SPI模式对 SD卡进行读写操作可大大简化硬件电路的设计二、硬件电路实现以NXP的LPC2210 ARM7MCU为例,下图是周立功开发的实现板电路这里,将LPC2210MCU的SPI0用于SD卡的控制和数据读写。

对SPI0的两个数据线加了上拉电阻以便于MMC卡兼容。

卡供电采用了可控方式,通过GPIO口控制MOS管对其进行供电。

卡检测电路也使用GPIO口实现。

通过读GPIO口数据,检查卡是否写保护和完全插入。

具体内容可以参考周立功的说明书,百度文库里边有三、SD卡物理接口我们看到的SD卡一包如下所示,包含9个引脚和一个写保护开关:其引脚定义如下:注:1. S:电源;I:输入;O:推挽输出;PP:推挽I/O。

2. 扩展的DAT线(DAT1 ~ DAT3)在上电后处于输入状态。

它们在执行SET_BUS_WIDTH命令后作为DAT线操作。

当不使用DAT1 ~ DAT3 线时,主机应使自己的DAT1~DAT3线处于输入模式。

这样定义是为了与MMC卡保持兼容。

3. 上电后,这条线为带50KΩ上拉电阻的输入线(可以用于检测卡是否存在或选择 SPI 模式)。

用户可以在正常的数据传输中用 SET_CLR_CARD_DETECT(ACMD42)命令断开上拉电阻的连接。

SD卡读写学习-----使用文档

SD卡读写学习-----使用文档

SD 卡读写学习使用文档一、 概述SD 卡是基于 flash 的存储卡,其和 MMC 卡的区别在于初始化过程不同。

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

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

二、SD 卡读写操作读操作的块长度受设备 sector 大小 (512 bytes)的限制,但是可以最小为一个字节。

51单片机读写SD 卡一般使用SD 卡的SPI 模式 0、CMD 命令格式:First Byte Byte 2-5 Last Byte 参数:4Byte---32bit ,指向要写入的字节地址,所以限制了SD 卡可以最大写入4g 数据bit7 bit6 bit5~0 Databit7~1 bit0 01命令参数(高位在前)CRC 校验1示例: CMD0号命令,CMD24(0x40+24=0x58)号命令时,参数为要写入的地址。

固定 CMD0命令 参数(2-5) CRC 校验 固定01 | 00 0000 | 0000 0000 ........ 0000 | 1001 010 | 1 0x40, 0x00,0x00,0x00,0x00, 0x95 adr<<=9;//取512的整数倍,因一个扇区为512字节。

CMD[1]=(addr>>24); CMD[2]=(addr>>16); CMD[3]=(addr>>8); CMD[4]=(addr>>0); $、SPI 模式:SD 卡启动时处在SD 总线模式下,要进入SPI 模式时,要遵守如下操作。

SD 卡复位及初始化时,时钟频率一定要慢下来,最高不超过400KHZ 。

1)SD 卡复位复位SD 卡:a 、所有引脚拉高,片选CS 为1时,首先往SD 卡写入至少74个时钟信号。

(SD 卡协议规定)b 、片选CS 拉低为0,写入CMD0命令(0x40,0x00,0x00,0x00,0x00,0x95)c 、读取SD 卡MISO 返回数据直到SD 卡返回0x01。

sd卡工作流程

sd卡工作流程

sd卡工作流程SD卡是一种常见的存储设备,广泛应用于数码相机、手机、平板电脑等电子设备中。

它具有体积小、存储容量大、读写速度快等优点,成为了现代数字化生活不可或缺的一部分。

下面将详细介绍SD卡的工作流程。

一、SD卡的基本结构SD卡主要由控制器和存储芯片两部分组成。

其中,控制器负责管理整个SD卡的读写操作,包括对数据进行编码、解码、传输等;存储芯片则是实际存储数据的地方,通常采用闪存技术。

二、SD卡的读写操作流程1.插入SD卡首先需要将SD卡插入读卡器或支持SD卡的设备中。

插入时需要注意方向和位置,确保正确插入。

2.建立连接当设备检测到SD卡后,会通过接口与控制器建立连接。

此时控制器会发送初始化命令给存储芯片,并获取SD卡相关信息(如容量、速度等)。

3.读取数据在进行读取操作时,控制器会发送读取命令给存储芯片,并指定要读取的数据块地址和长度。

存储芯片接收到命令后会将数据块读取出来,通过控制器传输给设备。

4.写入数据在进行写入操作时,控制器会发送写入命令给存储芯片,并指定要写入的数据块地址和长度。

存储芯片接收到命令后会将数据块写入,通过控制器传输给设备。

5.结束操作读取或写入操作完成后,设备会向控制器发送结束命令。

此时控制器会关闭连接并释放资源。

三、SD卡的文件系统为了更好地管理SD卡中的数据,需要对其进行格式化和分区。

格式化是指对存储芯片进行初始化,并建立文件系统;分区则是将SD卡划分为若干个逻辑区域,每个区域可以独立使用。

1.格式化SD卡格式化SD卡可以清除所有数据并重新建立文件系统。

通常有两种格式化方式:快速格式化和完全格式化。

快速格式化只清除文件表,而完全格式化则会对整个存储芯片进行擦除操作。

2.分区SD卡分区可以将SD卡划分为多个逻辑驱动器,在每个驱动器中可以独立使用。

通常使用Windows自带的磁盘管理工具或第三方分区软件来进行分区操作。

四、SD卡的保护机制为了防止SD卡中的数据丢失或被损坏,SD卡还具有一些保护机制。

SD卡读写的方式(用SD模式)

SD卡读写的方式(用SD模式)

SD卡读写的方式(用SD模式)大家读写SD卡怎么不用SD模式方式读取,是SPI方式读取简单?下面贴一段代码,是在FPGA上程序,只能用SD模式进行读,没有文件系统,没有用AVR硬件实现,电路图:电路说明,SD_DAT3一直给高电平程序:#ifndef __SD_Card_H__#define __SD_Card_H__#define High 1#define Low 0//-------------------------------------------------------------------------// SD Card Set I/O Direction#define SD_CMD_IN DDRX.1 = Low#define SD_CMD_OUT DDRX.1 = High#define SD_DAT_IN DDRX.2 = Low#define SD_DAT_OUT DDRX.2 = High#define SD_CLK_OUT DDRX.3 = High#define SD_DAT3_OUT DDRX.0 = High// SD Card Output High/Low#define SD_CMD_LOW PORTX.1 = Low#define SD_CMD_HIGH PORTX.1 = High#define SD_DAT_LOW PORTX.2 = Low#define SD_DAT_HIGH PORTX.2 = High#define SD_CLK_LOW PORTX.3 = Low#define SD_CLK_HIGH PORTX.3 = High#define SD_DAT3_HIGH PORTX.0 = High// SD Card Input Read#define SD_TEST_CMD PINX.1#define SD_TEST_DAT PINX.2//------------------------------------------------------------------------- #define BYTE unsigned char#define UINT16 unsigned int#define UINT32 unsigned long//------------------------------------------------------------------------- void Ncr(void);void Ncc(void);BYTE response_R(BYTE);BYTE send_cmd(BYTE *);BYTE SD_read_lba(BYTE *,UINT32,UINT32);BYTE SD_card_init(void);//------------------------------------------------------------------------- BYTE read_status;BYTE response_buffer[20];BYTE RCA[2];BYTE cmd_buffer[5];const BYTE cmd0[5] = {0x40,0x00,0x00,0x00,0x00};const BYTE cmd55[5] = {0x77,0x00,0x00,0x00,0x00};const BYTE cmd2[5] = {0x42,0x00,0x00,0x00,0x00};const BYTE cmd3[5] = {0x43,0x00,0x00,0x00,0x00};const BYTE cmd7[5] = {0x47,0x00,0x00,0x00,0x00};const BYTE cmd9[5] = {0x49,0x00,0x00,0x00,0x00};const BYTE cmd16[5] = {0x50,0x00,0x00,0x02,0x00};const BYTE cmd17[5] = {0x51,0x00,0x00,0x00,0x00};const BYTE acmd6[5] = {0x46,0x00,0x00,0x00,0x02};const BYTE acmd41[5] = {0x69,0x0f,0xf0,0x00,0x00};const BYTE acmd51[5] = {0x73,0x00,0x00,0x00,0x00};//------------------------------------------------------------------------- void Ncr(void){SD_CMD_IN;SD_CLK_LOW;SD_CLK_HIGH;SD_CLK_LOW;SD_CLK_HIGH;}//------------------------------------------------------------------------- void Ncc(void){int i;for(i=0;i<8;i++){SD_CLK_LOW;SD_CLK_HIGH;}}//------------------------------------------------------------------------- BYTE SD_card_init(void){BYTE x,y;SD_CMD_OUT;SD_DAT_IN;SD_CLK_HIGH;SD_CMD_HIGH;SD_DAT_LOW;read_status=0;for(x=0;x<40;x++)Ncr();for(x=0;x<5;x++)cmd_buffer[x]=cmd0[x];y = send_cmd(cmd_buffer);do{for(x=0;x<40;x++);Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd55[x];y = send_cmd(cmd_buffer);Ncr();if(response_R(1)>1) //response too long or crc errorreturn 1;Ncc();for(x=0;x<5;x++)cmd_buffer[x]=acmd41[x];y = send_cmd(cmd_buffer);Ncr();} while(response_R(3)==1); Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd2[x];y = send_cmd(cmd_buffer); Ncr();if(response_R(2)>1) return 1;Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd3[x];y = send_cmd(cmd_buffer); Ncr();if(response_R(6)>1) return 1;RCA[0]=response_buffer[1]; RCA[1]=response_buffer[2]; Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd9[x]; cmd_buffer[1] = RCA[0]; cmd_buffer[2] = RCA[1];y = send_cmd(cmd_buffer); Ncr();if(response_R(2)>1) return 1;Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd7[x]; cmd_buffer[1] = RCA[0];cmd_buffer[2] = RCA[1];y = send_cmd(cmd_buffer);Ncr();if(response_R(1)>1)return 1;Ncc();for(x=0;x<5;x++)cmd_buffer[x]=cmd16[x];y = send_cmd(cmd_buffer);Ncr();if(response_R(1)>1)return 1;read_status =1; //sd card readyreturn 0;}//------------------------------------------------------------------------- BYTE SD_read_lba(BYTE *buff,UINT32 lba,UINT32 seccnt) {BYTE c=0;UINT32 i,j;lba+=101;for(j=0;j<seccnt;j++)< p="">{{Ncc();cmd_buffer[0] = cmd17[0];cmd_buffer[1] = (lba>>15)&0xff; cmd_buffer[2] = (lba>>7)&0xff; cmd_buffer[3] = (lba<<1)&0xff; cmd_buffer[4] = 0;lba++;send_cmd(cmd_buffer); Ncr();}while(1){SD_CLK_LOW;SD_CLK_HIGH;if(!(SD_TEST_DAT)) break;}for(i=0;i<512;i++) {BYTE k;for(k=0;k<8;k++){SD_CLK_LOW;SD_CLK_HIGH;c <<= 1;if(SD_TEST_DAT)c |= 0x01;}*buff=c;buff++;}for(i=0; i<16; i++) {SD_CLK_LOW;SD_CLK_HIGH;}}read_status = 1; //SD data next inreturn 0;}//------------------------------------------------------------------------- BYTE response_R(BYTE s){BYTE a=0,b=0,c=0,r=0,crc=0;BYTE i,j=6,k;while(1){SD_CLK_LOW;SD_CLK_HIGH;if(!(SD_TEST_CMD))break;if(crc++ >100)return 2;}crc =0;if(s == 2)j = 17;for(k=0; k<="" p="">{c = 0;if(k > 0) //for crc culcarb = response_buffer[k-1];for(i=0; i<8; i++){SD_CLK_LOW;if(a > 0)c <<= 1;elsei++;a++;SD_CLK_HIGH;if(SD_TEST_CMD)c |= 0x01;if(k > 0){crc <<= 1;if((crc ^ b) & 0x80)crc ^= 0x09;b <<= 1;crc &= 0x7f;}}if(s==3){if( k==1 &&(!(c&0x80)))r=1;}response_buffer[k] = c;}if(s==1 || s==6){if(c != ((crc<<1)+1))r=2;}return r;}//------------------------------------------------------------------------- BYTE send_cmd(BYTE *in) {int i,j;BYTE b,crc=0;SD_CMD_OUT;for(i=0; i < 5; i++){b = in[i];for(j=0; j<8; j++){SD_CLK_LOW;if(b&0x80)SD_CMD_HIGH;elseSD_CMD_LOW;crc <<= 1;SD_CLK_HIGH;if((crc ^ b) & 0x80)crc ^= 0x09;b<<=1;}crc &= 0x7f;}crc =((crc<<1)|0x01);b = crc;for(j=0; j<8; j++){SD_CLK_LOW;if(crc&0x80)SD_CMD_HIGH;elseSD_CMD_LOW;SD_CLK_HIGH;crc<<=1;}return b;}//-------------------------------------------------------------------------#endif这些程序有些我也不明白,贴出来希望大家一起探讨交流,打破网站SD卡用SPI方式读写的垄断局面,哈哈sd模式下应该有4各data吧,怎么你的只用一个?SPI模式是1Bit的SD模式是1Bit或4BitSD卡确实也像USB一样分为全速(FULL-SPEED)卡和低速卡(LOW-SPEED)。

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卡是一种常见的存储媒介,它具有轻便、易携带、容量大、存储速度快等优势。

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卡的读写过程中,需要采取一定的措施保护数据。

SPI通信与SD卡

SPI通信与SD卡

SPI通信与SD卡一、前言SD 卡有两个可选的通讯协议:SD 模式和SPI模式SD 模式是SD 卡标准的读写方式,但是在选用SD 模式时,往往需要选择带有SD 卡控制器接口的MCU,或者必须加入额外的SD卡控制单元以支持SD 卡的读写然而,大多数MCU都没有集成SD 卡控制器接口,若选用SD 模式通讯就无形中增加了产品的硬件成本。

在SD卡数据读写时间要求不是很严格的情况下,选用SPI模式可以说是一种最佳的解决方案因为在SPI 模式下,通过四条线就可以完成所有的数据交换,并且目前市场上很多MCU都集成有现成的SPI接口电路,采用SPI模式对SD卡进行读写操作可大大简化硬件电路的设计二、硬件电路实现以NXP的LPC2210 ARM7MCU为例,下图是周立功开发的实现板电路这里,将LPC2210MCU的SPI0用于SD卡的控制和数据读写。

对SPI0的两个数据线加了上拉电阻以便于MMC卡兼容。

卡供电采用了可控方式,通过GPIO口控制MOS管对其进行供电。

卡检测电路也使用GPIO口实现。

通过读GPIO口数据,检查卡是否写保护和完全插入。

具体内容可以参考周立功的说明书,百度文库里边有三、SD卡物理接口我们看到的SD卡一包如下所示,包含9个引脚和一个写保护开关:其引脚定义如下:注:1. S:电源;I:输入;O:推挽输出;PP:推挽I/O。

2. 扩展的DAT线(DAT1 ~ DAT3)在上电后处于输入状态。

它们在执行SET_BUS_WIDTH命令后作为DAT线操作。

当不使用DAT1 ~ DAT3 线时,主机应使自己的DAT1~DAT3线处于输入模式。

这样定义是为了与MMC卡保持兼容。

3. 上电后,这条线为带50KΩ上拉电阻的输入线(可以用于检测卡是否存在或选择SPI 模式)。

用户可以在正常的数据传输中用SET_CLR_CARD_DETECT(ACMD42)命令断开上拉电阻的连接。

MMC卡的该引脚在SD模式下为保留引脚,在SD模式下无任何作用。

51单片机SD卡SPI模式操作_1568

51单片机SD卡SPI模式操作_1568

【51单片机SD卡SPI模式操作】摘要:sd卡有两种接口模式,一种是sd模式,另一种是spi模式。

在spi模式下,有六根接口线与主机相连,5V电平的51单片机通过电平转换可与3.3V电平的sd卡相连接。

51单片机没有专门的spi总线,可以用51单片机的IO口来模拟spi总结时序。

主机与sd卡的数据交换主要通过命令来实现,通过发送cmd0命令对sd卡进行复位,发送命令cmd1实现sd卡的spi模式初始化。

cmd17、cmd18命令是sd卡的读写扇区命令,对sd卡的操作是严格按照时序进行的。

关键词:sd卡;spi接口;时序sd卡以其大容量、低成本、携带方便、存储数据简单和安全可靠性高被大量应用于数码电子设备中,比如数码相机、数码摄像机、mp3、pda、电子学习机、电子图书等。

对sd卡的操作有复位、初始化、读写等,下面以本人掌握的材料对sd卡的操作进行分析。

一、sd卡的结构sd卡的外形与接口如图1,它有9个接点与主机相连,其接口端定义如表1所示。

sd卡有两种操作模式,一种是sd模式,另一种是spi模式,不同模式下端口的定义不同。

SD模式有一个时钟线、一个命令/反馈线、四根输入/输出信号线、两个电源地和一个电源,所有九根线都有定义,数据传输速率较快。

SPI模式只用到CS片选、数据输入、数据输出、时钟、电源地及电源六根线。

SPI模式较SD模式速度较慢,但很多单片机都有专用的SPI总线,可与sd卡直接相连,使用方便。

SD卡的内部结构如图2所示,主要有四部分组成,一是接口电路,共有九个接口电路,定义如表1所示。

二是接口控制电路,所有操作都由该控制电路具体去执行。

三是内部寄存器组OCR、CID、RCA等。

四是存储数据的存储单元。

接口电路通过控制电路与内部寄存器组成存储单元交换数据,其主要操作有写命令、读数据、写数据、读状态等。

二、sd卡的命令格式sd卡的命令格式固定为6个字节48个位,其格式如图3所示。

开始位固定为0,第二位固定为1,表示主机给sd卡的命令,然后是6位命令索引号,索引号的大小与索引号数字相同,比如cmd0的索引号为000000,索引号41为101001。

(整理)stm32Fatfs读写SD卡.

(整理)stm32Fatfs读写SD卡.

stm32 Fatfs 读写SD卡读写SD是嵌入式系统中一个比较基础的功能,在很多应用中都可以用得上SD 卡。

折腾了几天,总算移植成功了最新版Fatfs(Fatfs R0.09),成功读写SD卡下文件。

FatFs (/fsw/ff/00index_e.html)是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。

FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。

它可以嵌入到便宜的微控制器中,如8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。

1. SD卡/TF卡硬件接口SD卡有两种操作接口,SDIO和SPI。

使用SDIO口的速度比较快,SPI的速度比较慢。

SD卡引脚描述如下: SD卡SPI接法如下:我使用的是正点原子的开发板,所以采用的是SPI接口的模式。

TF卡SDIO 模式和SPI模式引脚定义:可以发现Micro SD卡只有8个引脚是因为比SD卡少了一个Vss。

使用TF转SD的卡套套在Micro SD卡上,这样一来大小就和SD卡一样大,这时候卡套上的9个引脚就和SD卡一样了,你可以完全当做SD卡来操作。

2. SD卡底层驱动SD卡的操作比较复杂,需要多看看一些文档。

这里附上SD底层驱动代码,代码说明详见注释Sd卡SPi操作底层代码: sdcard.c sdcard.h3. Fatfs 移植FatFs 软件包中相关文件:ffconf.h FatFs 模块配置文件ff.h FatFs 和应用模块公用的包含文件ff.c FatFs 模块diskio.h FatFs and disk I/O 模块公用的包含文件integer.h 数据类型定义option 可选的外部功能diskio.c FatFs 与disk I/O 模块接口层文件(不属于FatFs 需要由用户提供)FatFs 配置,文件系统的配置项都在ffconf.h 文件之中:(1) _FS_TINY :这个选项在R0.07 版本之中开始出现,在之前的版本都是以独立的文件出现,现在通过一个宏来修改使用起来更方便;(2) _FS_MINIMIZE、_FS_READONLY、_USE_STRFUNC、_USE_MKFS、_USE_FORWARD 这些宏是用来对文件系统进行裁剪(3) _CODE_PAGE :本选项用于设置语言码的类型(4) _USE_LFN :取值为0~3,主要用于长文件名的支持及缓冲区的动态分配:0:不支持长文件名;1:支持长文件名存储的静态分配,一般是存储在BSS 段;2:支持长文件名存储的动态分配,存储在栈上;3:支持长文件名存储的动态分配,存储在堆上。

SD卡总结

SD卡总结

1、SD 卡支持两种总线方式:SD 方式与 SPI 方式。

SD 方式采用6线制,使用 CLK、CMD、DAT0、DAT1、DAT2、DAT3 进行数据通信,其特点是数据位数宽(4 位)、速度快。

SPI 方式采用4线制,使用 CS、CLK、DataIn、DataOut这4个端口进行数据通信,其特点是速度要比 SD 方式慢,但总线简单、不需要进行 CRC 校验,因而比较适合单片机采用这种方式对SD卡进行读写操作。

3、电路4、SD 卡的命令字由 6 个字节组成命令字的第1个字节为命令号(CMD0、CMD1 等),命令号的最高位始终为 0,次高位(位 7)为1,表示命令是由主机向 SD 卡发送的命令。

命令字的第2、3、4、5字节为命令参数表,传送随命令附带的参数,如地址信息等。

命令字的最后一个字节为 CRC 校验字节,其中该字节的高7位为 CRC 码,最后一位为结束位,始终为1。

当主机向 SD 卡发送一个命令后,SD 卡会首先向主机发送一个相应码,如果指令没有错误 SD 卡接下来便会执行主机发来的命令。

5、SD 卡复位至 SPI 方式SD 卡默认的读写方式为 SD 模式,要使用 SPI 模式对 SD 卡进行读写,需要在 SD 卡上电后对 SD 卡写入 CMD0 和 CMD1 命令。

在两条命令写入 SD 卡后,如果一切正常,SD 卡会进入 SPI 模式,从而可以方便地采用单片机对 SD 卡进行 SPI 方式的读写操作。

当 SD 卡完成上电后,先对 SD 卡发送 74 个以上的同步时钟。

然后向 SD 卡发送 CMD0 命令(因命令号的最高位始终为 0,次高位为 1,因此发送给 SD 卡的命令是 0 与 0x40 进行或运算的结果)。

命令字的第 2、3、4、5 字节皆为 0x00。

命令字的第 6 字节为 CRC 校验字节,固定为 0x95。

命令字发送完成后,发送若干个 8 位的同步时钟,直至 SD 卡发出响应字节0x01。

Arduino+ESP32之SD卡读写

Arduino+ESP32之SD卡读写

Arduino+ESP32之SD卡读写背景知识:有两种使⽤SD卡的⽅法,⼀种是使⽤SPI接⼝访问SD卡,另⼀种是使⽤SDMMC接⼝访问SD卡。

Arduino core for the ESP32中SPI⽅式占⽤4个IO⼝,SDMMC⽅式占⽤6个IO⼝,⼀般来说SDMMC⽅式速度要⽐SPI⽅式快。

1. SDMMC⽅式ESP32虽然有两组SDMMC接⼝,但Arduino core for the ESP32中只⽤到了其中⼀组,IO⼝连接为:DAT2 - IO12、DAT3 - IO13、CMD -IO15、CLK - IO14、DAT0 - IO2、DAT1 - IO4;bool begin(const char * mountpoint="/sdcard", bool mode1bit=false)挂载存储卡,输⼊参数分别为挂载点、是否使⽤⼀线模式;void end()取消挂载;sdcard_type_t cardType() 返回存储卡类型,0、1、2、3、4,分别如下:CARD_NONE 未连接存储卡;CARD_MMC mmc卡;CARD_SD sd卡,最⼤2G;CARD_SDHC sdhc卡,最⼤32G;CARD_UNKNOWN 未知存储卡;uint64_t cardSize() 返回存储卡⼤⼩字节数;uint64_t totalBytes() 返回⽂件系统总字节数;uint64_t usedBytes() 返回⽂件系统已⽤字节数;2. SPI⽅式bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5)挂载存储卡,输⼊参数分别为SS引脚号、SPI对象、时钟频率、挂载点、⽂件最⼤同时打开数;默认IO⼝连接为:CS - IO5、DI - IO23、SCLK - IO18、DO - IO19;void end()取消挂载;sdcard_type_t cardType() 返回存储卡类型,0、1、2、3、4,分别如下:CARD_NONE 未连接存储卡;CARD_MMC mmc卡;CARD_SD sd卡,最⼤2G;CARD_SDHC sdhc卡,最⼤32G;CARD_UNKNOWN 未知存储卡;uint64_t cardSize() 返回存储卡⼤⼩字节数;uint64_t totalBytes() 返回⽂件系统总字节数;uint64_t usedBytes(); 返回⽂件系统已⽤字节数3. 我的实验我⼿头的ESP32_CAM板⼦的原理图右图可知,我的SD卡接到了ESP32的GPIO12 13 14 15 2 4 这6个脚上,根据前述,这符合SDMMC⽅式的IO连接。

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命令之后。

SD卡读写包括两种模式

SD卡读写包括两种模式

SD卡读写包括两种模式SD卡读写包括两种模式:SD模式和SPI模式。

其中SD模式又可以分为1bit 和4bit两种传输模式。

SD卡缺省使用专有的SD模式。

SD卡规范中主要讲了一些命令,响应和CRC效验等等,整个规范的内容还是很多的。

SD卡上电后,卡处于空闲状态,主机发送CMD0复位SD卡,然后通过CMD55和ACMD41判断当前电压是否在卡的工作范围内。

在得到了正确的响应后,主机可以继续通过CMD10读取SD卡的CID寄存器,通过CMD16设置数据块长度,通过CMD9读取卡的CSD寄存器。

从CSD寄存器中,主机可以获知卡容量,支持的命令集等重要参数。

此时,卡以进入了传输状态,主机就可以通过CMD17/18和CMD24/25对卡进行读写。

CRC校验是为了防止SD卡的命令,应答,数据传输出现错误。

每个命令和应答信号都会产生CRC效验码,每个数据块的传输也会长生CRC效验码。

这段程序是友善之臂推出的mini2440开发板中带的ADS测试源码。

整个阅读代码的过程是对这S3C2440的芯片手册和SD卡规范来看的,对于MMC卡没有给出注释,其实和SD卡是大同小异。

由于是初次接触ARM,对SD规范的认识也不是很深入,再加上自己水平有限,还不能完全读懂源代码,其中的肯定存在一些错误,欢迎大家一起交流讨论。

#define INT 1#define DMA 2int CMD13(void);// Send card statusint CMD9(void);unsigned int*Tx_buffer;//128[word]*16[blk]=8192[byte] unsigned int*Rx_buffer;//128[word]*16[blk]=8192[byte] volatile unsigned int rd_cnt;//读数据计数器volatile unsigned int wt_cnt;//写数据计数器volatile unsigned int block;//读写块总数volatile unsigned int TR_end=0;int Wide=0;// 0:1bit, 1:4bitint MMC=0;// 0:SD , 1:MMCint Maker_ID;char Product_Name[7];int Serial_Num;volatile int RCA;void Test_SDI(void){U32 save_rGPEUP, save_rGPECON;RCA=0;MMC=0;block=3072;//3072Blocks=1.5MByte,((2Block=1024Byte)*1024Block=1MByte)save_rGPEUP=rGPEUP;save_rGPECON=rGPECON;//**配置SD/MMC控制器rGPEUP = 0xf83f;// SDCMD, SDDAT[3:0] => PU En. rGPECON = 0xaaaaaaaa;//SDCMD, SDDAT[3:0]Uart_Printf("\nSDI Card Write and Read Test\n");if(!SD_card_init())//等待SD卡初始化完成return;TR_Buf_new();//发送数据缓冲区初始化Wt_Block();//写卡Rd_Block();//读卡View_Rx_buf();if(MMC)TR_Buf_new();if(MMC){rSDICON |=(1<<5);// YH 0519, MMC Type SDCLKWt_Stream();Rd_Stream();View_Rx_buf();}Card_sel_desel(0);// Card deselectif(!CMD9())Uart_Printf("Get CSD fail\n");rSDIDCON=0;//tarkrSDICSTA=0xffff;rGPEUP=save_rGPEUP;rGPECON=save_rGPECON;}void TR_Buf_new(void)//发送数据缓冲区初始化{//-- Tx & Rx Buffer initializeint i, j;Tx_buffer=(unsigned int*)0x31000000;j=0;for(i=0;i<2048;i++)//128[word]*16[blk]=8192[byte] *(Tx_buffer+i)=i+j;Flush_Rx_buf();}void Flush_Rx_buf(void)//接收数据缓冲区清0{//-- Flushing Rx bufferint i;Rx_buffer=(unsigned int*)0x31800000;for(i=0;i<2048;i++)//128[word]*16[blk]=8192[byte] *(Rx_buffer+i)=0;Uart_Printf("End Rx buffer flush\n");}void View_Rx_buf(){//-- Display Rx bufferint i,error=0;Tx_buffer=(unsigned int*)0x31000000;Rx_buffer=(unsigned int*)0x31800000;Uart_Printf("Check Rx data\n");for(i=0;i<128*block;i++){if(Rx_buffer[i]!= Tx_buffer[i]){Uart_Printf("\nTx/Rx error\n");Uart_Printf("%d:Tx-0x%08x, Rx-0x%08x\n",i,Tx_buffer[i], Rx_buffer[i]);error=1;break;}}if(!error){Uart_Printf("\nThe Tx_buffer is same to Rx_buffer!\n");Uart_Printf("SD CARD Write and Read test is OK!\n");}}void View_Tx_buf(void){}int SD_card_init(void)//SD卡初始化{//-- SD controller & card initializeint i;/* Important notice for MMC test condition *//* Cmd & Data lines must be enabled by pull up resister */rSDIPRE=PCLK/(INICLK)-1;// 400KHzUart_Printf("Init. Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));rSDICON=(1<<4)|1;//先传高位,再传低位,使能CLKrSDIFSTA=rSDIFSTA|(1<<16);//SDI FIFO status register,FIFO 复位rSDIBSIZE=0x200;// SDI block size register,设置每块大小为512byte(128word)rSDIDTIMER=0x7fffff;// SDI data / busy timer register,设置超时周期for(i=0;i<0x1000;i++);// 延时,CARD自身初始化需要74个CLKCMD0();//发送CMD0Uart_Printf("In idle\n");//-- Check MMC card OCRif(Chk_MMC_OCR()){Uart_Printf("In MMC ready\n");MMC=1;goto RECMD2;}Uart_Printf("MMC check end!!\n");//-- Check SD card OCRif(Chk_SD_OCR())Uart_Printf("In SD ready\n");else{Uart_Printf("Initialize fail\nNo Card assertion\n");return 0;}RECMD2://检查连接的卡,识别卡的状态rSDICARG=0x0;// CMD2(stuff bit)rSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;//CMD2为长应答并等待应答,开始发//送CMD2,命令卡发回CID寄存器(保存了生产厂家/时间/批号等等),产生RSP2//检查CMD2是否成功发送并收到响应if(!Chk_CMDend(2, 1))goto RECMD2;//CMD2出错,重新发送rSDICSTA=0xa00;// 清除命令和应答结束标志位Uart_Printf("End id\n");RECMD3://--发送CMD3,给卡分配RCA,rSDICARG=MMC<<16;//CMD3参数,MMC:设置RCA, SD:请求发RCArSDICCON=(0x1<<9)|(0x1<<8)|0x43;//CMD3为短应答并等待应答,开始发//送CMD3, MMC(设置RCA,产生RSP1),SD(设置RCA,产生RSP6)//检查CMD3是否成功发送并收到响应if(!Chk_CMDend(3, 1))goto RECMD3;//CMD3出错,重新发送rSDICSTA=0xa00;// 清除命令和应答结束标志位//--Publish RCAif(MMC){RCA=1;rSDIPRE=(PCLK/MMCCLK)-1;Uart_Printf("MMC Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));}else{RCA=( rSDIRSP0 & 0xffff0000 )>>16;//回读RCA,卡被分配RCA 后进入//TransferMODE,准备读写Uart_Printf("RCA=0x%x\n",RCA);rSDIPRE=PCLK/(SDCLK)-1;// Normal clock=25MHzUart_Printf("SD Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));}//--State(stand-by) check//根据SD规范,rSDIRSP0高16位存储RCA,低16位存储CARD的状态if(rSDIRSP0 &0x1e00!=0x600 )// 检查CARD状态,不是处于stand-by 状态goto RECMD3;////未就绪,重新发送CMD3Uart_Printf("In stand-by\n");Card_sel_desel(1);// Selectif(!MMC)//若位SD卡,设置4bit的数据传输模式Set_4bit_bus();else//若位MMC卡,设置1bit的数据传输模式Set_1bit_bus();return 1;}void Card_sel_desel(char sel_desel){//-- Card select or deselectif(sel_desel)//选择该卡{RECMDS7://送CMD7表示选择该卡,准备读写,产生RSP1.rSDICARG=RCA<<16;// CMD7参数(RCA,stuff bit),其中高16位为RCA rSDICCON=(0x1<<9)|(0x1<<8)|0x47;//CMD7为短应答并等待应答,开始发//送CMD7选择该卡,准备读写,产生RSP1//检查CMD7是否成功发送并收到响应if(!Chk_CMDend(7, 1))goto RECMDS7;//出错,重新发送rSDICSTA=0xa00;//清除命令和应答结束标志位//检查是否处于transfer modeif( rSDIRSP0 & 0x1e00!=0x800 )goto RECMDS7;//不处于transfer mode,重新发送CMD7}else//卸载该卡{RECMDD7:rSDICARG=0<<16;// CMD7参数(RCA,stuff bit),其中高16位为RCA rSDICCON=(0x1<<8)|0x47;// 无应答并,并开始发送CMD7 //检查CMD7是否成功if(!Chk_CMDend(7, 0))goto RECMDD7;//失败,重新卸载rSDICSTA=0x800;// //清除命令结束标志位}}void __irq Rd_Int(void)//读中断函数U32 i,status;status=rSDIFSTA;if((status&0x200)== 0x200 )//检查接收FIFO最后是否有数据到来{for(i=(status & 0x7f)/4;i>0;i--){*Rx_buffer++=rSDIDAT;rd_cnt++;}rSDIFSTA=rSDIFSTA&0x200;//清 Rx FIFO Last data Ready标志位}else if((status&0x80)== 0x80 )// 检查Half FULL interrupt标志,只要大于31个字节,就会将该标志置1{for(i=0;i<8;i++){*Rx_buffer++=rSDIDAT;rd_cnt++;}}ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器}void __irq Wt_Int(void)//写中断函数ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器rSDIDAT=*Tx_buffer++;wt_cnt++;if(wt_cnt==128*block){rINTMSK |= BIT_SDI;//屏蔽BIT_SDI中断rSDIDAT=*Tx_buffer;TR_end=1;}}void __irq DMA_end(void){ClearPending(BIT_DMA0);//清零源中断挂起寄存器和中断挂起寄存器TR_end=1;}void Rd_Block(void){U32 mode;int status;rd_cnt=0;Uart_Printf("Block read test[ Polling read ]\n");mode = 0 ;rSDIFSTA=rSDIFSTA|(1<<16);// 复位FIFOif(mode!=2)rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)| (2<<12)|(block <<0);//YH 040220//设置数据控制寄存器:字传输,块数据传输,4bit数据传输,开始数据传输,数据发送模//式,共读block个块rSDICARG=0x0;// CMD17/18地址参数RERDCMD:switch(mode){case POL:if(block<2)// SINGLE_READ写单块{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发//送CMD17单块读命令,开始读,产生RSP1if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;//失败,继续发送}else// MULTI_READ,读多块{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发//送CMD18多块读命令,开始读,产生RSP1 if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;//失败,继续发送}rSDICSTA=0xa00;// 清命令和应答结束标志while(rd_cnt<128*block)// 512块个字节{if((rSDIDSTA&0x20)==0x20)// 是否超时{rSDIDSTA=(0x1<<0x5);// 清超时标志位break;}status=rSDIFSTA;if((status&0x1000)==0x1000)// FIFO非空{*Rx_buffer++=rSDIDAT;rd_cnt++;}}break;case INT:pISR_SDI=(unsigned)Rd_Int;rINTMSK =~(BIT_SDI);//屏蔽除所有其他中断rSDIIMSK=5;// 开启Last & Rx FIFO half 中断.if(block<2)// SINGLE_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发//送CMD17单块读命令,开始读,产生RSP1if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;//失败,继续发送}else// MULTI_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发//送CMD18多块读命令,开始读,产生RSP1 if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;//失败,继续发送}rSDICSTA=0xa00;// 清命令和应答结束标志while(rd_cnt<128*block);rINTMSK |=(BIT_SDI);//屏蔽BIT_SDI中断rSDIIMSK=0;//屏蔽所有中断break;case DMA:pISR_DMA0=(unsigned)DMA_end;rINTMSK =~(BIT_DMA0);rSDIDCON=rSDIDCON|(1<<24);//YH 040227, Burst4 Enable rDISRC0=(int)(SDIDAT);// SDIDATrDISRCC0=(1<<1)+(1<<0);// APB, fixrDIDST0=(U32)(Rx_buffer);// Rx_bufferrDIDSTC0=(0<<1)+(0<<0);// AHB, incrDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+( 2<<24)+(1<<23) +(1<<22)+(2<<20)+128*block;rDMASKTRIG0=(0<<2)+(1<<1)+0;//no-stop, DMA2 channel on, no-swtriggerrSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)| (1<<14)|(2 <<12)|(block<<0);if(block<2)// SINGLE_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;// sht_resp, wait_resp, dat, start, CMD17if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;}else// MULTI_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;// sht_resp, wait_resp, dat, start, CMD18if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;}rSDICSTA=0xa00;// Clear cmd_end(with rsp)while(!TR_end);//Uart_Printf("rSDIFSTA=0x%x\n",rSDIFSTA);rINTMSK |=(BIT_DMA0);TR_end=0;rDMASKTRIG0=(1<<2);//DMA0 stopbreak;default:break;}//-- Check end of DATAif(!Chk_DATend())Uart_Printf("dat error\n");rSDIDCON=rSDIDCON&~(7<<12);rSDIFSTA=rSDIFSTA&0x200;//Clear Rx FIFO Last data Ready, YH 040221 rSDIDSTA=0x10;// Clear data Tx/Rx end detectif(block>1){RERCMD12://--Stop cmd(CMD12)rSDICARG=0x0;//CMD12(stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12 //-- Check end of CMD12if(!Chk_CMDend(12, 1))。

SD卡文件系统读写

SD卡文件系统读写

SD 文件系统SD文件系统SD卡概述1122SD卡通信协议文件系统的实现3344DE2实例55总结一、SD卡概述1、SD卡简介(1)SD卡(Secure Digital Memory Card)是一种基于半导体快闪记忆器的新一代记忆设备。

SD卡数据传送和物理规范由MMC发展而来一、SD卡概述1、SD卡简介(2)特点:大容量、高性能、安全性高。

用途:可用在MP3、移动电话、PDA、数码相机、数码摄像机、电子图书、微型电脑、AV器材等领域。

数据传输速率:SD卡读写速度比MMC卡要快四倍,最大速率可达到10MB/秒。

几种SD卡的区分:普通SD,高速SD,SDHC。

一、 SD 卡概述2、SD 卡内部结构SD 卡由9线接口控制,数写 保 护据线包括:CMD,CLK,DAT0-DAT3。

包括6个寄存器写保护一、SD卡概述3、SD通信模式一个主机一般情况下可以挂多张SD卡,最大10个堆叠的卡。

主机访问模式:SD模式;SPI模式一、SD卡概述4、SD卡通信主机和SD卡之间的通信是通过命令和数据流实现的,如下图所示:命令发送/数据传输二、SD卡通信协议1、SD卡接口可以支持两种操作模式1、SD卡模式2、SPI模式主机系统可以选择以上其中任一模式,SD卡模式允许4线的高速数据传输。

SPI模式允许简单通用的SPI通道接口,这种模式相对于SD模式的不足之处是丧失了速度。

二、SD卡通信协议SD模式(1)SD模式总线连接图二、SD卡通信协议SD模式(2)SD模式针脚定义SD总线允许1线和4线数据信号设置。

二、SD卡通信协议SPI模式(1)SPI模式连接图二、SD卡通信协议SPI模式(2)SPI模式针脚定义注意:SPI模式时,数据信号需要在主机端用10- 100K欧的上拉电阻。

二、SD卡通信协议2、SD模式介绍SD模式下的命令和数据都有一个开始位和结束位。

数据传输格式主要有命令、响应和数据格式。

命令格式命令: 在CMD上传输的用于启动一个操作的比特流由主机发往从机, 可以是点对点也可以是广播的。

SPI模式下SD卡的读写

SPI模式下SD卡的读写

SPI模式下SD卡的读写李书巳【摘要】SD卡具有移动性、体积小、容量大、易保存等许多优点,如今越来越多的被用于生产控制装置。

SD卡支持两种总线模式:SD模式与SPI模式。

SD模式时的数据传输速度与SPI模式要快,但是SD模式的协议复杂,采用单片机对SD 卡进行读写时一般都采用SPI模式。

采用不同的初始化方式可以使SD卡工作于SD模式或SPI模式。

本文以STC12C5A60S2单片机为例详细的介绍了SD卡在SPI模式下的读写操作过程。

【期刊名称】《数字技术与应用》【年(卷),期】2015(000)001【总页数】1页(P76-76)【关键词】SD卡读写;SPI模式;STC12C5A60S2单片机【作者】李书巳【作者单位】沈阳市苏家屯区职业教育中心辽宁沈阳 110102【正文语种】中文【中图分类】TP333.5随着科技的发展SD卡在人们的生活中被广泛的使用,由于SD卡具有移动性、体积小、容量大、易保存等许多优点如今越来越多的被用于生产控制装置。

一些设计开发人员会经常利用单片机对SD卡进行读写操作,下面就本人在SPI模式下SD 卡读写过程中遇到的一些问题与各位读者交流。

以STC12C5A60S2单片机为例,SPI模式下连接方法如图1,其中CS是片选端口为低电平有效,DI是SD卡写入数据端口即单片机输出数据,DO是单片机从SD卡读数据端口,CLK是同步时钟脉冲信号。

通常SD具有两种读写模式,一种是SD模式,SD卡被接通电源后就自动进入SD 模式,SD模式利用四条数据线可以实现数据并行传输,具有较高的传输速率。

但是其通讯协议比较复杂,并且多数单片机没提供专门的接口,如果用软件编写协议会使程序变得繁琐复杂,甚至影响数据传输效率。

另一种是SPI模式,我们在通电后将CS置“1”向SD卡CLK端发送至少74个时钟周期然后将CS置“0”向DI 端发送CMD0复位指令,然后向CLK发送时钟信号等待DO端回复“01H”表示复位成功,此时SD卡已进入SPI模式,并处在空闲状态。

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

SD卡读写包括两种模式:SD模式和SPI模式。

其中SD模式又可以分为1bit 和4bit两种传输模式。

SD卡缺省使用专有的SD模式。

SD卡规范中主要讲了一些命令,响应和CRC效验等等,整个规范的内容还是很多的。

SD卡上电后,卡处于空闲状态,主机发送CMD0复位SD卡,然后通过CMD55和ACMD41判断当前电压是否在卡的工作范围内。

在得到了正确的响应后,主机可以继续通过CMD10读取SD卡的CID寄存器,通过CMD16设置数据块长度,通过CMD9读取卡的CSD寄存器。

从CSD寄存器中,主机可以获知卡容量,支持的命令集等重要参数。

此时,卡以进入了传输状态,主机就可以通过CMD17/18和CMD24/25对卡进行读写。

CRC校验是为了防止SD卡的命令,应答,数据传输出现错误。

每个命令和应答信号都会产生CRC效验码,每个数据块的传输也会长生CRC效验码。

这段程序是友善之臂推出的mini2440开发板中带的ADS测试源码。

整个阅读代码的过程是对这S3C2440的芯片手册和SD卡规范来看的,对于MMC卡没有给出注释,其实和SD卡是大同小异。

由于是初次接触ARM,对SD规范的认识也不是很深入,再加上自己水平有限,还不能完全读懂源代码,其中的肯定存在一些错误,欢迎大家一起交流讨论。

#define INT 1#define DMA 2int CMD13(void);// Send card statusint CMD9(void);unsigned int*Tx_buffer;//128[word]*16[blk]=8192[byte] unsigned int*Rx_buffer;//128[word]*16[blk]=8192[byte] volatile unsigned int rd_cnt;//读数据计数器volatile unsigned int wt_cnt;//写数据计数器volatile unsigned int block;//读写块总数volatile unsigned int TR_end=0;int Wide=0;// 0:1bit, 1:4bitint MMC=0;// 0:SD , 1:MMCint Maker_ID;char Product_Name[7];int Serial_Num;volatile int RCA;void Test_SDI(void){U32 save_rGPEUP, save_rGPECON;RCA=0;MMC=0;block=3072;//3072Blocks=1.5MByte,((2Block=1024Byte)*1024Block=1MByte)save_rGPEUP=rGPEUP;save_rGPECON=rGPECON;//**配置SD/MMC控制器rGPEUP = 0xf83f;// SDCMD, SDDAT[3:0] => PU En. rGPECON = 0xaaaaaaaa;//SDCMD, SDDAT[3:0]Uart_Printf("\nSDI Card Write and Read Test\n");if(!SD_card_init())//等待SD卡初始化完成return;TR_Buf_new();//发送数据缓冲区初始化Wt_Block();//写卡Rd_Block();//读卡View_Rx_buf();if(MMC)TR_Buf_new();if(MMC){rSDICON |=(1<<5);// YH 0519, MMC Type SDCLKWt_Stream();Rd_Stream();View_Rx_buf();}Card_sel_desel(0);// Card deselectif(!CMD9())Uart_Printf("Get CSD fail!!!\n");rSDIDCON=0;//tark???rSDICSTA=0xffff;rGPEUP=save_rGPEUP;rGPECON=save_rGPECON;}void TR_Buf_new(void)//发送数据缓冲区初始化{//-- Tx & Rx Buffer initializeint i, j;Tx_buffer=(unsigned int*)0x31000000;j=0;for(i=0;i<2048;i++)//128[word]*16[blk]=8192[byte]*(Tx_buffer+i)=i+j;Flush_Rx_buf();}void Flush_Rx_buf(void)//接收数据缓冲区清0{//-- Flushing Rx bufferint i;Rx_buffer=(unsigned int*)0x31800000;for(i=0;i<2048;i++)//128[word]*16[blk]=8192[byte]*(Rx_buffer+i)=0;Uart_Printf("End Rx buffer flush\n");}void View_Rx_buf(){//-- Display Rx bufferint i,error=0;Tx_buffer=(unsigned int*)0x31000000;Rx_buffer=(unsigned int*)0x31800000;Uart_Printf("Check Rx data\n");for(i=0;i<128*block;i++){if(Rx_buffer[i]!= Tx_buffer[i]){Uart_Printf("\nTx/Rx error\n");Uart_Printf("%d:Tx-0x%08x, Rx-0x%08x\n",i,Tx_buffer[i], Rx_buffer[i]);error=1;break;}}if(!error){Uart_Printf("\nThe Tx_buffer is same to Rx_buffer!\n");Uart_Printf("SD CARD Write and Read test is OK!\n");}}void View_Tx_buf(void){}int SD_card_init(void)//SD卡初始化{//-- SD controller & card initializeint i;/* Important notice for MMC test condition *//* Cmd & Data lines must be enabled by pull up resister */rSDIPRE=PCLK/(INICLK)-1;// 400KHzUart_Printf("Init. Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));rSDICON=(1<<4)|1;//先传高位,再传低位,使能CLKrSDIFSTA=rSDIFSTA|(1<<16);//SDI FIFO status register,FIFO复位rSDIBSIZE=0x200;// SDI block size register,设置每块大小为512byte(128word)rSDIDTIMER=0x7fffff;// SDI data / busy timer register,设置超时周期for(i=0;i<0x1000;i++);// 延时,CARD自身初始化需要74个CLKCMD0();//发送CMD0Uart_Printf("In idle\n");//-- Check MMC card OCRif(Chk_MMC_OCR()){Uart_Printf("In MMC ready\n");MMC=1;goto RECMD2;}Uart_Printf("MMC check end!!\n");//-- Check SD card OCRif(Chk_SD_OCR())Uart_Printf("In SD ready\n");else{Uart_Printf("Initialize fail\nNo Card assertion\n");return 0;}RECMD2://检查连接的卡,识别卡的状态rSDICARG=0x0;// CMD2(stuff bit)rSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;//CMD2为长应答并等待应答,开始发//送CMD2,命令卡发回CID寄存器(保存了生产厂家/时间/批号等等),产生RSP2//检查CMD2是否成功发送并收到响应if(!Chk_CMDend(2, 1))goto RECMD2;//CMD2出错,重新发送rSDICSTA=0xa00;// 清除命令和应答结束标志位Uart_Printf("End id\n");RECMD3://--发送CMD3,给卡分配RCA,rSDICARG=MMC<<16;//CMD3参数, MMC:设置 RCA, SD:请求发RCArSDICCON=(0x1<<9)|(0x1<<8)|0x43;//CMD3为短应答并等待应答,开始发//送CMD3, MMC(设置RCA,产生RSP1),SD(设置RCA,产生RSP6)//检查CMD3是否成功发送并收到响应if(!Chk_CMDend(3, 1))goto RECMD3;//CMD3出错,重新发送rSDICSTA=0xa00;// 清除命令和应答结束标志位//--Publish RCAif(MMC){RCA=1;rSDIPRE=(PCLK/MMCCLK)-1;Uart_Printf("MMC Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));}else{RCA=( rSDIRSP0 & 0xffff0000 )>>16;//回读RCA,卡被分配RCA后进入//TransferMODE,准备读写Uart_Printf("RCA=0x%x\n",RCA);rSDIPRE=PCLK/(SDCLK)-1;// Normal clock=25MHzUart_Printf("SD Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));}//--State(stand-by) check//根据SD规范,rSDIRSP0高16位存储RCA,低16位存储CARD的状态if(rSDIRSP0 &0x1e00!=0x600 )// 检查CARD状态,不是处于stand-by 状态goto RECMD3;////未就绪,重新发送CMD3Uart_Printf("In stand-by\n");Card_sel_desel(1);// Selectif(!MMC)//若位SD卡,设置4bit的数据传输模式Set_4bit_bus();else//若位MMC卡,设置1bit的数据传输模式Set_1bit_bus();return 1;}void Card_sel_desel(char sel_desel){//-- Card select or deselectif(sel_desel)//选择该卡{RECMDS7://送CMD7表示选择该卡,准备读写,产生RSP1.rSDICARG=RCA<<16;// CMD7参数(RCA,stuff bit),其中高16位为RCA rSDICCON=(0x1<<9)|(0x1<<8)|0x47;//CMD7为短应答并等待应答,开始发//送CMD7选择该卡,准备读写,产生RSP1//检查CMD7是否成功发送并收到响应if(!Chk_CMDend(7, 1))goto RECMDS7;//出错,重新发送rSDICSTA=0xa00;//清除命令和应答结束标志位//检查是否处于transfer modeif( rSDIRSP0 & 0x1e00!=0x800 )goto RECMDS7;//不处于transfer mode,重新发送CMD7}else//卸载该卡{RECMDD7:rSDICARG=0<<16;// CMD7参数(RCA,stuff bit),其中高16位为RCA rSDICCON=(0x1<<8)|0x47;// 无应答并,并开始发送CMD7//检查CMD7是否成功if(!Chk_CMDend(7, 0))goto RECMDD7;//失败,重新卸载rSDICSTA=0x800;// //清除命令结束标志位}}void __irq Rd_Int(void)//读中断函数U32 i,status;status=rSDIFSTA;if((status&0x200)== 0x200 )//检查接收FIFO最后是否有数据到来{for(i=(status & 0x7f)/4;i>0;i--){*Rx_buffer++=rSDIDAT;rd_cnt++;}rSDIFSTA=rSDIFSTA&0x200;//清 Rx FIFO Last data Ready标志位}else if((status&0x80)== 0x80 )// 检查Half FULL interrupt标志,只要大于31个字节,就会将该标志置1{for(i=0;i<8;i++){*Rx_buffer++=rSDIDAT;rd_cnt++;}}ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器}void __irq Wt_Int(void)//写中断函数ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器rSDIDAT=*Tx_buffer++;wt_cnt++;if(wt_cnt==128*block){rINTMSK |= BIT_SDI;//屏蔽BIT_SDI中断rSDIDAT=*Tx_buffer;TR_end=1;}}void __irq DMA_end(void){ClearPending(BIT_DMA0);//清零源中断挂起寄存器和中断挂起寄存器TR_end=1;}void Rd_Block(void){U32 mode;int status;rd_cnt=0;Uart_Printf("Block read test[ Polling read ]\n");mode = 0 ;rSDIFSTA=rSDIFSTA|(1<<16);// 复位FIFOif(mode!=2)rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(block <<0);//YH 040220//设置数据控制寄存器:字传输,块数据传输,4bit数据传输,开始数据传输,数据发送模//式,共读block个块rSDICARG=0x0;// CMD17/18地址参数RERDCMD:switch(mode){case POL:if(block<2)// SINGLE_READ写单块{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发//送CMD17单块读命令,开始读,产生RSP1if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;//失败,继续发送}else// MULTI_READ,读多块{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发//送CMD18多块读命令,开始读,产生RSP1if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;//失败,继续发送}rSDICSTA=0xa00;// 清命令和应答结束标志while(rd_cnt<128*block)// 512块个字节{if((rSDIDSTA&0x20)==0x20)// 是否超时{rSDIDSTA=(0x1<<0x5);// 清超时标志位break;}status=rSDIFSTA;if((status&0x1000)==0x1000)// FIFO非空{*Rx_buffer++=rSDIDAT;rd_cnt++;}}break;case INT:pISR_SDI=(unsigned)Rd_Int;rINTMSK =~(BIT_SDI);//屏蔽除所有其他中断rSDIIMSK=5;// 开启Last & Rx FIFO half 中断.if(block<2)// SINGLE_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发//送CMD17单块读命令,开始读,产生RSP1if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;//失败,继续发送}else// MULTI_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发//送CMD18多块读命令,开始读,产生RSP1if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;//失败,继续发送}rSDICSTA=0xa00;// 清命令和应答结束标志while(rd_cnt<128*block);rINTMSK |=(BIT_SDI);//屏蔽BIT_SDI中断rSDIIMSK=0;//屏蔽所有中断break;case DMA:pISR_DMA0=(unsigned)DMA_end;rINTMSK =~(BIT_DMA0);rSDIDCON=rSDIDCON|(1<<24);//YH 040227, Burst4 EnablerDISRC0=(int)(SDIDAT);// SDIDATrDISRCC0=(1<<1)+(1<<0);// APB, fixrDIDST0=(U32)(Rx_buffer);// Rx_bufferrDIDSTC0=(0<<1)+(0<<0);// AHB, incrDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23) +(1<<22)+(2<<20)+128*block;rDMASKTRIG0=(0<<2)+(1<<1)+0;//no-stop, DMA2 channel on, no-swtriggerrSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(2 <<12)|(block<<0);if(block<2)// SINGLE_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x51;// sht_resp, wait_resp, dat, start, CMD17if(!Chk_CMDend(17, 1))//-- Check end of CMD17goto RERDCMD;}else// MULTI_READ{rSDICCON=(0x1<<9)|(0x1<<8)|0x52;// sht_resp, wait_resp, dat, start, CMD18if(!Chk_CMDend(18, 1))//-- Check end of CMD18goto RERDCMD;}rSDICSTA=0xa00;// Clear cmd_end(with rsp)while(!TR_end);//Uart_Printf("rSDIFSTA=0x%x\n",rSDIFSTA);rINTMSK |=(BIT_DMA0);TR_end=0;rDMASKTRIG0=(1<<2);//DMA0 stopbreak;default:break;}//-- Check end of DATAif(!Chk_DATend())Uart_Printf("dat error\n");rSDIDCON=rSDIDCON&~(7<<12);rSDIFSTA=rSDIFSTA&0x200;//Clear Rx FIFO Last data Ready, YH 040221 rSDIDSTA=0x10;// Clear data Tx/Rx end detectif(block>1){RERCMD12://--Stop cmd(CMD12)rSDICARG=0x0;//CMD12(stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12 //-- Check end of CMD12if(!Chk_CMDend(12, 1))goto RERCMD12;rSDICSTA=0xa00;// Clear cmd_end(with rsp)}}void Rd_Stream(void)// only for MMC, 3blk read{int status, rd_cnt=0;if(MMC!=1){Uart_Printf("Stream read command supports only MMC!\n"); return;}Uart_Printf("\n[Stream read test]\n");RECMD11:rSDIDCON=(2<<22)|(1<<19)|(0<<17)|(0<<16)|(1<<14)|(2<<12);rSDICARG=0x0;// CMD11(addr)rSDICCON=(0x1<<9)|(0x1<<8)|0x4b;//sht_resp, wait_resp, dat, start, CMD11while(rd_cnt<128*block){if((rSDIDSTA&0x20)== 0x20 ){Uart_Printf("Rread timeout error");return;}status=rSDIFSTA;if((status&0x1000)==0x1000){//*Rx_buffer++=rSDIDAT;//rd_cnt++;Rx_buffer[rd_cnt++]=rSDIDAT;}}//-- Check end of CMD11if(!Chk_CMDend(11, 1))goto RECMD11;rSDICSTA=0xa00;// Clear cmd_end(with rsp)//-- Check end of DATArSDIDCON=(2<<22)|(1<<19)|(0<<17)|(0<<16);//YH 040220rSDIDCON=rSDIDCON&~(7<<12);//YH 040220, no operation, data readywhile( rSDIDSTA&0x3 !=0x0 );if(rSDIDSTA!=0)Uart_Printf("rSDIDSTA=0x%x\n", rSDIDSTA);rSDIDSTA=0xff;//YH 040221STRCMD12://--Stop cmd(CMD12)rSDICARG=0x0;//CMD12(stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12//-- Check end of CMD12if(!Chk_CMDend(12, 1))goto STRCMD12;rSDICSTA=0xa00;// Clear cmd_end(with rsp)rSDIFSTA=rSDIFSTA&0x200;//Clear Rx FIFO Last data Ready, YH 040221 Uart_Printf("rSDIFSTA1=0x%x\n", rSDIFSTA);//YH 040221rSDIFSTA=rSDIFSTA&0x200;//Clear Rx FIFO Last data Ready, YH 040221Uart_Printf("rSDIFSTA2=0x%x\n", rSDIFSTA);//YH 040221Uart_Printf("\n--End stream read test\n");}void Wt_Block(void){U32 mode;int status;wt_cnt=0;Uart_Printf("Block write test[ Polling write ]\n");mode = 0 ;rSDIFSTA=rSDIFSTA|(1<<16);//复位FIFOif(mode!=2)rSDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(block <<0);//设置数据控制寄存器:字传输,块数据传输,4bit数据传输,开始数据传输,数据发送模//式,共写block个块rSDICARG=0x0;// CMD24/25地址参数REWTCMD:switch(mode){case POL:if(block<2)// SINGLE_WRITE,写单块{rSDICCON=(0x1<<9)|(0x1<<8)|0x58;//CMD24为短应答并等待应答,开始发//送CMD24单块写命令,开始写,产生RSP1if(!Chk_CMDend(24, 1))//-- Check end of CMD24goto REWTCMD;//命令发送失败}else// MULTI_WRITE,写多块{rSDICCON=(0x1<<9)|(0x1<<8)|0x59;//CMD25为短应答并等待应答,开发//送CMD25多块写命令,开始读写,产生RSP1if(!Chk_CMDend(25, 1))//-- Check end of CMD25goto REWTCMD;//命令发送失败}rSDICSTA=0xa00;// 清命令和应答结束标志while(wt_cnt<128*block){status=rSDIFSTA;if((status&0x2000)==0x2000)//FIFO未满{rSDIDAT=*Tx_buffer++;wt_cnt++;//Uart_Printf("Block No.=%d, wt_cnt=%d\n",block,wt_cnt);}}break;case INT:pISR_SDI=(unsigned)Wt_Int;rINTMSK =~(BIT_SDI);rSDIIMSK=0x10;// Tx FIFO half int.if(block<2)// SINGLE_WRITE{rSDICCON=(0x1<<9)|(0x1<<8)|0x58;//sht_resp, wait_resp, dat, start, CMD24if(!Chk_CMDend(24, 1))//-- Check end of CMD24goto REWTCMD;}else// MULTI_WRITE{rSDICCON=(0x1<<9)|(0x1<<8)|0x59;//sht_resp, wait_resp, dat, start, CMD25if(!Chk_CMDend(25, 1))//-- Check end of CMD25goto REWTCMD;}rSDICSTA=0xa00;// Clear cmd_end(with rsp)while(!TR_end);//while(wt_cnt<128);rINTMSK |=(BIT_SDI);TR_end=0;rSDIIMSK=0;// All maskbreak;case DMA:pISR_DMA0=(unsigned)DMA_end;rINTMSK =~(BIT_DMA0);rSDIDCON=rSDIDCON|(1<<24);//YH 040227, Burst4 EnablerDISRC0=(int)(Tx_buffer);// Tx_bufferrDISRCC0=(0<<1)+(0<<0);// AHB, incrDIDST0=(U32)(SDIDAT);// SDIDATrDIDSTC0=(1<<1)+(1<<0);// APB, fixrDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23) +(1<<22)+(2<<20)+128*block;//handshake, sync PCLK, TC int, single tx, single service, SDI, H/W request,//auto-reload off, word, 128blk*numrDMASKTRIG0=(0<<2)+(1<<1)+0;//no-stop, DMA0 channel on, no-swtriggerrSDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(3<<1 2)|(block<<0);//YH 040220// Word Tx, Tx after rsp, blk, 4bit bus, dma enable, Tx start, blk numif(block<2)// SINGLE_WRITE{rSDICCON=(0x1<<9)|(0x1<<8)|0x58;//sht_resp, wait_resp, dat, start, CMD24if(!Chk_CMDend(24, 1))//-- Check end of CMD24goto REWTCMD;}else// MULTI_WRITE{rSDICCON=(0x1<<9)|(0x1<<8)|0x59;//sht_resp, wait_resp, dat, start, CMD25if(!Chk_CMDend(25, 1))//-- Check end of CMD25goto REWTCMD;}rSDICSTA=0xa00;// Clear cmd_end(with rsp)while(!TR_end);rINTMSK |=(BIT_DMA0);TR_end=0;rDMASKTRIG0=(1<<2);//DMA0 stopbreak;default:break;}//-- Check end of DATAif(!Chk_DATend())Uart_Printf("dat error\n");rSDIDCON=rSDIDCON&~(7<<12);//YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer startrSDIDSTA=0x10;// Clear data Tx/Rx endif(block>1){//--Stop cmd(CMD12)REWCMD12:rSDIDCON=(1<<18)|(1<<17)|(0<<16)|(1<<14)|(1<<12)|(block<<0);//YH 040220rSDICARG=0x0;//CMD12(stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12 //-- Check end of CMD12if(!Chk_CMDend(12, 1))goto REWCMD12;rSDICSTA=0xa00;// Clear cmd_end(with rsp)//-- Check end of DATA(with busy state)if(!Chk_BUSYend())Uart_Printf("error\n");rSDIDSTA=0x08;//! Should be cleared by writing '1'.}}void Wt_Stream(void)// only for MMC, 3blk write{int status, wt_cnt=0;if(MMC!=1){Uart_Printf("Stream write command supports only MMC!\n");return;}Uart_Printf("\n[Stream write test]\n");RECMD20:rSDIDCON=(2<<22)|(1<<20)|(0<<17)|(0<<16)|(1<<14)|(3<<12);// stream moderSDICARG=0x0;// CMD20(addr)rSDICCON=(0x1<<9)|(0x1<<8)|0x54;//sht_resp, wait_resp, dat, start, CMD20//-- Check end of CMD25if(!Chk_CMDend(20, 1))goto RECMD20;rSDICSTA=0xa00;// Clear cmd_end(with rsp)while(wt_cnt<128*block){status=rSDIFSTA;if((status&0x2000)==0x2000)rSDIDAT=Tx_buffer[wt_cnt++];}//-- Check end of DATAwhile( rSDIFSTA&0x400 );Delay(10);// for the empty of DATA line(Hardware)rSDIDCON=(1<<20)|(0<<17)|(0<<16);//YH 040220rSDIDCON=rSDIDCON&~(7<<12);//YH 040220, no operation, data readywhile((rSDIDSTA&0x3)!=0x0 );if(rSDIDSTA!=0x0)Uart_Printf("rSDIDSTA=0x%x\n", rSDIDSTA);rSDIDSTA=0xff;//Clear rSDIDSTASTWCMD12://--Stop cmd(CMD12)rSDIDCON=(1<<18)|(1<<17)|(0<<16)|(1<<14)|(1<<12);rSDICARG=0x0;//CMD12(stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12//-- Check end of CMD12if(!Chk_CMDend(12, 1))goto STWCMD12;rSDICSTA=0xa00;// Clear cmd_end(with rsp)//-- Check end of DATA(with busy state)if(!Chk_BUSYend())Uart_Printf("error\n");rSDIDSTA=0x08;Uart_Printf("\n--End Stream write test\n");}int Chk_CMDend(int cmd,int be_resp)//0: Timeout{int finish0;if(!be_resp)// 没有应答信号{finish0=rSDICSTA;//读取SDI command status register,while((finish0&0x800)!=0x800)// 等待命令结束finish0=rSDICSTA;rSDICSTA=finish0;// 清命令结束标志return 1;//成功,返回1}else// 有应答信号{finish0=rSDICSTA;//读取SDI command status register,while(!(((finish0&0x200)==0x200)|((finish0&0x400)==0x400)))//检查超时和应答信号finish0=rSDICSTA;if(cmd==1 | cmd==41)// CRC no check, CMD9 is a long Resp. command.{if((finish0&0xf00)!= 0xa00 )// 命令,应答有错,或超时{rSDICSTA=finish0;// 清错误标志if(((finish0&0x400)==0x400))// 若超时,返回0return 0;}rSDICSTA=finish0;// 清命令和应答结束标志}else// 进行CRC效验{if((finish0&0x1f00)!= 0xa00 )// CRC效验出错{Uart_Printf("CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);//输出对应寄存器的值rSDICSTA=finish0;// 清除错误标志位if(((finish0&0x400)==0x400))// 若超时,返回0return 0;}rSDICSTA=finish0;}return 1;}}int Chk_DATend(void){int finish;finish=rSDIDSTA;while(!(((finish&0x10)==0x10)|((finish&0x20)==0x20)))// 检查数据结束和超时位finish=rSDIDSTA;if((finish&0xfc)!= 0x10 )//数据传输结束{Uart_Printf("DATA:finish=0x%x\n", finish);rSDIDSTA=0xec;//清除错误标志return 0;}return 1;}int Chk_BUSYend(void){int finish;finish=rSDIDSTA;while(!(((finish&0x08)==0x08)|((finish&0x20)==0x20)))//检查忙标志位finish=rSDIDSTA;if((finish&0xfc)!= 0x08 ){Uart_Printf("DATA:finish=0x%x\n", finish);rSDIDSTA=0xf4;//清除错误标志return 0;}return 1;}void CMD0(void)//CMD0用于对SD实现软件复位,不论卡处于何种状态,使SD卡处于//空闲状态,等待下一个命令的到来{//-- Make card idle staterSDICARG=0x0;// ,CMD0(stuff bit)rSDICCON=(1<<8)|0x40;// 不等待应答信号,命令开始//并再次发送CMD0 关于cmd0定义:0(start_bit)1(cmd标志)000000(6位cmd编//码)后面是参数(无参数就全0)//-- Check end of CMD0Chk_CMDend(0, 0);// 检查命令是否成功发送rSDICSTA=0x800;// 清除命令结束标志}int Chk_MMC_OCR(void){int i;//-- MMC卡识别的等待操作, 使卡处于空闲状态for(i=0;i<100;i++)//等待的时间取决于厂商{// rSDICARG=0xffc000; //CMD1(MMC OCR:2.6V~3.6V),设置工作电压rSDICARG=0xff8000;//CMD1(SD OCR:2.7V~3.6V),设置工作电压rSDICCON=(0x1<<9)|(0x1<<8)|0x41;//CMD1为短应答并等待应答,开始发送CMD1//-- 检查CMD1是否发送成功,并检查卡状态// if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ffc000) //31:忙状态标志位,0表示忙//0xffc000为卡的正常工作电压范围if(Chk_CMDend(1, 1)&&(rSDIRSP0>>16)==0x80ff)//卡处于空闲// if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ff8000)rSDICSTA=0xa00;// 清除命令和应答结束标志位return 1;// 成功}}rSDICSTA=0xa00;//清除命令和应答结束标志位return 0;// 失败}int Chk_SD_OCR(void){int i;//-- SD卡识别的等待操作, 使卡处于空闲状态for(i=0;i<50;i++)// 如果这段时间太短,SD卡的初始化可能会失败{CMD55();//送CMD55,表示下个命令将是特殊功能命令acmd,而非一般命令cmdrSDICARG=0xff8000;//ACMD41(SD OCR:2.7V~3.6V) ,设置工作电压// rSDICARG=0xffc000;//ACMD41(MMC OCR:2.6V~3.6V)设置工作电压rSDICCON=(0x1<<9)|(0x1<<8)|0x69;// ACMD41为短应答并等待应答,开始发//送ACMD41,命令卡发回OCR寄存器(保存了电压参数/busy信号等等),产生//-- 检查ACMD41是否发送成功,并检查卡状态if( Chk_CMDend(41, 1)& rSDIRSP0==0x80ff8000 )//发送成功并且卡处于空闲状态{rSDICSTA=0xa00;//清除命令和应答结束标志位return 1;//成功}Delay(200);//等待卡上电后处于空闲状态}//Uart_Printf("SDIRSP0=0x%x\n",rSDIRSP0);rSDICSTA=0xa00;//清除命令和应答结束标志位return 0;// 失败}int CMD55(void){//CMD55,表示下个命令将是特殊功能acmd,而非一般命令cmdrSDICARG=RCA<<16;//CMD55(RCA,stuff bit)rSDICCON=(0x1<<9)|(0x1<<8)|0x77;//CMD55为短应答(R1)并等待应答,并开始发送CMD55//-- 检查CMD55是成功发送if(!Chk_CMDend(55, 1))return 0;//出错,返回rSDICSTA=0xa00;////清除命令和应答结束标志位return 1;}int CMD13(void)//送CMD13,命令卡的当前状态{int response0;rSDICARG=RCA<<16;// CMD13(RCA,stuff bit),高16位为RCArSDICCON=(0x1<<9)|(0x1<<8)|0x4d;//CMD13为短应答(R1)并等待应答,并开始发送CMD13//-- Check end of CMD13if(!Chk_CMDend(13, 1))//-- 检查CMD13是成功发送return 0;//出错,返回//Uart_Printf("rSDIRSP0=0x%x\n", rSDIRSP0);if(rSDIRSP0&0x100)//数据是否就绪//Uart_Printf("Ready for Data\n");// else//Uart_Printf("Not Ready\n");response0=rSDIRSP0;response0 &= 0x3c00;response0 = response0 >> 9;//Uart_Printf("Current Status=%d\n", response0);if(response0==6)//卡处于receive data stateTest_SDI();rSDICSTA=0xa00;//清除命令和应答结束标志位return 1;}int CMD9(void)//送CMD9,命令卡发回CSD寄存器(保存了读写参数/卡的容量等内容),产生RSP2{rSDICARG=RCA<<16;// CMD9参数,高16位为RCArSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x49;//CMD9为长应答并等待应答,开始发//送CMD9,产生RSP2Uart_Printf("\nCSD register :\n");//-- Check end of CMD9if(!Chk_CMDend(9, 1))// 检查命令是否成功发送return 0;//失败则返回Uart_Printf("SDIRSP0=0x%x\nSDIRSP1=0x%x\nSDIRSP2=0x%x\nSDIRSP3= 0x%x\n", rSDIRSP0,rSDIRSP1,rSDIRSP2,rSDIRSP3);return 1;}void Set_1bit_bus(void)//设置1位数据线{Wide=0;if(!MMC)SetBus();//Uart_Printf("\n****1bit bus****\n");}void Set_4bit_bus(void)//设置4位数据线{Wide=1;SetBus();//Uart_Printf("\n****4bit bus****\n");}void SetBus(void)//设置数据线宽度{SET_BUS:CMD55();//CMD55,表示下个命令将是特殊功能acmd,而非一般命令cmdrSDICARG=Wide<<1;//数据宽度00: 1bit, 10: 4bitrSDICCON=(0x1<<9)|(0x1<<8)|0x46;//ACMD6为短应答(R1)并等待应答,并开始发送// ACMD6设置数据线宽度位4bitif(!Chk_CMDend(6, 1))// 设置失败,则重新设置goto SET_BUS;rSDICSTA=0xa00;//清除命令和应答结束标志位}void Set_Prt(void)//写保护{//-- Set protection addr.0 ~ 262144(32*16*512)Uart_Printf("[Set protection(addr.0 ~ 262144) test]\n"); RECMD28://--Make ACMDrSDICARG=0;// CMD28(addr)rSDICCON=(0x1<<9)|(0x1<<8)|0x5c;//sht_resp, wait_resp, start, CMD28//-- Check end of CMD28if(!Chk_CMDend(28, 1))goto RECMD28;rSDICSTA=0xa00;// Clear cmd_end(with rsp)}void Clr_Prt(void)//清除写保护{//-- Clear protection addr.0 ~ 262144(32*16*512)//Uart_Printf("[Clear protection(addr.0 ~ 262144) test]\n");RECMD29://--Make ACMDrSDICARG=0;// CMD29(addr)rSDICCON=(0x1<<9)|(0x1<<8)|0x5d;//sht_resp, wait_resp, start, CMD29//-- Check end of CMD29。

相关文档
最新文档