下载
加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 SD卡读写操作__SD卡电路

SD卡读写操作__SD卡电路.doc

SD卡读写操作__SD卡电路

梁江蓉
2018-08-08 0人阅读 举报 0 0 暂无简介

简介:本文档为《SD卡读写操作__SD卡电路doc》,可适用于IT/计算机领域

SD卡读写操作SD卡电路SD卡在现在的日常生活与工作中使用非常广泛时下已经成为最为通用的数据存储卡。在诸如MP、数码相机等设备上也都采用SD卡作为其存储设备。SD卡之所以得到如此广泛的使用是因为它价格低廉、存储容量大、使用方便、通用性与安全性强等优点。既然它有着这么多优点那么如果将它加入到单片机应用开发系统中来将使系统变得更加出色。这就要求对SD卡的硬件与读写时序进行研究。对于SD卡的硬件结构在官方的文档上有很详细的介绍如SD卡内的存储器结构、存储单元组织方式等内容。要实现对它的读写最核心的是它的时序笔者在经过了实际的测试后使用单片机成功实现了对SD卡的扇区读写并对其读写速度进行了评估。下面先来讲解SD卡的读写时序。()SD卡的引脚定义:SD卡引脚功能详述:引脚SD模式(WYF:口)SPI模式(WYF:口)编号名称类型描述名称类型描述IO或PP卡检测数据线片选#CSICDDAT命令回应数据输入PPDIICMD电源地电源地SVSSSVSS电源电源SVDDSVDD时钟时钟ISCLKICLK电源地电源地SVSSSVSSIO或PP数据线O或PP数据输出DODATIO或PP数据线RSVDATIO或PP数据线RSVDAT注:S:电源供给I:输入O:采用推拉驱动的输出PP:采用推拉驱动的输入输出SD卡SPI模式下与单片机的连接图:SD卡支持两种总线方式:SD方式与SPI方式。其中SD方式采用线制使用CLK、CMD、DAT~DAT进行数据通信。而SPI方式采用线制使用CS、CLK、DataIn、DataOut进行数据通信。SD方式时的数据传输速度与SPI方式要快采用单片机对SD卡进行读写时一般都采用SPI模式。采用不同的初始化方式可以使SD卡工作于SD方式或SPI方式。这里只对其SPI方式进行介绍。()SPI方式驱动SD卡的方法SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。从应用的角度来看采用SPI接口的好处在于很多单片机内部自带SPI控制器不光给开发上带来方便同时也见降低了开发成本。然而它也有不好的地方如失去了SD卡的性能优势要解决这一问题就要用SD方式因为它提供更大的总线数据带宽。SPI接口的选用是在上电初始时向其写入第一个命令时进行的。以下介绍SD卡的驱动方法只实现简单的扇区读写。)命令与数据传输命令传输SD卡自身有完备的命令系统以实现各项操作。命令格式如下:命令的传输过程采用发送应答机制过程如下:每一个命令都有自己命令应答格式。在SPI模式中定义了三种应答格式如下表所示:字节位含义字节位含义开始位始终为开始位始终为参数错误参数错误地址错误地址错误擦除序列错误擦除序列错误CRC错误CRC错误非法命令非法命令擦除复位擦除复位闲置状态闲置状态溢出CSD覆盖擦除参数字节位含义写保护非法开始位始终为卡ECC失败参数错误卡控制器错误地址错误未知错误擦除序列错误写保护擦除跳过锁,解锁失败CRC错误锁卡非法命令擦除复位闲置状态,全操作条件寄存器部高位在前写命令的例程:向SD卡中写入命令并返回回应的第二个字节unsignedcharWriteCommandSD(unsignedchar*CMD){unsignedchartmpunsignedcharretry=unsignedchariSPICS=禁止SD卡片选WriteByteSD(xFF)发送个时钟信号SPICS=使能SD卡片选向SD卡发送字节命令for(i=i<xi){WriteByteSD(*CMD)}获得位的回应ReadByteSD()readthefirstbyte,ignoreitdo{读取后位tmp=ReadByteSD()retry}while((tmp==xff)(retry<))return(tmp)})初始化SD卡的初始化是非常重要的只有进行了正确的初始化才能进行后面的各项操作。在初始化过程中SPI的时钟不能太快否则会造初始化失败。在初始化成功后应尽量提高SPI的速率。在刚开始要先发送至少个时钟信号这是必须的。在很多读者的实验中很多是因为疏忽了这一点而使初始化不成功。随后就是写入两个命令CMD与CMD使SD卡进入SPI模式初始化时序图:初始化例程:初始化SD卡到SPI模式unsignedcharSDInit(){unsignedcharretry,tempunsignedchariunsignedcharCMD={x,x,x,x,x,x}SDPortInit()初始化驱动端口InitFlag=将初始化标志置for(i=i<xfi){WriteByteSD(xff)发送至少个时钟信号}向SD卡发送CMDretry=do{为了能够成功写入CMD,在这里写次temp=WriteCommandSD(CMD)retryif(retry==){超过次return(INITCMDERROR)CMDError!}}while(temp!=)回应h停止写入发送CMD到SD卡CMD=xCMDCMD=xFFretry=do{为了能成功写入CMD,写次temp=WriteCommandSD(CMD)retryif(retry==){超过次return(INITCMDERROR)CMDError!}}while(temp!=)回应h停止写入InitFlag=初始化完毕初始化标志清零SPICS=片选无效return()初始化成功})读取CIDCID寄存器存储了SD卡的标识码。每一个卡都有唯一的标识码。CID寄存器长度为位。它的寄存器结构如下:WYF:字节*位=位名称域数据宽度CID划分生产标识号MID:OEM应用标识OID:产品名称PNM:产品版本PRV:产品序列号PSN:保留,:生产日期MDT:CRC校验合CRC:未使用始终为,:它的读取时序如下:与此时序相对应的程序如下:读取SD卡的CID寄存器字节成功返回unsignedcharReadCIDSD(unsignedchar*Buffer){读取CID寄存器的命令unsignedcharCMD={xA,x,x,x,x,xFF}unsignedchartemptemp=SDReadBlock(CMD,Buffer,)readbytesreturn(temp)})读取CSDWYF:共字节位CSD(CardSpecificData)寄存器提供了读写SD卡的一些信息。其中的一些单元可以由用户重新编程。具体的CSD结构如下:名称域数据宽度单元类型CSD划分CSD结构CSDSTRUCTURER:保留R:数据读取时间TAACR:数据在CLK周期内读取NSACR:时间(NSAC*)最大数据传输率TRANSPEEDR:卡命令集合CCCR:最大读取数据块长READBLLENR:允许读的部分块READBLPARTIALR:非线写块WRITEBLKMISALIGNR:非线读块READBLKMISALIGNR:DSR条件DSRIMPR:保留R:设备容量CSIZER:最大读取电流VminVDDRCURRMINR:DD最大读取电流VmaxVDDRCURRMAXR:DD最大写电流VminVDDWCURRMINR:DD最大写电流VmaxVDDWCURRMAXR:DD设备容量乘子CSIZEMULTR:擦除单块使能ERASEBLKENR:擦除扇区大小SECTORSIZER:写保护群大小WPGRPSIZER:写保护群使能WPGRPENABLER:保留R:写速度因子RWFACTORR:最大写数据块长度WRITEBLLENR:允许写的部分部WRITEBLPARTIALR:保留R:文件系统群FILEOFRMATGRPRW:拷贝标志COPYRW:永久写保护PERMWRITEPROTECTRW:暂时写保护TMPWRITEPROTECTRW:文件系统FILFORMATRW:保留RW:CRCCRCRW:未用始终为:读CSD的时序:相应的程序例程如下:读SD卡的CSD寄存器共字节返回说明读取成功unsignedcharReadCSDSD(unsignedchar*Buffer){读取CSD寄存器的命令unsignedcharCMD={x,x,x,x,x,xFF}unsignedchartemptemp=SDReadBlock(CMD,Buffer,)readbytesreturn(temp)})读取SD卡信息综合上面对CID与CSD寄存器的读取可以知道很多关于SD卡的信息以下程序可以获取这些信息。如下:返回SD卡的容量单位为MsectorcountandmultiplierMBareinu==CSIZE(^(CSIZEMULT))SD卡的名称voidSDgetvolumeinfo(){unsignedchariunsignedcharctempVOLUMEINFOTYPESDvolumeInfo,*vinfvinf=SDvolumeInfoInitthepointoer读取CSD寄存器ReadCSDSD(sectorBufferdat)获取总扇区数vinf>sectorcount=sectorBufferdatxvinf>sectorcount<<=vinf>sectorcount=sectorBufferdatvinf>sectorcount<<=vinf>sectorcount=(sectorBufferdatxc)>>获取multipliervinf>sectormultiply=sectorBufferdatxvinf>sectormultiply<<=vinf>sectormultiply=(sectorBufferdatx)>>获取SD卡的容量vinf>sizeMB=vinf>sectorcount>>(vinf>sectormultiply)getthenameofthecardReadCIDSD(sectorBufferdat)vinf>name=sectorBufferdatvinf>name=sectorBufferdatvinf>name=sectorBufferdatvinf>name=sectorBufferdatvinf>name=sectorBufferdatvinf>name=xendflag}以上程序将信息装载到一个结构体中这个结构体的定义如下:typedefstructSDVOLUMEINFO{SDSDCardinfounsignedintsizeMBunsignedcharsectormultiplyunsignedintsectorcountunsignedcharname}VOLUMEINFOTYPE)扇区读扇区读是对SD卡驱动的目的之一。SD卡的每一个扇区中有个字节一次扇区读操作将把某一个扇区内的个字节全部读出。过程很简单先写入命令在得到相应的回应后开始数据读取。扇区读的时序:扇区读的程序例程:unsignedcharSDReadSector(unsignedlongsector,unsignedchar*buffer){unsignedcharretry命令unsignedcharCMD={x,x,x,x,x,xFF}unsignedchartemp地址变换由逻辑块地址转为字节地址sector=sector<<sector=sector*CMD=((sectorxFF)>>)CMD=((sectorxFF)>>)CMD=((sectorxFF)>>)将命令写入SD卡retry=do{为了保证写入命令一共写次temp=WriteCommandMMC(CMD)retryif(retry==){return(READBLOCKERROR)blockwriteError!}}while(temp!=)ReadStartByteformMMCSDCard(FEhStartByte)Nowdataisready,youcanreaditoutwhile(ReadByteMMC()!=xfe)readPos=SDgetdata(,buffer)字节被读出到buffer中return}其中SDgetdata函数如下:获取数据到buffer中voidSDgetdata(unsignedintBytes,unsignedchar*buffer){unsignedintjfor(j=j<Bytesj)*buffer=ReadByteSD()})扇区写扇区写是SD卡驱动的另一目的。每次扇区写操作将向SD卡的某个扇区中写入个字节。过程与扇区读相似只是数据的方向相反与写入命令不同而已。扇区写的时序:扇区写的程序例程:写个字节到SD卡的某一个扇区中去返回说明写入成功unsignedcharSDwritesector(unsignedlongaddr,unsignedchar*Buffer){unsignedchartmp,retryunsignedinti命令unsignedcharCMD={x,x,x,x,x,xFF}addr=addr<<addr=addr*CMD=((addrxFF)>>)CMD=((addrxFF)>>)CMD=((addrxFF)>>)写命令到SD卡中去retry=do{为了可靠写入写次tmp=WriteCommandSD(CMD)retryif(retry==){return(tmp)sendcommamdError!}}while(tmp!=)在写之前先产生个时钟信号for(i=i<i){ReadByteSD()}写入开始字节WriteByteMMC(xFE)现在可以写入个字节for(i=i<i){WriteByteMMC(*Buffer)}CRCByteWriteByteMMC(xFF)DummyCRCWriteByteMMC(xFF)CRCCodetmp=ReadByteMMC()readresponseif((tmpxF)!=x)写入的个字节是未被接受{SPICS=return(WRITEBLOCKERROR)Error!}等到SD卡不忙为止因为数据被接受后SD卡在向储存阵列中编程数据while(ReadByteMMC()!=xff){}禁止SD卡SPICS=return()写入成功}此上内容在笔者的实验中都已调试通过。单片机采用STCLE单片机(SD卡的初始化电压为V~V操作电压为V~V因此不能用V单片机或进行分压处理)工作于M的时钟下由于所采用的单片机中没硬件SPI采用软件模拟SPI因此读写速率都较慢。如果要半SD卡应用于音频、视频等要求高速场合则需要选用有硬件SPI的控制器或使用SD模式当然这就需要各位读者对SD模式加以研究有了SPI模式的基础SD模式应该不是什么难事。以下内容参考WYF下载的网页资料:F:otherNEWSTMRealView《基于ATC单片机的SD卡读写设计》转神奇的日志网易博客htmSPI工作模式SD卡在上电初期自动进入SD总线模式在此模式下向SD卡发送复位命令CMD。如果SD卡在接收复位命令过程中CS低电平有效则进入SPI模式否则工作在SD总线模式。SD卡的初始化对SD卡进行操作首先要对SD卡进行初始化初始化的过程中设置SD卡工作在SPI模式其流程图如图所示。在复位成功之后可以通过CMD和ACMD判断当前电压是否在工作范围内。主机还可以继续通过CMD读取SD卡的CID寄存器通过CMD设置数据Block长度通过CMD读取卡的CSD寄存器。从CSD寄存器中主机可获知卡容量支持的命令集等重要参数。SD卡初始化的C语言程序如下:unsignedcharSDInit(void){unsignedcharretry,tempunsignedcharifor(i=i<xfi){SPITransferByte(xff)延迟个以上的时钟}SDEnable()开片选SPITransferByte(SDRESET)发送复位命令SPITransferByte(x)SPITransferByte(x)SPITransferByte(x)SPITransferByte(x)SPITransferByte(x)SPITransferByte(xff)SPITransferByte(xff)retry=do{temp=WriteCommandSD(SDINIT,)发送初始化命令retryif(retry==)重试次{SDDisable()关片选return(INITCMDERROR)如果重试次失败返回错误号}}while(temp!=)SDDisable()关片选return(TRUE)返回成功}数据块的读写完成SD卡的初始化之后即可进行它的读写操作。SD卡的读写操作都是通过发送SD卡命令完成的。SPI总线模式支持单块(CMD)和多块(CMD)写操作多块操作是指从指定位置开始写下去直到SD卡收到一个停止命令CMD才停止。单块写操作的数据块长度只能是字节。单块写入时命令为CMD当应答为时说明可以写入数据大小为字节。SD卡。对每个发送给自己的数据块都通过一个应答命令确认它为个字节长当低位为时表明数据块被正确写入SD卡在需要读取SD卡中数据的时候读SD卡的命令字为CMD接收正确的第一个响应命令字节为xFE随后是个字节的用户数据块最后为个字节的CRC验证码。可见读写SD卡的操作都是在初始化后基于SD卡命令和响应完成操作的写、读SD卡的程序流程图如图和图所示。结束语实验结果表明单片机使用MHz的晶体振荡器时读写速度和功耗都基本令人满意可以应用于对读写速度要求不高的情况下。本文详细阐述了用ATC单片机对SD卡进行操作的过程提出了一种不带SD卡控制器MCU读写SD卡的方法实现了SD卡在电能监测及无功补偿数据采集系统中的用途。

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/23

SD卡读写操作__SD卡电路

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利