规划计划
使用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的逻辑电平为5VCMOS电平规范。因而,它们之间不能直接相连,不然会有焚毁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;
#defineSD_DISAble() CS=1 //片选关
#defineSD_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;
}