基于STM32的SD卡设计毕业论文
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
摘要
SD卡(Secure Digital Memory Card)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。
SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。
大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。
由于互联网的飞速发展,各种移动设备的计算能力得到大幅提升,与外界数据通信交换量越来越大,通信的安全性以及数据的真实性尤为重要。
正是因为SD卡具有如此多的优点,才被人们广泛的应用。
根据SD卡的各种优点和特性,而在STM32平台上对其进行开发设计,着重于加强SD卡的数据通信的速度以及与嵌入式产品的通信更加方便,主要对SD卡通信时采集的电压、电流、功率及时间监测及补偿。
包含一些基本的通信及SD卡驱动实现和分析,本文基于STM32就SD卡的硬件和软件作研究设计。
最后,对SD卡课题研究进行阶段性总结和对后续工作进行展望。
关键词:SD卡;移动存储;STM32;SPI接口
ABSTRACT
SD card (Secure Digital Memory Card) Secure Digital card translated into Chinese, is a flash memory device based on a new generation of semiconductor memory devices, it is widely used in portable devices such as digital cameras, personal digital assistant (PDA) and multimedia players. SD card from Japan Panasonic, Toshiba and SanDisk Corporation in the United States in August 1999 jointly developed. Like a postage stamp size SD memory card, weight only 2 grams, but it has high memory capacity, fast data transfer rates, great flexibility and good mobile security. As the rapid development of Internet, computing power of mobile devices has increased substantially, with the outside world, increasing the amount of data traffic exchange, traffic safety and authenticity of data is particularly important.
It is precisely because of the SD card has so many advantages, was only a wide range of applications. The various advantages and features of the SD card, while in the STM32 platform, its development and design, focus on strengthening the SD card data communication speed and more convenient communications and embedded products, mainly collected in the SD card to communicate voltage, current, power and time monitoring and compensation . Contains some basic communication and SD card driver implementation and analysis, SD card hardware and software design based on the STM32.
Finally, the stage summary and outlook on the follow-up research of the SD card. Key Words: SD card; Removable Storage; STM32; SPI interface
目录
第一章绪论
1.1 课题背景及意义 (1)
1.2 SD卡简介 (1)
1.3 SD卡的应用 (2)
1.4 SD卡所研究的内容以及特色 (3)
第二章 SD卡硬件设计
2.1 硬件读写模块 (4)
2.2 硬件设计模块 (4)
第三章 SD卡软件设计
3.1 SPI工作模式: (7)
3.2 SD卡初始化: (9)
3.3数据块的读写 (10)
3.4 SD卡软件设计 (11)
第四章调试与效果
4.1 STM32连接原理图 (13)
4.2 下载与调试 (13)
第五章结论与展望
参考文献(References) (16)
致谢 (17)
附录 (18)
附录1 (18)
附录2 (20)
第一章绪论
1.1 课题背景及意义
21世纪是一信息传递及应用高速的时代,信息在人类社会活动中已经必不可缺,使用嵌入式系统的电子产品已经在人们的日常生活中广泛普及应用。
其中人们日常生活中最经常接触使用到的数码相机、手机、MP3、MP4、多媒体播放器等,其信息数据的存储大部分都是使用的SD卡。
所以SD卡在嵌入式上应用有着十分大市场空间。
SD卡拥有轻小、高存储容量、高速的传输速率以及很高的安全性,更换和编程也相当方便。
根据SD卡胡特性,它已然成为非常多数码产品的外部应用储存的第一选择目标。
ALIENTKE MiniSTM32开发板就带有SD卡接口,利用STM32自带的SPI接口,最大通信速度可达18Mbps,每秒可传输数据2M 字节以上,对于一般应用足够了。
1.2 SD卡简介
SD卡——Secure Digital Memory Card,中文意思是安全数码卡,是一种可移动的存储设备,面积和体积都很小,质量也够轻。
但记忆性好,传输的速度很快,通信非常方便,移动性好,安全性能也十分高。
所以很多数码产品都是用的它,有数码相机、手机、还有一些媒体播放器都是非常的适用。
加上由于互联网的飞速发展,各种移动设备的计算能力得到大幅提升,与外界数据通信交换量越来越大,通信的安全性以及数据的真实性尤为重要。
现在用于数据储存的产品有很多,如U盘和SD卡等。
但是由于各自的优点不同,比较一下的话,还是SD卡适合用于嵌入式应用,非常大的容量,有些的产品达到了32GB以上的容量,而且有着标准的大小。
21世纪是一信息传递及应用高速的时代,信息在人类社会活动中已经必不可缺,使用嵌入式系统的电子产品已经在人们的日常生活中广泛普及应用。
其中人们日常生活中最经常接触使用到的数码相机、手机、MP3、MP4、多媒体播放器等,其信息数据的存储大部分都是使用的SD卡。
SD卡在24mm×32mm×2.1mm的体积内结合了〔SanDisk〕快闪记忆卡控制与MLC(Multilevel Cell)技术和Toshiba(东芝)0.16u及0.13u的NAND技术。
SD卡的通信模式有2种,如下:
a. SD卡模式;
b. SPI模式;
主机可以选取两种模式中的任何一种来与SD卡进行通信。
其中SD卡所允许的最大传输线数是四线,所以SPI模式与SD卡模式两者的传输速率相比的话较多,所以SPI模式传输数据的速率非常快但要比SD卡模式传输数据的好戏速率要慢了好多。
图1.2.1 SD卡物理方面的特性示例
1.3 SD卡的应用
从SD卡进入到人类的社会活动的时间来看,SD卡的发展是非常的短暂而又快速,可见人们对其应用是相当的依赖。
使用SD卡的电子产品也是非常的多数不胜数,时下已经成为最为通用的数据存储卡。
质量轻,尺寸小,传输速度快,安全性能高。
SD卡拥有轻小、高存储容量、高速的传输速率以及很高的安全性,更换和编程也相当方便。
正是因为SD卡有着如此多的优点,将它应用到嵌入式开发中来,将是不二的选择。
图1.3.1实际应用图例
1.4 安全数码卡所研究的内容以及特色
本文基于STM32就SD卡硬件和软件的研究设计加以介绍,分析系统软硬件的选择,以及其开发环境的调试和应用。
将SD卡插入STM32开发板,SD卡与STM32 进行数据交换,要将SD卡外部驱动,将外部储存卡与STM32联系起来。
开发板对成为外部储存空间的SD卡进行读写,把读写命令解析并传送到SD卡中,从而实现开发板对外部储存卡的操作与控制。
重点研究设计以下内容:
1、STM32的简单介绍以及在此嵌入式操作系统下所进行驱动地开发步骤;
2、对SD卡命令分析和实现;
3、对SD卡通信分析,包含SD通信模式和SPI通信模式,DMA的所有寄存器的含义和设置,及其它的一些设置;
4、基本的驱动分析及实现,SD卡的驱动实验;
5、SD卡硬件和软件的研究设计。
研究设计的特色:
通过此次的研究分析,可以更好的深入了解SD卡及STM32。
实现SD卡在STM32开发板上更好的驱动,加快SD卡与STM32之间的数据交互。
最终实现SD卡与嵌入式系统产品更加紧密的联系和应用。
第二章 SD卡硬件方面的研究设计
2.1 硬件读写模块
SD卡存储模式是Flash。
SD卡的卡内智能控制模块包含电源和时钟的管理、协议、算法安全、存取数据、ECC算法、处理缺陷和分析数据。
FLASH每个扇区的写寿命在10万次左右,读的次数是无限制的。
SD卡引脚分布排列顺序如下图所示:
图2.1.1 SD卡引脚图
针脚 1 2 3 4 5 6 7 8 9 SD卡模式CD/DAT3 CMD VSS VCC CLK VSS DAT0 DA T1 DAT2 SPI模式CS MOSI VSS VCC CLK VSS MOSI NC NC
表2.1.1 安全数码卡引脚功能表
在STM32中,开板使用的是SPI的接口模式来进得读写,所以,本课题主要应用的便是SPI的模式。
由于SD卡内部的供电电压上升是需要一段时间,大约是64个时钟,而且需要10个时钟与SD卡同步,所以在发送CMD0之前,要发送>74个时钟。
SD卡与STM32进行数据交换,要将SD卡外部驱动,将外部储存卡与STM32联系起来。
开发板对成为外部储存空间的SD卡进行读写,把读写命令解析并传送到SD卡中,从而实现开发板对外部储存卡的操作与控制。
2.2 硬件设计模块
开机之后先将进行安全数码卡的初始化,如若完成安全数码卡的初始,将会读出数据,内容是零扇区里面的。
对SD卡通信分析,包含SD通信模式和SPI通信模式,DMA的所有寄存器的含义和设置,及其它的一些设置若是没有通过初
始,LCD上会显示初始化失败。
通过DS0来指示程序正在运行。
所需要的硬件资源如下:
1.SD卡。
2.STM32F103ZET6。
3.DS0(外部LED0)。
4.串口1。
SD卡和STM32的连接:
SPI1与安全数码卡通信,如下其引脚的连接定义为:
PE3:SPI1-SPI2全双工通讯,低电平作用;
PA7:通讯结束后跟随一个CRC校验;
PA5:SPI1、SPI2的NSS引脚是断开的;
PA6:SPI驱动,NSS引脚由软件设置配置;
PC12:MOSI输出,与STM32通信;
CLK:时钟信号;
CMD:双向命令和响应信号;
DAT0-3:双向数据信号;
VDD,VSS:电源和地信号;
SD卡的总线结构是单主多从的结构,即在SD模式下允许有一个主机, 多个从机或是多个卡, 主机可以给从机分别地址。
总线上卡使用都是统一的时钟和电源线。
主机访问各个卡都是依照顺序来,区分不同的卡的根据是每一个卡里的CID 寄存器当中都有一个已经编好的程序作为唯一的卡识别号。
SD在主机的定义下有一定的电压范围,当提供的电压在主机定义范围之外时,SD卡将处于非活动的状态,所有总线上的数据总线传输都将被忽略。
要使SD 卡进入活动状态的唯一的办法是将SD卡重新上电。
SD卡的内存组织:SD卡以一个字节作为数据读写的基本单元,根据不一样的要求来组成不一样的模块。
Block:块的实际大小等信息是由CSD寄存器所控制的,其大小按照需求来改变,也可以将其大小固定。
Sector:Sector对于每个设备大小都是固定的也是由CSD寄存器来存储信息的大小。
相关的擦除命令,是由几个块组成的。
WP Group:写保护单位。
大小包括几个块,一位决定写保护,WP 对于每个设备大小都是固定的,同样将信息大小存储在CSD 寄存器中。
SD卡与MCU的连接原理图如下:
图2.2.1 SD卡与STM32连接电路图
硬件接口设计:
在SPI模式下,引脚1(DAT3)作为SPI片选线CS用,引脚2(CMD)用作SPI总线的数据输出线MOSI,而引脚7(DAT0)为数据输入线MISO,NSS 由硬件配置,SPI2为主机,SPI1为从机,使SS输出(置位SPI_ CR2 SSOE位),SPI2 NSS引脚复位SPI1的NSS引脚并配置SPI1为从机。
在通讯中使用DMA 可以减少代码密度和执行时间,容易接收和发送数据。
利用各种硬件设备自身的特点来减小其运转开销,例如减小中断次数、利用DMA传输方式等。
安全数码卡传输给STM32,STM32和SD卡进行数据间的互换。
第三章 SD卡软件设计
3.1 SPI工作模式:
SPI可以同时发出和接收串行数据。
SD卡在STM32上的驱动,以及STM32的数据交换,开发板可以通过程序来获知SD卡的内容,通过命令参数来控制SD 卡。
SPI2为主机,SPI1为从机,使SS输出(置位SPI_ CR2 SSOE位),SPI2 NSS 引脚复位SPI1的NSS引脚并配置SPI1为从机。
我们通常也需要最大可能地利用各种硬件设备自身的特点来减小其运转开销,例如减小中断次数、利用DMA传输方式等。
包含SD通信模式和SPI通信模式,DMA的所有寄存器的含义和设置,及其它的一些设置。
SD模式和SPI模式是安全数码卡的两个协议作为通信用的。
NSS由硬件配置,SPI2为主机,SPI1为从机,使SS输出(置位SPI_ CR2 SSOE位),SPI2 NSS 引脚复位SPI1的NSS引脚并配置SPI1为从机。
在通讯中使用DMA可以减少代码密度和执行时间,容易接收和发送数据在SPI模式下,主机只使用两根数据线和外围器件进行通讯,且每条线是单工模式,因此在速度上不如SD模式,也无法像SD模式一样实现主机连接多设备时数据线的通用。
但由于其实现简单,具有良好的设备兼容性,因此大多部设备默认的通讯协议都是SPI模式。
而STM32 开发板本身具有SD卡接口,大大节省了成本。
1、SPI1-SPI2全双工通讯,通讯结束后跟随一个CRC校验。
SPI1和SPI2的数据输入端(MISO)连接在一起,SPI1、SP2的数据输出端(MOSI)连接在一起,两个SPI的时钟输入SCK连接在一起。
由于NSS管理,SPI1、SPI2的NSS引脚是断开的。
图3.1.1 STM32F10XXX的SPI1-SPI2全双工通讯的典型连接提供的固件包含SPI驱动,NSS引脚由软件设置配置SPI1为主,SPI2为从。
能够通过CRC校验,则其SPI为可靠的。
2、半双工通讯的典型连接,SPI2的MOSI和SPI2的MISO引脚连接在一起,SCK连接在一起。
SPI1和SPI2的NSS引脚连接在一起。
图3.1.2 SPI1与SPI2单通讯模式半双工通讯连接
NSS由硬件配置,SPI2 为主机,SPI1为从机,使SS输出(置位SPI_CR2SSOE 位),SPI2 NSS引脚复位SPI1的NSS引脚并配置SPI1为从机。
在通讯中使用DMA可以减少代码密度和执行时间,容易接收和发送数据。
3、SPI1与SPI2单通讯模式,SPI1的数据输出(MOSI)连接到SPI2的(MISO),时钟线连接到一起。
NSS引脚不连接,以便NSS软件管理。
图3.1.3 SPI1与SPI2单通讯模式
在单通讯模式下,使用者只需要使用主机的MOSI引脚和从机的MISO引脚及CLK引脚。
3.2 SD卡初始化:
初始化安全数码卡,是进行安全数码进行卡操作的前提,其流程图为。
图3.2.1流程图(安全数码卡的初始化)
附录一为安全数码卡的参考,程序。
复位:首先是至少74个CLK,然后CS_LOW;发送CMD0(COM0:0x40 0x00 0x00 0x00 0x00 0x95),收到的应答是0x01;初始化:接着发送CMD1(COM0:0x41 0x00 0x00 0x00 0x00 0xff),收到的应答应该是0x00;最后CS_HIGH。
至此,初始化完成。
3.3数据块的读写
安全数码卡读写数据块,NSS由硬件配置,SPI2为主机,SPI1为从机,使SS输出(置位SPI_ CR2 SSOE位),SPI2 NSS引脚复位SPI1的NSS引脚并配置SPI1为从机。
首先,进行安全数码卡的初始化,安全数码卡的初始化,其过程是这样的:1.安全数码卡初始化,及其硬件的连接:MCU的SPI配置,IO配置;
2.上电延时(>74个CLK);
3.复位(CMD0);
4.查询OCR,获取供电状况(CMD58);
5.是否使用CRC(CMD59);
6.74个CLK,然后CS_LOW;
7.接着发送CMD1;
8.收到应答,CS_HIGH;
按照以上的步骤进行操作之后,收到的应答,初始化,初始化完成如下:1.发送CMD24;
2.发送与接收安全数码卡响应;
3.送入相对应的特殊的指令;
4.发送数据;
5.将数据进行接收;
6.发送八个时钟之后,片选将被禁止;
访问各个卡都是依照顺序来,区分不同的卡的根据是每一个卡里的CID寄存器当中都有一个已经编好的程序作为唯一的卡识别号。
SD在主机的定义下有一定的电压范围,当提供的电压在主机定义范围之外时,SD卡将处于非活动的状态,所有总线上的数据总线传输都将被忽略。
安全数码卡的读写操作都是在经过初始化之后基于安全数码卡命令与响应完成相应的操作地,安全数码卡的读、写如下图所示,其为程序的流程图。
3.4 安全数码卡软件设计
通过 SD_GetCapacity 函数来得到SD 卡的容量,然后在液晶上显示出来,接着我们读取SD 卡的扇区0,然后把这部分数据通过串口打印出来。
每6s 执行一次。
源程序参照附录二 ( 程序由C 语言编写,有很好的移植性) 。
此程序实现SD 卡在STM32上的驱动,以及STM32的数据交换,开发板可以通过程序来获知SD
卡的内容,通过命令参数来控制SD卡。
SD卡与STM32 进行数据交换,要将SD 卡外部驱动,将外部储存卡与STM32联系起来。
开发板对成为外部储存空间的SD 卡进行读写,把读写命令解析并传送到SD卡中,从而实现开发板对外部储存卡的操作与控制。
分析系统软硬件的选择,以及其开发环境的调试和应用。
除了编程上的技巧外,为提高系统的运行效率,我们通常也需要最大可能地利用各种硬件设备自身的特点来减小其运转开销,例如减小中断次数、利用DMA 传输方式等。
第四章调试与效果
4.1 STM32连接原理图
图4.1.1 STM32连接原理
4.2 下载与调试
将附录2的代码编译成功后,将代码下载到ALIENTEK MiniSTM32 开发板上,在LCD显示屏上可以看到如下图所示,则表示SD卡已经连接上STM32:
图4.2.1 SD卡连接显示内容
完成以上步骤后,打开串口调试助手,可以得到从STM32开发板发送回来的数据如下图所示:
图 4.2.2 串口收到的SD卡扇区0内容
第五章结论与展望
SD卡应用使让人越来依赖它,可以说是已经成为人类社会生活中不可或缺的一部分,SD卡具有广阔的发展前景和市场前景。
21世纪是一信息传递及应用高速的时代,信息在人类社会活动中已经必不可缺,使用嵌入式系统的电子产品已经在人们的日常生活中广泛普及应用。
通过毕业设计,让我各方面都有了一个提升。
技术上,我更加深入了解STM32和SD卡,学到了以前没有学过的知识。
在作此毕业设计时,也有着各种各样的困难,但在老师的指导下,同学的帮助下,我克服了一个又一个的困难和解决了一个又一个的问题。
实际动手能力也有一个很大的提升,从程序的编译和设备的连接调式及仿真,都是非常考验我。
也学会了查阅并应用资料,分析能力都有一个很大的进步。
这次毕业设计是我对前所学专业的知识的一个总结和实际检验和巩固,同时帮助我在作之前一个很好的锻炼,加强了我的独立工作能力,是走向工作岗位的至关重要的一步。
此毕业设计由选题之初到准备材料到编写论文到完成论文,都暴露了我的很多不足之处,比如缺乏综合应用专业知识的能力,在一些小细节和小问题太过放松。
通过这次的学习和实践,我清楚的认识到自己的知识还很不全面,处理问题等方面都还需要一个更大的提升,做任何都要认真对待、全力以赴。
毕业将至,在我以后漫漫人生路更加要不断学习,充实和提升自己。
把活到老学到老真正运用到实际中来,也警示自己世上有太多自己不懂的地方,只有通过不停的学习和努力工作才能克服困难,走向成功。
参考文献(References)
[1] Joseph Yiu 著.宋岩译.Cortex-M3 权威指南.(电子版)
[2] 李宁主编.基于MDK的STM32处理器开发应用. 北京:北京航空航天大学出版社.2008
[3] 张义和主编.Altium Designer完全电路设计.北京:机械工业出版社.2007
[4] 刘同法,肖志刚,彭继卫编. ARM Cortex-M3内核微控制器快速入门与应用.北京:北京航空航天大学出版社.2009
[5] Cortex-M3 技术参考手册.pdf
[6] 红牛用户手册.pdf
[7] 软件使用手册.pdf
[8] STM32F10x参考手册_cn.pdf
[9] STM32固件库使用手册的中文翻译版.pdf
[10]Smartcard interface with the STM32F101xx and STM32F103xx.pdf
[11] DSP之SD卡与文件系统彻底研究.pdf(红尘出品)
[12]stm32不完全手册.pdf
[13]STM32F系列ARM Cortex-M3核微控制器开发与应用(喻金钱、喻斌编著)清华大学出版社
致谢
本毕业设计是在蔡军老师的精心指导和鼓励帮助下完成的。
蔡老师在我大学期给予我悉心的教导和无偿的帮助。
蔡老师严谨的治学态度和真诚谦逊的品质,为我树立了榜样,不但教会我学术研究,并且教我更做人的道理。
在此,谨向蔡老师表示最衷心的感谢!
感谢所有支持和帮助过我的同学和老师!
此外,我还要感谢在我的论文中所有被援引过的文献的作者们,他们是我的知识之源!
最后,感谢我的父母在背后给予我无限的关怀和支持!
刘明福
2012年5月5日
附录
附录1
SD卡初始化程序:
unsigned char SD_Init(void)
{
unsigned char retry,temp;
unsigned char i;
for (i=0;i<0x0f;i++)
{
SPI_TransferByte(0xff);
}
SD_Enable();
SPI_TransferByte(SD_RESET);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x95);
SPI_TransferByte(0xff);
SPI_TransferByte(0xff);
retry=0;
do
{
temp=Write_Command_SD(SD_INIT,0);
retry++;
if(retry==100)
{
SD_Disable();
return(INIT_CMD1_ERROR);
}
}
while(temp!=0);
SD_Disable();
return(TRUE);
}
附录2
SD软件设计程序:
#include "sys.h"
#include "mmc_sd.h"
#include "spi.h"
#include "usart.h"
#include "delay.h"
u8 SD_Type=0;
NumByteToRead);
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;
}
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:
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)
{
retry++;
if(retry>=0XFFFFFFFE)return 0XFF;
};
return 0;
}
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_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;
SPIx_ReadWriteByte(0xFF);
return r1;
}
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc) {
u8 Retry=0;
u8 r1;
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
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;
}
return r1;
}
u8 SD_Idle_Sta(void)
{
u16 i;
u8 retry;
or(i=0;i<0xf00;i++);
for(i=0;i<10;i++)SPIx_ReadWriteByte(0xFF);
retry = 0;
do
{
i = SD_SendCommand(CMD0, 0, 0x95);
retry++;
}
while((i!=0x01)&&(retry<200));
if(retry==200)return 1;
return 0;
}
u8 SD_Init(void)
{
u8 r1;
u16 retry;
u8 buff[6];
RCC->APB2ENR|=1<<2;
GPIOA->CRL&=0XFFF000FF;
GPIOA->CRL|=0X00033300;
GPIOA->ODR|=0X7<<2;
SPIx_Init();
SPIx_SetSpeed(SPI_SPEED_256);
SD_CS=1;
if(SD_Idle_Sta()) return 1;
SD_CS=0;
r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);
if(r1 == 0x05)
{
SD_Type = SD_TYPE_V1;
SD_CS=1;
SPIx_ReadWriteByte(0xFF);
retry = 0;
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1 == 0XFF)return r1;
r1 = SD_SendCommand(ACMD41, 0, 0);
retry++;
}
while((r1!=0x00) && (retry<400));
if(retry==400)
{
retry = 0;
do
{
r1 = SD_SendCommand(1,0,0);
retry++;
}
while((r1!=0x00)&& (retry<400));
if(retry==400)return 1;
SD_Type = SD_TYPE_MMC;
}
SPIx_SetSpeed(SPI_SPEED_4);
SPIx_ReadWriteByte(0xFF);
r1 = SD_SendCommand(CMD59, 0, 0x95);
if(r1 != 0x00)return r1;
r1 = SD_SendCommand(CMD16, 512, 0x95);
if(r1 != 0x00)return r1;
else if(r1 == 0x01)
{
buff[0] = SPIx_ReadWriteByte(0xFF);
buff[1] = SPIx_ReadWriteByte(0xFF);
buff[2] = SPIx_ReadWriteByte(0xFF);
buff[3] = SPIx_ReadWriteByte(0xFF);
SD_CS=1;
SPIx_ReadWriteByte(0xFF);
{
retry = 0;
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1!=0x01)return r1;
r1=SD_SendCommand(ACMD41, 0x40000000, 0);
if(retry>200)return r1;
}
while(r1!=0);
r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
if(r1!=0x00)
{
SD_CS=1;
return r1;
}
buff[0] = SPIx_ReadWriteByte(0xFF);
buff[1] = SPIx_ReadWriteByte(0xFF);
buff[2] = SPIx_ReadWriteByte(0xFF);
buff[3] = SPIx_ReadWriteByte(0xFF);
SD_CS=1;
SPIx_ReadWriteByte(0xFF);
if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC;
else SD_Type = SD_TYPE_V2;
SPIx_SetSpeed(SPI_SPEED_4);
}
}
return r1;
}
u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
{
SD_CS=0;
if(SD_GetResponse(0xFE))
{
SD_CS=1;
return 1;
}
while(len--)
{
*data=SPIx_ReadWriteByte(0xFF);
data++;
}
SPIx_ReadWriteByte(0xFF);
SPIx_ReadWriteByte(0xFF);
if(release==RELEASE)
{
SD_CS=1;
SPIx_ReadWriteByte(0xFF);
}
return 0;
}
u8 SD_GetCID(u8 *cid_data)
{
u8 r1;
r1 = SD_SendCommand(CMD10,0,0xFF);
if(r1 != 0x00)return r1;
SD_ReceiveData(cid_data,16,RELEASE);
return 0;
}
u8 SD_GetCSD(u8 *csd_data)
{
u8 r1;
r1=SD_SendCommand(CMD9,0,0xFF);
if(r1)return r1;
SD_ReceiveData(csd_data, 16, RELEASE);
return 0;
}
u32 SD_GetCapacity(void)
{
u8 csd[16];
u32 Capacity;
u8 r1;
u16 i;
u16 temp;
if(SD_GetCSD(csd)!=0) return 0;
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);
r1 = csd[9]&0x03;
r1<<=1;
r1 += ((csd[10]&0x80)>>7);
r1+=2;//BLOCKNR
temp = 1;
while(r1)
{
temp*=2;
r1--;
}
Capacity = ((u32)(i+1))*((u32)temp);
i = csd[5]&0x0f;
temp = 1;
while(i)
{
temp*=2;
i--;
}
Capacity *= (u32)temp;
}
return (u32)Capacity;
}
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
{
u8 r1;
SPIx_SetSpeed(SPI_SPEED_4);
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;
}
#define BLOCK_SIZE 512
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite) {
u32 i,NbrOfBlock = 0, Offset = 0;
u32 sector;
u8 r1;
NbrOfBlock = NumByteToWrite / BLOCK_SIZE;
SD_CS=0;
while (NbrOfBlock--)
{
sector=WriteAddr+Offset;
if(SD_Type==SD_TYPE_V2HC)sector>>=9;
r1=SD_SendCommand_NoDeassert(CMD24,sector,0xff);
if(r1)
{
SD_CS=1;
return 1;
}
SPIx_ReadWriteByte(0xFE);
for(i=0;i<512;i++)SPIx_ReadWriteByte(*pBuffer++);
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
if(SD_WaitDataReady())
{
SD_CS=1;
return 2;
}
Offset += 512;
}
SD_CS=1;
SPIx_ReadWriteByte(0xff);
return 0;
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead) {
u32 NbrOfBlock=0,Offset=0;
u32 sector=0;
u8 r1=0;
NbrOfBlock=NumByteToRead/BLOCK_SIZE;
SD_CS=0;
while (NbrOfBlock --)
{
sector=ReadAddr+Offset;
if(SD_Type==SD_TYPE_V2HC)sector>>=9;
r1=SD_SendCommand_NoDeassert(CMD17,sector,0xff);
if(r1)
{
SD_CS=1;
return r1;
}
r1=SD_ReceiveData(pBuffer,512,RELEASE);
if(r1)
{
SD_CS=1;
return r1;
}
pBuffer+=512;
Offset+=512;
}
SD_CS=1;
SPIx_ReadWriteByte(0xff);
return 0;
}
u8 SD_WriteSingleBlock(u32 sector, const u8 *data) {
u8 r1;
u16 i;
u16 retry;
if(SD_Type!=SD_TYPE_V2HC)
{
sector = sector<<9;
}
r1 = SD_SendCommand(CMD24, sector, 0x00);
if(r1 != 0x00)
{
return r1;
}
SD_CS=0;
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xFE);
for(i=0;i<512;i++)
{
SPIx_ReadWriteByte(*data++);
}
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
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;
}
}
SD_CS=1;
SPIx_ReadWriteByte(0xff);
return 0;
}
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
{
u8 r1;
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;
}
u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
{
u8 r1;
u16 i;
if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count,
0x00);
r1 = SD_SendCommand(CMD25, sector, 0x00);
if(r1 != 0x00)return r1;
SD_CS=0;
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
do
{
SPIx_ReadWriteByte(0xFC);
for(i=0;i<512;i++)
{
SPIx_ReadWriteByte(*data++);
}
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
r1 = SPIx_ReadWriteByte(0xff);
if((r1&0x1F)!=0x05)
{
SD_CS=1;
return r1;
}
if(SD_WaitDataReady()==1)
{
SD_CS=1;
return 1;
}
}
while(--count);
r1 = SPIx_ReadWriteByte(0xFD);
if(r1==0x00)
{
count = 0xfe;
}
if(SD_WaitDataReady())
{
SD_CS=1;
return 1;
}
SD_CS=1;
SPIx_ReadWriteByte(0xff);
return count;
}
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;
if(SD_GetResponse(0xFE))
{
SD_CS=1;
Return 1;
}
for(i=0;i<offset;i++)SPIx_ReadWriteByte(0xff);
for(;i<offset+bytes;i++)*buf++=SPIx_ReadWriteByte(0xff);
for(;i<512;i++) SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
SPIx_ReadWriteByte(0xff);
SD_CS=1;
return 0;
}。