51单片机spi驱动sd卡程序
89C51单片机读取SD卡驱动程序

89C51单片机读取SD卡驱动程序本程序是应用于51单片机的 89c52#include "MMC.h"bit Init_Flag; //Set it to 1 when Init is processing.bit card_type;//uchar csd_data[16];//uchar cid_data[16];unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};//CMD0/**********************************************************延时子函数**********************************************************/void delay(unsigned int time){while(time--);}/**********************************************************us延时子程序 (4.34us)**********************************************************/void delayNOP(){_nop_();_nop_();_nop_();_nop_();}/************************************************************ 卡端口初始化************************************************************/ void MMC_Port_Init(){SPI_CLK=1;SPI_DO =1;SPI_CS=1;}//************************************************************* ***************//Routine for sending a byte to MMC/SD-Card//write a byte//************************************************************* ***************void Write_Byte_MMC(uchar value){unsigned char i;for (i=0;i<8;i++){if (value&0x80)SPI_DI=1; //Send bit by bit(MSB First)elseSPI_DI=0;SPI_CLK=0; //Clock lowif(Init_Flag)delayNOP();SPI_CLK=1; //Clock Highif(Init_Flag)delayNOP();value <<=1;}}//************************************************************* ***************//Routine for reading a byte from MMC/SD-Card//Software SPI//************************************************************* ***************unsigned char Read_Byte_MMC(){unsigned char temp=0;unsigned char i;SPI_DO=1;for (i=0;i<8;i++) //MSB First{SPI_CLK=0; //Clock Lowif(Init_Flag)delayNOP();SPI_CLK=1; //Clock Highif(Init_Flag)delayNOP();temp=(temp<<1)|SPI_DO; //read mmc data out pin}return (temp);}//************************************************************* ***************//Send a Command to MMC/SD-Card//Return: the second byte of response register of MMC/SD-Card//************************************************************* ***************unsigned char Write_Command_MMC(unsigned char *CMD) {unsigned char tmp;unsigned char i;//set MMC_Chip_Select to high (MMC/SD-Card disable)SPI_CS=1;//send 8 Clock ImpulseWrite_Byte_MMC(0xFF);//set MMC_Chip_Select to low (MMC/SD-Card active) SPI_CS=0;//send 6 Byte Command to MMC/SD-Cardfor (i=0;i<0x06;i++){Write_Byte_MMC(*CMD++);}i = 0;//get 16 bit responseRead_Byte_MMC(); //read the first byte,ignore it.do{ //Only last 8 bit is used here.Read it out.tmp = Read_Byte_MMC();i++;}while((tmp==0xff)&&(i<100));return(tmp);}//********************************************************** //Routine for Init MMC/SD card(SPI-MODE)unsigned char MMC_Init()//********************************************************** {unsigned char temp;unsigned char i;MMC_Port_Init(); //Init SPI portdelay(200);Init_Flag=1; //Set the init flagfor (i=0;i<0x0f;i++){Write_Byte_MMC(0xff); //send 74 clock at least}//Send Command CMD0 to MMC/SD Cardi = 0;do{ //retry 200 times to send CMD0 commandtemp=Write_Command_MMC(CMD);i++;if(i >= 200){ //time outreturn(INIT_CMD0_ERROR); //CMD0 Error!}}while(temp!=1);i = 0;do{CMD[0] = 0x77; //CMD55命令temp = Write_Command_MMC(CMD); //先发送 CMD55if(temp == 0x01) //如果有反应{CMD[0] = 0x69; //ACMD41命令temp = Write_Command_MMC(CMD); //发送CMD41进行激活if(temp == 0x00) //激活成功就是SD卡{card_type =1; //SD}}else //如果发送CMD55无反应,改发送CMD1{CMD[0] = 0x41; //CMD1命令CMD[5] = 0xFF;temp = Write_Command_MMC(CMD); //发送CMD1进行激活if(temp == 0x00) //激活成功就是MMC卡{card_type =0; //MMC}}i++;if(i >= 200){return(INIT_CMD1_ERROR); //CMD1 Error!}}while(temp != 0x00); // MMC和SD卡激活后的返回值均为0x00Init_Flag=0; //Init is completed,clear the flagSPI_CS=1; //set MMC_Chip_Select to high// wr_string(0,2," INIT SUCCESS ");return(0); //All commands have been taken.}//************************************************************ //Routine for reading data Registers of MMC/SD-Card//Return 0 if no Error.//************************************************************ unsigned char MMC_Read_Block(uchar *CMD,uchar *Buffer,uint Bytes){unsigned int i;unsigned char temp;//Send Command CMD to MMC/SD-Cardi = 0;do{ //Retry 100 times to send command.temp=Write_Command_MMC(CMD);i++;if(i == 100){return(READ_BLOCK_ERROR); //block write Error!}}while(temp!=0);//Read Start Byte form MMC/SD-Card (FEh/Start Byte)while (Read_Byte_MMC()!=0xfe) ;//Write blocks(normal 512Bytes) to MMC/SD-Cardfor (i=0;i<bytes;i++){*Buffer++ = Read_Byte_MMC();}Read_Byte_MMC();//CRC - ByteRead_Byte_MMC();//CRC - ByteSPI_CS=1;return(0);}//************************************************************ //Routine for</bytes;i++)reading CSD Registers from MMC/SD-Card (16Bytes)//Return 0 if no Error.//Command for reading CSD Registers//************************************************************ unsigned char Read_CSD_MMC(unsigned char *Buffer) {unsigned char temp;CMD[0]=0X49; //CMD9:读CSD寄存器.CMD[5]=0XFF;temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytes return(temp);}//************************************************************ //Routine for reading CID Registers from MMC/SD-Card (16Bytes)//Return 0 if no Error.//Command for reading CID Registers//************************************************************ unsigned char Read_CID_MMC(unsigned char *Buffer){unsigned char temp;CMD[0]=0X4A; //CMD10:读CID寄存器.CMD[5]=0XFF;temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytesreturn(temp);}/**********************************************************/。
SD卡SPI模式驱动程序!!

4.
在所有的指令中,唯独CMD0特殊,在向SD卡发送以前需要向SD卡发送74+个时钟。那么为什么要74个CLK呢?因为在上电初期,电压的上升过程据
SD卡组织的计算约合64个CLK周期才能到达SD卡的正常工作电压他们管这个叫做Supply ramp up
1.为了使SD卡初始化进入SPI模式,我们需要使用的命令有3个:CMD0,ACMD41,CMD55(使用ACMD类的指令前应先发CMD55,CMD55起到一个
为什么在使用CMD0以后不使用CMD1?CMD1是MMC卡使用的指令,虽然本文并不想讨论MMC卡的问题,但是我还是要说:为了实现兼容性,上电或者
关于程序,大家请到我在论坛上的这个帖子下载。
最后,还是那句老话,大家有问题可以问我,在这篇文章留言,留言时选择匿名就可以不注册留言,必要时留下自己的邮箱,我们可以一起研究。我的邮箱地址在首页的右上方的图片上有。
1.SD卡的官方资料(我承认这个资料很垃圾,比起民间的技术总结它的内容可谓又臭又长,但是作为基础也要了解一下,SD协议不用看)
2.清晰明了的MMC卡时序图(虽然这个是MMC卡的,但是在初始化的时候CMD0的时序是一样的)
发送CMD0后,应该首先发送CMD55+ACMD41确认是否有回应,如果有回应则为SD卡,如果等回应超时,则可能是MMC卡,再发CMD1确认。
3.正确的回应内容应该是:
CMD0——0x01(SD卡处于in-idle-state)
电路:我用的SD卡的电路其实很简单,参考SD卡的官方资料中的电路链接就可以的。
供电问题:由于SD卡的电压是3.3V,所以你的CPU必须支持3.3V的IO端口输出。
再来说一说鸡毛蒜皮的细节:
51单片机读写SD卡(命令解释)

51单片机读写SD卡(命令解释)SD卡命令共分为12类,分别为class0到class11,不同的SDd卡,主控根据其功能,支持不同的命令集如下: Class0 :(卡的识别、初始化等基本命令集)CMD0:复位SD 卡.CMD1:读OCR寄存器.CMD9:读CSD寄存器.CMD10:读CID寄存器.CMD12:停止读多块时的数据传输CMD13:读Card_Status 寄存器Class2 (读卡命令集):CMD16:设置块的长度CMD17:读单块.CMD18:读多块,直至主机发送CMD12为止 .Class4(写卡命令集):CMD24:写单块.CMD25:写多块.CMD27:写CSD寄存器 .Class5 (擦除卡命令集):CMD32:设置擦除块的起始地址.CMD33:设置擦除块的终止地址.CMD38: 擦除所选择的块.Class6(写保护命令集):CMD28:设置写保护块的地址.CMD29:擦除写保护块的地址.CMD30: Ask the card for the status of the write protection bitsclass7:卡的锁定,解锁功能命令集class8:申请特定命令集。
class10 -11 :保留其中class1, class3,class9:SPI模式不支持51单片机读写SD卡(概述,硬件连接)SD卡全称为Secrue Digital Memory Card,具有轻巧、可加密、传输速度高、适用于手持设备使用等优点。
SD需要高速读写,同时也要使手持等嵌入式设备能方便使用,特设有两个访问接口:SD模式接口和SPI接口。
由于51单片机的速度的原因,一般采用SPI接口方式连接SD卡, 在连接时需要在SD卡边接10-100K上拉电阻,SD卡的电源是DC3.3V51单片机读写SD卡(寄存器)SD卡有以下几种内部寄存器1.CID 卡的识别号宽度128,详细描述如下2.RCA 卡的相对地址(SPI模式不可用)3.DSR 可选寄存器宽度164.CSD 描述操作该卡的规则(时序规则)。
51平台通过SPI方式读写SD

一、总则本文件介绍了在51平台通过SPI方式读写SD/MMC卡,包括软硬件需求, SD/MMC硬件连接, SPI接口软件模拟,SD/MMC上电初始化,写单块,读单块,写多块,读多块,块擦除,上位串口通讯协议,PC上位软件操作说明等。
二、软硬件需求a) 单片机固件编译环境:Keil C51 uVision2b) PC上位软件编译环境:Visual C++ 6.0c) 硬件环境:1)W78E52B一片;2)SD/MMC卡插座一个;3)MAX232一片;4)cross串口线一条;三、SD/MMC硬件连接SD/MMC与51单片机引脚连接如下表1,供参考:51单片机引脚SD/MMC引脚P1_0SPI_CS (PIN1)P1_1SPI_SI(PIN2)P1_2SPI_SCK(PIN5)P1_3SPI_SO(PIN7)PIN4接VDDPIN3/6接GND表1 SD/MMC与51单片机引脚连接表注意:SD/MMC引脚除VDD(PIN4)/VSS(PIN3/6)外,其它引脚连接上拉电阻(47k)至3.3v 电源。
四、SPI接口软件模拟由于W78E52B没有集成硬件SPI接口,所以固件需要通过软件来模拟实现SPI接口;a) SPI接口基本原理:SPI采用HOST/SLAVE结构,HOST与SLA VE以字节为传输单位,支持4种模式;SPI接口定义有4个引脚CS,SI,SO,SCK;SD SPI接口工作于模式0,各引脚功能分别描述如下:1) CS为片选引脚,低电平为有效;2) SI为Host输出Slave输入引脚,空闲为高电平,SCK上升有效,;3) SO为Slave输出Host输入引脚,SCK下降有效;4) SCK为同步时钟;b) SPI HAL:包括4个函数,上层软件通过调用这4个函数,来实现与SD/MMC以SPI方式进行数据交换。
1) SPI_SendByte(INT8U onebyte)――以SPI方式向SD/MMC发送一个字节2) INT8U SPI_RecByte(void)――以SPI方式从SD/MMC接收一个字节3) SPI_CS_Assert(void)――将CS引脚置为低电平有效4) SPI_CS_Deassert(void)――将CS引脚置为高电平无效c) 通过SPI HAL发送的RESET命令CMD0波形图,如下图1,以供参考:图1-RESET命令CMD0波形图一、SD/MMC上电初始化当SD/MMC卡上电后,单片机需要对其进行上电初始化,上电初始化步骤顺序所列如下:1) 置CS为低,至少延时74个CLK,延时波形图,如图2,以供参考:图2-延时波形图1) 发送RESET命令CMD0,其波形图参考图1:2) 发送命令CMD1(SD卡使用命令ACMD41)激活SD/MMC卡, 固件需重复发送命令CMD1直到R1 idle state位为0。
用51单片机读写SD卡

引脚号 1 2 3 4 5 6 7 8 9
图 1 SD 卡外形 表 1 SD 卡引脚功能
名称
功能 (SD 模式) 功能 (SPI 模式)
DAT3/CS
数据线 3
片选/从选 (SS)
CMD/DI
命令线
主出从入 (MOSI)
VSS1 VDD CLK VSS2 DAT0/DO DAT1/IRQ DAT2/NC
DAT2 / NC DAT3 / CS CMD / DI VSS1 VDD CLK / SCK VSS2 DAT0 / DO DAT1 / IRQ
图2
3 软件实现
软件部分 主 要 实 现 底 层 SPI 通 信 , SD 卡 的 复 位 , SD 卡 的 初始化、 以及 SD 卡的通用写命令和单块数据的读写等功能。
3.1 底层 SPI 通信函数
//======================================= //写一字节到 SD 卡,模拟 SPI 总线方式 void SD_spi_write(unsigned char n) {
unsigned char i;
for(i=0;i<8;i++) { SD_CLK=0; if(is_init) delay(DELAY_TIME); SD_DI=(n&0x80)>>7; SD_CLK=1; if(is_init) delay(DELAY_TIME);
在 SPI 模式中, 命令都是以如表 2 的 6 字节形式发送的。 表2
第一字节
第 2-5 字节
第 6 字节
0
1
命令号
参数
CRC 校验 1
每帧命令都以 “01” 开头, 然后是 6 位命令号和 4 字节的 参 数 (高 位 在 前 , 低 位 在 后), 最 后 是 7 位 CRC 校 验 和 1 位 停 止位 “1”。
SD卡引脚及spi模式基本操作过程

SD卡引脚及spi模式基本操作过程(摘自网络)对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的存储器结构、存储单元组织方式等内容。
要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写,并对其读写速度进行了评估。
下面先来讲解SD卡的读写时序。
SD卡的引脚定义SD卡引脚功能详述:引脚编号SD模式SPI模式名称类型描述名称类型描述1 CD/DAT3 IO或PP 卡检测/数据线3#CS I 片选2 CMD PP 命令/回应DI I 数据输入3 VSS1 S 电源地VSS S 电源地4 VDD S 电源VDD S 电源5 CLK I 时钟SCLK I 时钟6 VSS2 S 电源地VSS2 S 电源地7 DAT0 IO或PP 数据线0 DO O或PP 数据输出8 DAT1 IO或PP 数据线1 RSV9 DAT2 IO或PP 数据线2 RSV注:S:电源供给I:输入O:采用推拉驱动的输出PP:采用推拉驱动的输入输出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方式进行介绍。
SPI方式驱动SD卡的方法SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。
从应用的角度来看,采用SPI接口的好处在于,很多单片机内部自带SPI控制器,不光给开发上带来方便,同时也见降低了开发成本。
然而,它也有不好的地方,如失去了SD卡的性能优势,要解决这一问题,就要用SD方式,因为它提供更大的总线数据带宽。
用51单片机读写SD卡

…
实用第一 智慧密集
… . … … … … … … ~ …
2
非 法命 令
n<< 1 :
1
l
O
擦 除 复 位
空 闲 状 态
)
/= , l ==== ==:= ===== :=== =:==: ====== ==== =====
结 构 .在 官 方 的文 档 上有 很 详 细 的介 绍 ,如 S 卡 内 的存 储 器 D 结 构 、存 储单 元组 织 方 式 等 内容 。
1 S 卡标 准 D
S D卡标 准是 S D卡协 会针 对可 移动 存 储设 备设 计 专 利并 授权
命 令 和 专 。 命 令 ,后 面接 命 令 的 编 号 。例 如 ,C 用 MD1 是 一 7就
u sg e h r n in dc a
p SD s iwre “n in dc a ) a g me t3 ) i “ J s e h r & r u n ) ] t g f ;
_
_
SD s iwr eCR : p i ( C) t
— _
d o
f rI0 8i +) o ( < : _ +
个 通 用 命 令 ,用来 读 单 块 数 据 。
的一 种标 准 .主要用 于制 定卡 的外形 尺 寸 、电气接 口和 通信协 议 。
在 SI P 模式 中 ,命 令 都 是 以如 表 2的 6字 节 形 式 发 送 的 。
表 2
第 一 字 节 第 2 5字 节 - 第 6字 节
的 响 应 类 型 都 是 R1 ,这 里 的通 用 写 命 令 函数 所 接 收 的 响 应 类
C LK / CK S VS 2 S DA TO,
MCS51 MCU读写SD卡版(单片机论文)

摘要摘要近年来, SD存储卡在嵌入式产品中的应用越来越广泛, 但SD卡接口一般仅集成在32位高端处理器中, 一般51单片机则由于资源限制没有该接口。
因此,如何解决51单片机应用系统存取SD卡大容量数据就显得很有实际意义。
本系统使用MXT8051F04A作为单片机与SD卡的接口芯片, 采用SPI串行方式对SD卡的扇区进行读写,读写过程和结果通过串口调试助手在主机上显示。
本论文的核心主要从硬件设计和软件编程两个大的方面介绍了系统的实现。
硬件电路设计主要包括MXT8051F04A最小系统电路、电源电路、串口电路、SD卡接口电路。
程序采用C语言在Keil软件下进行编写、调试,程序主要包括SD卡扇区读写程序、串口程序等软件模块。
系统实现了对SD卡扇区的读写,达到了设计的要求和目的。
关键字:MXT8051F04A,SD卡,KeilIABSTRACTABSTRACTIn recent years, SD memory card applications in the embedded products more widely, but generally only the integrated SD card interface in 32-bit high-end processor, microcontroller 51 is generally not the interface due to resource constraints. Therefore, how to solve the 51 SCM applications to access data on large-capacity SD cards seem very practical.The system uses MXT8051F04A as SCM and SD card interface chip, using SPI mode on the SD card serial read and write sectors, reading and writing process and results through the serial port on the host display debugging assistant. The core of this thesis, the main hardware and software design introduces two major aspects of the system implementation. Hardware design includes MXT8051F04A minimum system circuit, power circuit, the serial port circuitry, SD card interface circuit. Program using C language under the Keil software write, debug, the program includes reading and writing SD card sector program, serial procedures of software modules. System realizes the SD card read and write sectors, meets the design requirements and objectives.Keywords: MXT8051F04A,SD Card,KeilII目录第1章引言 (1)1.1 选题背景 (1)1.2 研究目标和意义 (1)1.3 本文要完成的工作 (1)第2章单片机读写SD卡的硬件电路设计 (3)2.1 系统硬件平台组成 (3)2.2 电源模块 (3)2.3 MXT8051F04A单片机最小系统电路设计 (4)2.3.1 MXT8051F04A简介 (4)2.3.2 晶振复位电路 (8)2.4 SD卡电路设计 (8)2.4.1 通讯模式 (9)2.4.2 电平匹配 (9)2.4.3 硬件接口设计 (10)2.5 串口电路设计 (12)2.6 PCB绘制 (13)2.7 本章小结 (14)第3章单片机读写SD卡的软件设计 (14)3.1 SD卡的扇区读写 (14)3.1.1 模拟SPI协议 (14)3.1.2 SD卡命令 (15)3.1.3 SD卡的初始化 (19)3.1.4 数据块的读写 (20)3.2 串口程序 (25)第4章调试 (26)4.1 系统硬件调试 (26)4.2 软件调试 (27)4.3 软硬件的联合调试 (27)III4.4 本章小结 (29)第5章结束语 (30)5.1 总结 (30)5.2 展望 (30)参考文献 (31)致谢 (32)附录 (33)附录一:单片机读写SD卡的完整原理图 (33)附录二:单片机读写SD卡的完整程序 (36)外文资料原文 (63)译文 (64)IV第1章引言第1章引言1.1选题背景SD卡(Secure Digital Memory Card)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如个人数码助理(PDA)、数码相机和多媒体播放器等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
AT89C52单片机驱动SD卡系统设计
本文详细阐述了用AT89C52单片机对SD卡进行操作的过程,提出了一种不带SD卡控制器,MCU读写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卡的可能。
出于对安全工作的考虑,有必要解决电平匹配问题。
要解决这一问题,最根本的就是解决逻辑器件接口的电平兼容问题,原则主要有两条:一为输出电平器件输出高电平的最小电压值,应该大于接收电平器件识别为高电平的最低电压值;另一条为输出电平器件输出低电平的最大电压值,应该小于接收电平器件识别为低电平的最高电压值。
一般来说,通用的电平转换方案是采用类似SN74ALVC4245的专用电平转换芯片,这类芯片不仅可以用作升压和降压,而且允许两边电源不同步。
但是,这个方案代价相对昂贵,而且一般的专用电平转换芯片都是同时转换8路、16路或者更多路数的电平,相对本系统仅仅需要转换3路来说是一种资源的浪费。
考虑到SD卡在SPI协议的工作模式下,通讯都是单向的,于是在单片机向
SD卡传输数据时采用晶体管加上拉电阻法的方案,基本电路如图1所示。
而在SD卡向单片机传输数据时可以直接连接,因为它们之间的电平刚好满足上述的电平兼容原则,既经济又实用。
这个方案需要双电源供电(一个5V电源、一个3.3V电源供电),3.3V电源可以用AMS1117稳压管从5V电源稳压获取。
硬件接口设计
SD卡提供9Pin的引脚接口便于外围电路对其进行操作,9Pin的引脚随工作模式的不同有所差异。
在SPI模式下,引脚1(DAT3)作为SPI片选线CS 用,引脚2(CMD)用作SPI总线的数据输出线MOSI,而引脚7(DAT0)为数据输入线MISO,引脚5用作时钟线(CLK)。
除电源和地,保留引脚可悬空。
本文中控制SD卡的MCU是ATMEL公司生产的低电压、高性能CMOS 8位单片机AT89C52,内含8K字节的可反复擦写的只读程序存储器和256字节的随机存储数据存储器。
由于AT89C52只有256字节的数据存储器,而SD卡的数据写入是以块为单位,每块为512字节,所以需要在单片机最小系统上增加一片RAM。
本系统中RAM选用存储器芯片HM62256,容量为32K。
对RAM进行读写时,锁存器把低8位地址锁存,与P2口的8位地址数据构成16位地址空间,从而可使SD卡一次读写512字节的块操作。
系统硬件图如图2所示。
软件设计
SPI工作模式
SD卡在上电初期自动进入SD总线模式,在此模式下向SD卡发送复位命令CMD0。
如果SD卡在接收复位命令过程中CS低电平有效,则进入SPI模式,否则工作在SD总线模式。
对于不带SPI串行总线接口的AT89C52单片机来说,用软件来模拟SPI总线操作的具体做法是:将P1.5口(模拟CLK线)的初始状态设置为1,而在允许接收后再置P1.5为0。
这样,MCU在输出1位SCK时钟的同时,将使接口芯片串行左移,从而输出1位数据至AT89C52单片机的P1.7(模拟MISO线),此后再置P1.5为1,使单片机从P1.6(模拟MOSI线)输出1位数据(先为高位)至串行接口芯片。
至此,模拟1位数据输入输出便完成。
此后再置P1.5为0,模拟下1位数据的输入输出,依此循环8次,即可完成1次通过SPI总线传输8位数据的操作。
本文的实现程序把SPI总线读写功能集成在一起,传递的val变量既是向SPI 写的数据,也是从SPI读取的数据。
具体程序如下:(程序是在Keil uVision2的编译环境下编写)
sbit CS=P3^5;
sbit CLK= P1^5;
sbit DataI=P1^7;
sbit DataO=P1^6;
#define SD_Disable() CS=1 //片选关
#define SD_Enable() CS=0 //片选开
unsigned char SPI_TransferByte(unsigned char val)
{
unsigned char BitCounter;
for(BitCounter=8; BiCounter!=0; BitCounter--)
{ CLK=0;
DataI=0; // write
if(val&0x80) DataI=1;
val<<=1;
CLK=1;
if(DataO)val|=1; // read
}
CLK=0;
return val;
}
SD卡的初始化
对SD卡进行操作首先要对SD卡进行初始化,初始化的过程中设置SD卡工作在SPI模式,其流程图如图3所示。
在复位成功之后可以通过CMD55和ACMD41判断当前电压是否在工作范围
内。
主机还可以继续通过CMD10读取SD卡的CID寄存器,通过CMD16设置数据Block长度,通过CMD9读取卡的CSD寄存器。
从CSD寄存器中,主机可获知卡容量,支持的命令集等重要参数。
SD卡初始化的C语言程序如下:unsigned char SD_Init(void)
{ unsigned char retry,temp;
unsigned char i;
for (i=0;i<0x0f;i++)
{ SPI_TransferByte(0xff); //延迟74个以上的时钟
}
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) //重试100次
{SD_Disable(); //关片选
return(INIT_CMD1_ERROR);
//如果重试100次失败返回错误号
}
}while(temp!=0);
SD_Disable(); //关片选
return(TRUE); //返回成功
}
数据块的读写
完成SD卡的初始化之后即可进行它的读写操作。
SD卡的读写操作都是通过发送SD卡命令完成的。
SPI总线模式支持单块(CMD24)和多块(CMD25)写操作,多块操作是指从指定位置开始写下去,直到SD卡收到一个停止命令CMD12才停止。
单块写操作的数据块长度只能是512字节。
单块写入时,命令为CMD24,当应答为0时说明可以写入数据,大小为512字节。
SD卡对每个发送给自己的数据块都通过一个应答命令确认,它为1个字节长,当低5位为00101时,表明数据块被正确写入SD卡。
在需要读取SD卡中数据的时候,读SD卡的命令字为CMD17,接收正确的第一个响应命令字节为0xFE,随后是512个字节的用户数据块,最后为2个字节的CRC验证码。
可见,读写SD卡的操作都是在初始化后基于SD卡命令和响应完成操作的,写、读SD卡的程序流程图如图4和图5所示。
结束语
实验结果表明单片机使用12MHz的晶体振荡器时,读写速度和功耗都基本令人满意,可以应用于对读写速度要求不高的情况下。