单片机读写SD卡API模式读写
51单片机的SD卡的读写设计
基于AT89C52单片机的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卡的可能。
51单片机实现对SD卡的读写
51单片机实现对SD卡的读写51单片机实现对SD卡的读写SD卡在现在的日常生活与工作中使用非常广泛,时下已经成为最为通用的数据存储卡。
在诸如MP3、数码相机等设备上也都采用SD卡作为其存储设备。
SD卡之所以得到如此广泛的使用,是因为它价格低廉、存储容量大、使用方便、通用性与安全性强等优点。
既然它有着这么多优点,那么如果将它加入到单片机应用开发系统中来,将使系统变得更加出色。
这就要求对SD卡的硬件与读写时序进行研究。
对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的存储器结构、存储单元组织方式等内容。
要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写,并对其读写速度进行了评估。
下面先来讲解SD卡的读写时序。
(1)SD卡的引脚定义:SD卡引脚功能详述:引脚编号SD模式 SPI模式名称类型描述名称类型描述1 CS/DAT3 IO或PP 卡检测/数据线3 #CS I 片选2 CMD PP 命令/回应DI I 数据输入3 VSS1S 电源地VSS S 电源地4 VDDS 电源VDD S 电源5 CLK I 时钟SCLK I 时钟6 VSS2S 电源地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方式。
4根线单片机读写SD卡
还记得刚才说的那 6 字节命令格式吗?【1 字节】(0x40+命令序号)+【4 字】节参 数+【1 字节】CRC 校验码。套用这命令的格式,我们得到如下 SD 卡比较常用的命令串。 读 SD 卡 0 扇区的命令串:{0x51,0x00,0x00,0x00,0x00,0xff};
写 SD 卡 1 扇区的命令串:{0x58,0x00,0x00,0x02,0x00,0xff};
七、 驱动程式
文末了,在本文的文件夹中,有我已经写好的 SD 卡读写驱动。供大家学习使用,程序 写的比较简单。
SD_MMC.C 的文件里有 3 个函数:1、初始化 SD 卡,2、读 SD 卡指定扇区,3、写 SD 卡指定扇区。
初始化 SD 卡函数 SD_INIT():它使 SD 卡进入 SPI 模式并复位。读 SD 卡指定扇区函数 sd_read(),函数的入口是 4 字节 SD 卡地址,用了 unsigned long 数据类型,如果函数返回 1 表示操作成 功,返回 0 则表示操作失败。写 SD 卡指定扇区函数 sd_write(),方式和读 SD 卡指定扇区一样。
SD 卡复位的命令串:{0x40,0x00,0x00,0x00,0x00,0x95};
SD 卡进入 SPI 模式的命令串:{0x41,0x00,0x00,0x00,0x00,0xff};
五、 数据传送
当 SD 卡接收到“读” 命令后,SD 卡会在 MISO 线上回应命令(0x00),其后 SD 卡再向单片机,发送 1 字节的起始字节(0xfe),紧接着发送连续的 512 字节数据。在发送 完这些数据后,还有 2 个字节的 CRC 校验码,也是紧接着发送的。同样,单片机通过 MOSI 线向 SD 卡发送“写 SD 卡” 命令后,单片机需要先读取 SD 卡向 MISO 线上传送的回应数 据(0x00)。当接收到回应后,单片机就可以先发送 1 个字节的起始字节(0xfe)。随后,单 片机再发送 512 字节的 RAM 数据。最后再加上 2 个字节的 CRC 校验码。不过,SD 卡默认 是不对数据进行校验的。也就是说,2 字节校验码可以是任意数据,但一定要发送的。发完 这 515 字节个数据后,SD 卡会又有一个 5 位的回应数据(二进制:XXX00101B)。表示数 据已经写入完毕。
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)、数码相机和多媒体播放器等。
单片机对SD卡读写系列(三)
单片机对SD卡读写系列(三)
对SD 卡的驱动主要有初始化、读、写、擦除等。
1、初始化步骤:
(1)延时至少74clock
(2)发送CMD0,需要返回0x01,进入Idle 状态
(3)循环发送CMD55+ACMD41,直到返回0x00,进入Ready 状态。
如果是MMC,此步应发送CMD1。
2、读步骤:
(1)发送CMD17(单块)或CMD18(多块)读命令,返回0x00
(2)接收数据开始令牌0xfe(或0xfc)+正式数据512Bytes + CRC 校验2Bytes
默认正式传输的数据长度是512Bytes,可用CMD16 设置。
3、写步骤:
(1)发送CMD24(单块)或CMD25(多块)写命令,返回0x00
(2)发送数据开始令牌0xfe(或0xfc)+正式数据512Bytes + CRC 校验2Bytes
4、擦除步骤:
(1)发送CMD32,跟一个参数来指定首个要擦出的扇区号(SD 手册上说
是块号)
(2)发送CMD33,,指定最后的扇区号
(3)发送CMD38,擦除指定区间的扇区
此3 步顺序不能颠倒。
还要注意发送CMD 命令时,后面要跟一个字节的CRC 校验数据,总之要保证每次发送的数据包长度符合协议要求,命令、数据符合时序要求。
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。
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 描述操作该卡的规则(时序规则)。
单片机读写SD卡分析陈
单片机读写SD卡分析一、开篇二、硬件电路三、SPI操作1.初始化2.读3.写四、SD操作1.初始化2.读3.写五、FAT文件系统六、总结三、SPI操作1、SPI总线简介SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息,20世纪80年代由Motorola 首先在其MC68HCXX系列处理器上定义的。
SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。
其主要特点包括:可以同时发出和接受串行数据;可以作为主机或丛机工作;发送结束中断标志;写冲突保护;总线竞争保护。
图1是SPI总线架构示意图。
图1 SPI 总线架构基本特点:1.同步2.串行3.全双工4.非即插即用5.一主多从更多细节:1.同步时钟有主控芯片产生,每个时钟传输一位数据2.数据在传输前,首先要进行并转串,才能用一条线传输3.两条数据线,一条输入、一条输出4.主从双方有关于SPI传输的先验知识,如比特顺序、数据长度等5.数据传输有主控芯片发起,每次只与一个从芯片通讯SPI是一种同步全双工的通讯接口,每个时钟在两条数据线上各传输一比特数据。
SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
工作模式:原理上讲,串行传输是按位传输方式,只利用一条信号线进行传输SPI由工作方式的不同,可分为两种模式:主模式和从模式 1).主模式将Master的数据传送给Slave,8位数据传送,传送完毕,申请中断2).从模式从控制器从SIMO引脚接收串行数据并把数据移入自身移位寄存器的最低位或最高位。
用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”。
FAT文件系统的SD卡单片机读写方法详解
FAT文件系统的SD卡单片机读写方法详解FAT(File Allocation Table)文件系统是一种常用的文件系统,被广泛应用于存储设备如SD卡上。
在单片机中使用SD卡进行读写操作时,需要使用FAT文件系统进行文件的管理和操作。
下面将详细介绍FAT文件系统的SD卡单片机读写方法。
1.SD卡初始化:在进行SD卡读写操作之前,首先需要初始化SD卡。
初始化SD卡的步骤如下:1.1硬件上电及等待稳定。
将SD卡模块供电,并等待SD卡电压稳定,通常需要几十毫秒的时间。
1.2发送复位命令。
向SD卡发送复位命令,命令的格式如下:CMD0:0x400x000x000x000x000x95发送这个命令后,SD卡会返回R1响应,其中bit 0为0表示复位成功。
1.3发送检测版本命令。
向SD卡发送检测版本命令,命令的格式如下:CMD8:0x480x000x000x010xAA0x87发送这个命令后,SD卡会返回R7响应,其中bit 0为0表示命令执行成功。
1.4判断SD卡类型。
根据R7响应中的数据,判断SD卡的类型,如果是SDHC卡或SDXC卡,需要进行额外的操作。
1.5发送初始化命令。
向SD卡发送初始化命令,命令的格式如下:CMD55:0x770x000x000x000x000xFFACMD41:0x690x400x000x000x000xFF循环发送这两个命令,直到SD卡返回R1响应的bit 0为0,表示初始化完成。
1.6发送读取OCR命令。
向SD卡发送读取OCR命令,命令的格式如下:CMD58:0x7A0x000x000x000x000xFF发送这个命令后,SD卡会返回R3响应,其中包含卡的OCR寄存器的内容。
2.FAT文件系统格式化:在SD卡上创建FAT文件系统之前,需要对SD卡进行格式化操作。
格式化操作会将SD卡分为引导扇区、FAT表、根目录区和数据区。
2.1创建引导扇区。
在SD卡的第一个扇区创建引导扇区,引导扇区包含引导记录和磁盘参数表。
单片机读写SD卡教程
郑重声明:本实验并不是对所有SD卡都能成功运行第一步:打开winhex软件,用读卡器读SD卡,在winhex中查看SD卡点这点击查找(ctrl+F)输入FAT(找到DBR处)发现DBR起始于0x11200扇区地址,它必是512整数倍,因为一个扇区含512BYTE,所以在程序中读一个扇区时一定要是512整数倍,否则会出错。
11200地址对应的值是0xEB,本程序读一下这个地址的值看看是否正确。
注意有的winhex编址是十进制看看程序吧#include <reg52.h>#define uchar unsigned char#define uint unsigned int//=============================================================//定义SD卡需要的4根信号线sbit SD_CLK = P1^1;sbit SD_DI = P1^2;sbit SD_DO = P1^0;sbit SD_CS = P1^3;sbit Beep=P2^0;//用来调程序标志//===========================================================//===========================================================//定义512字节缓冲区,,89C52直接定义成unsigned char DATA[80];,太大了RAM不够unsigned char xdata DATA[512];void delay(unsigned int z){unsigned int x,y;for(x=z;x>0;x--);for(y=110;y>0;y--);}//=========================================================== //写一字节到SD卡,模拟SPI总线方式void SdWrite(unsigned char n){unsigned char i;for(i=8;i;i--){SD_CLK=0;SD_DI=(n&0x80);n<<=1;SD_CLK=1;}SD_DI=1;}//=========================================================== //从SD卡读一字节,模拟SPI总线方式unsigned char SdRead(){unsigned char n,i;for(i=8;i;i--){SD_CLK=1;SD_CLK=0;n<<=1;if(SD_DO) n|=1;}return n;}//============================================================ //检测SD卡的响应unsigned char SdResponse(){uchar i=0,response=0;while(i<=8){response = SdRead();if(response==0x00)break;if(response==0x01)break;i++;}return response;}//================================================================ //发命令到SD卡void SdCommand(unsigned char command, unsigned long argument, unsigned char CRC) {SdWrite(command|0x40);/*SdWrite(((unsigned char *)&argument)[0]);SdWrite(((unsigned char *)&argument)[1]);SdWrite(((unsigned char *)&argument)[2]);SdWrite(((unsigned char *)&argument)[3]);*/SdWrite(argument>>24);SdWrite(argument>>16);SdWrite(argument>>8);SdWrite(argument);SdWrite(CRC);}//================================================================ //初始化SD卡unsigned char SdInit(void){unsigned char i;unsigned char response=0xFF;P3=0xff;SD_CS=1;for(i=0;i<=0xfe;i++)SdWrite(0xff);SD_CS=0;SdCommand(0x00,0,0x95);SD_DI=1;response=SdResponse();if(response!=0x01){return 0;}if(response==0x01){ //不管什么SD卡都能进入这一步,同时也说明硬件没问题SD_CS=1;//Beep=0;//while(1);//用来查看程序能否运行到这一步,去掉//即可SdWrite(0xff);SD_CS=0;while(1){SdCommand(0x01,0,0xff);//SdCommand(0x01,0x00000000,0xff);//进SPIresponse=0xff;SD_DI=1;for(i=0;i<250;i++)//response!=0x00//等待回复{response=SdResponse(); //Beep=0;/if(response==0) break;}if(response==0) {break;}//回复0则通过SPI,只要通过SPI后面的指令才能继//续// Beep=0;}// Beep=0;//看程序能否跳出来,挑不出来则进不了SPISD_CS=1;SdWrite(0xff);SD_CS=0;// Beep=0;return 1;}}//================================================================//往SD卡指定地址写数据,一次最多512字节最好不要乱写否则fat系统被改掉SD卡打不开unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len){unsigned int count;unsigned char dataResp;SD_CS=0;SdCommand(0x18,address,0xff);if(SdResponse()==00){SdWrite(0xff);SdWrite(0xff);SdWrite(0xff);//command was a success - now send data//start with DATA TOKEN = 0xFESdWrite(0xfe);//now send datafor(count=0;count<len;count++) SdWrite(*Block++);for(;count<512;count++) SdWrite(0);//data block sent - now send checksumSdWrite(0xff); //两字节CRC校验, 为0XFFFF 表示不考虑CRCSdWrite(0xff);//Now read in the DA TA RESPONSE tokendataResp=SdRead();while(SdRead()==0);dataResp=dataResp&0x0f; //mask the high byte of the DATA RESPONSE tokenSD_CS=1;SdWrite(0xff);if(dataResp==0x0b){return 0;}if(dataResp==0x05)return 1;return 0;}//printf("Command 0x18 (Write) was not received by the SD.\n");return 0;}//===================================================================== ==//从SD卡指定地址读取数据,一次最多512字节unsigned char SdReadBlock(unsigned char *Block, unsigned long address,int len){unsigned int count,i;uchar response;SD_CS=0;// while(1)// {SdCommand(0x11,address,0xff);// SD_DO=1;// P0=SdResponse();// P0=0xff;// while(1);while(response!=0xfe && i<200) {response=SdRead();P0=response;i++;} // if(i>=200) Beep=0;// P0=0xf0;// }// Beep=0;for(count=0;count<512;count++) *Block++=SdRead();SdRead();SdRead();//Now read in the DA TA RESPONSE tokenSD_CS=1;SdWrite(0xff);return 1;}void main(){unsigned int mm;unsigned long AddTemp=0x11200;//70144;//SD卡地址第一个数据物理地址初始值70144是通过winhex查看,对于你的SD卡肯定要改//可以用winhex查看,一定要是512整数倍mm=SdInit();//SdReadBlock(DATA,AddTemp,1);delay(10);// Beep=0;if(DATA[0]==0xeb) Beep=0;// 看读的对不对while(1);}。
sd卡读写模块的用法
SD卡读写模块是一种使单片机能够读写SD卡/TF卡的模块,它可以帮助单片机实现大容量存储方案。
该模块内置文件系统,可直接进行文件读写操作,适用于单片机系统。
使用SD卡读写模块时,需要了解其用法和操作。
1. 连接SD卡:将SD卡插入SD卡读写模块的卡槽中,确保卡槽与SD卡之间的接触良好。
2. 连接单片机:将SD卡读写模块与单片机相连接。
通常,SD卡读写模块会提供标准的SPI接口或MMC接口与单片机相连。
根据单片机的接口类型和SD卡读写模块的接口类型,选择合适的连接方式。
3. 初始化模块:在程序中调用SD卡读写模块的初始化函数,对模块进行初始化。
初始化过程中,模块会自动检测SD卡的类型和容量,并配置相应的操作模式。
4. 文件操作:通过调用SD卡读写模块的文件操作函数,实现文件的创建、删除、读取、写入等操作。
例如,可以使用open()函数打开一个文件,使用read()函数读取文件内容,使用write()函数写入文件内容,使用close()函数关闭文件。
5. 目录操作:通过调用SD卡读写模块的目录操作函数,实现目录的创建、删除、遍历等操作。
例如,可以使用mkdir()函数创建一个目录,使用rmdir()函数删除一个目录,使用opendir()函数打开一个目录,使用readdir()函数读取目录下的一个文件,使用closedir()函数关闭目录。
6. 卡操作:通过调用SD卡读写模块的卡操作函数,实现SD卡的格式化、挂载、卸载等操作。
例如,可以使用format()函数格式化SD卡,使用mount()函数挂载SD卡,使用umount()函数卸载SD卡。
需要注意的是,不同的SD卡读写模块可能具有不同的功能和操作方式,因此在使用时需要参考相应的模块手册或开发指南。
同时,为了提高程序的稳定性和可维护性,建议使用模块提供的函数进行操作,而不要直接操作SD卡的底层寄存器。
单片机读写SD卡教程
单片机读写SD卡教程引言:SD卡(Secure Digital Card)是广泛应用于各类数字设备上的一种存储介质。
它小巧轻便,可靠性高,容量大,因此在各种嵌入式系统中都广泛使用。
本教程将介绍如何使用单片机读写SD卡,包括初始化SD卡、读写数据等基本操作。
一、硬件准备在开始之前,我们需要准备以下硬件设备:1.一个支持SPI协议的单片机开发板(例如STC89C51、STM32等);2.一个SD卡插槽,或者是一个带有SD卡插槽的扩展板;3.杜邦线、面包板等连接器。
二、软件准备除了硬件设备,我们还需要准备以下软件工具:1. Keil C51、IAR、Keil MDK等单片机编译工具;2. SD卡相关的库文件,例如FatFs;3.一个用于测试的程序(可以是一个简单的读写数据的程序)。
三、连接SD卡插槽将SD卡插入到对应的插槽中,并将插槽与单片机的硬件SPI接口连接。
根据不同的开发板,连接方式可能有所不同,一般SPI接口包括SCK(时钟线)、MOSI(主机输出从机输入线)、MISO(主机输入从机输出线)和CS(片选线)等。
四、编写读写SD卡的程序在开始编写程序之前,我们需要先了解SD卡的工作原理。
SD卡通过SPI总线与单片机进行通信,通过发送特定的命令和参数实现读写操作。
以下是一个简单的读写SD卡的流程:1.初始化SD卡a.发送CMD0命令,将SD卡设置为SPI模式;b.发送CMD8命令,验证SD卡是否支持高速SPI模式;c.发送ACMD41命令,等待SD卡初始化完成。
2.读写数据a.发送CMD17命令,指定要读取的扇区地址;b.等待SD卡回应,确认读取命令执行成功;c.读取数据;d.发送CMD18命令,继续读取下一个扇区;e.重复步骤c和d,直到读取完所有数据;f.发送CMD12命令,停止读取。
g.发送CMD24命令,指定要写入的扇区地址;h.等待SD卡回应,确认写入命令执行成功;i.写入数据;j.发送CMD25命令,继续写入下一个扇区;k.重复步骤i和j,直到写入完所有数据;l.发送CMD12命令,停止写入。
基于单片机的SD卡读写系统设计
SD卡读写系统设计1文献综述SD卡(Secure Digital Memory Card )中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。
SD卡由日本松下、东芝及美国San Disk公司于1999年8月共同开发研制。
SD卡为9引脚,目的是通过把传输方式由串行变成并行,以提高传输速度。
它最大的特点就是通过加密功能,可以保证数据资料的安全保密,它还具备版权保护技术,所采用的版权保护技术是DVD中使用的CPRM 技术(可刻录介质内容保护)。
大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。
长期以来,闪存卡(SD卡、MMC卡等)因其体积小、功耗低、容量大和非易失性等特点,在嵌入式存储领域的应用越来越广泛。
特别是近年来,随着闪存技术的发展,存卡价格不断下降且存储容量不断提高。
当数据采集系统需要长时间地采集和记录海量数据时,应用SD卡作为存储介质是很好的选择,例如电能检测、温度湿度检测、病人心肺数据记录等。
近年来,单片机系统发展迅猛,这不仅体现在CPU处理能力迅速提升、外界设备与处理器交互能力快速提高,更体现在单片机系统的复杂性日益提高、系统存储容量急剧增大。
这些变化对于数据操作的灵活性提出了越来越高的要求。
因此,如何系统地、灵活地管理数据文件就成了单片机系统开发者无法回避的问题。
文件系统的使用使开发者获得“路径”的概念,从而回避了存储介质的地址空间,不用每次都从头对物理介质进行操作。
文件系统提供清晰明了的API 函数,使上层应用层不再关心底层存储介质,而方便地利用标准接口访问底层存储器。
标准化的接口和层次分明的程序增加了程序的可移植性。
因此在单片机系统中植入文件系统是单片机系统发展的必然结果。
由于该系统是通过SD卡模组向SD卡写入一系列文件,这些文件需要被Windows 系列操作系统正确识别,并进行读写操作,因此,我们选择了应用最为广泛的FAT16文件系统。
FAT文件系统的SD卡单片机读写方法详解
FAT文件系统的SD卡单片机读写方法详解FAT(File Allocation Table)文件系统是一种用于存储和组织文件的文件系统。
SD卡是一种常见的存储设备,广泛应用于单片机系统中。
在单片机中,访问和读写SD卡上的文件需要特定的方法和步骤。
本篇文章将详细介绍FAT文件系统的SD卡在单片机中的读写方法。
1.硬件接口配置:在单片机系统中使用SD卡之前,需要进行硬件接口的配置。
SD卡使用SPI(Serial Peripheral Interface)进行数据传输,因此需要连接SD卡的CLK(时钟)、MISO(主从串行数据输入)、MOSI(主从串行数据输出)和CS(片选)引脚。
在单片机上使能SPI模块,并设置相关寄存器进行SPI传输的配置。
2.初始化SD卡:在开始使用SD卡之前,需要进行初始化操作。
初始化主要包括向SD 卡发送初始化命令和等待SD卡的响应。
初始化命令主要包括发送复位命令(CMD0)和发送初始化命令(CMD1)。
发送命令后,需要等待SD卡发回响应信号,即SD卡的操作完成,才能进行下一步的操作。
3.读取文件目录:在FAT文件系统中,文件目录存储了文件的相关信息,如文件名、文件大小、起始簇号等。
读取文件目录需要进行多次读取操作,以读取目录项的内容。
首先需要读取FAT表,获取根目录的起始簇号。
然后根据起始簇号,读取对应的目录项内容。
目录项的读取可以通过读取SD卡上的扇区数据进行,需要注意目录项的位置和格式。
4.读取文件数据:在FAT文件系统中,文件数据以簇(Cluster)为单位进行存储。
每个簇的大小一般为512字节。
首先需要根据文件目录项中的起始簇号,定位到对应的簇,并读取簇的数据内容。
读取文件数据就是按照簇的顺序进行读取,直到读取到文件结束符为止。
通过读取SD卡上的扇区数据,并根据FAT表中的簇号进行簇的链式读取。
5.写入文件数据:写入文件数据和读取文件数据类似,也是按照簇的顺序进行写入。
sd卡在单片机上的应用
SD卡在现在的日常生活与工作中使用非常广泛,时下已经成为最为通用的数据存储卡。
在诸如MP3、数码相机等设备上也都采用SD卡作为其存储设备。
SD卡之所以得到如此广泛的使用,是因为它价格低廉、存储容量大、使用方便、通用性与安全性强等优点。
既然它有着这么多优点,那么如果将它加入到单片机应用开发系统中来,将使系统变得更加出色。
这就要求对SD卡的硬件与读写时序进行研究。
对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的存储器结构、存储单元组织方式等内容。
要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写,并对其读写速度进行了评估。
下面先来讲解SD卡的读写时序。
<1) SD卡的引脚定义SD卡引脚功能详述:引脚编号SD模式SPI模式名称类型描述名称类型描述1CD/DAT3IO或PP卡检测/数据线3#CS I片选2CMD PP命令/回应DI I数据输入3VSS1S电源地VSS S电源地4VDD S电源VDD S电源5CLK I时钟SCLK I时钟6VSS2S电源地VSS2S电源地7DAT0IO或PP数据线0DO O或PP数据输出8DAT1IO或PP数据线1RSV9DAT2IO或PP数据线2RSV注: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方式进行介绍。
b5E2RGbCAP<2)SPI方式驱动SD卡的方法SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。
单片机与SD卡的接口技术及应用
单片机与SD卡的接口技术及应用SD卡是一种常见的存储介质,被广泛应用于各种电子设备中。
而单片机作为一种微型计算机,常常需要与SD卡进行数据交互,实现数据的读写。
本文将重点讨论单片机与SD卡的接口技术及应用。
首先,为了实现单片机与SD卡之间的通信,必须了解SD卡的工作原理和接口规范。
SD卡采用SPI(Serial Peripheral Interface)或SDIO(SecureDigital InputOutput)接口进行通信。
SPI接口是一种串行通信接口,采用4线全双工通信模式;而SDIO接口则是一种并行接口,采用多线程通信模式。
根据实际需求,选择合适的接口方式。
在选择接口方式后,需要根据SD卡的物理接口进行连接。
SD卡的物理接口分为标准卡接口和微型卡接口,标准卡接口主要用于传统的SD卡,而微型卡接口则用于小型设备。
通过适配器可以实现不同接口类型之间的兼容。
根据SD卡的接口类型,将其与单片机相应的接口引脚连接。
接下来,需要编写相应的软件驱动程序,以实现单片机与SD卡的数据交互。
首先,需要对SD卡进行初始化,包括发送命令和等待SD卡的响应。
接着,可以实现数据的读取和写入操作。
数据读取包括发送读命令、接收数据和校验数据等步骤;数据写入包括发送写命令、发送数据和校验数据等步骤。
通过相应的操作,可以实现对SD卡中存储数据的读取和写入。
在实际应用中,单片机与SD卡的接口技术具有广泛的应用场景。
首先,可以将单片机与SD卡结合,实现数据的存储和读取。
例如在一些嵌入式系统中,单片机可以采集传感器数据,并将其存储在SD卡中,以便后续的数据分析和处理。
同时,通过SD卡的大容量,可以存储更多的数据,提高系统的灵活性和可扩展性。
此外,单片机与SD卡的接口技术还可以被应用于数据传输领域。
通过单片机与SD卡的组合,可以实现数据的高速传输和存储。
例如在一些音频设备中,单片机可以通过SD卡来播放音乐和录制声音,提供更好的用户体验。
单片机读写SD卡API模式读写
单片机读写SD卡最简单最根本的程序处理器:s3c44b0 〔arm7〕SD卡与处理器的引脚连接:MISO -->SIORxD MOSI -->SIOTxD CLK -->SCLK CS-->PE5四个文件:sd_drive.c :用户API函数,移植时不需修改sd_cmd.c:中间层函数,移植时不需修改sd_hard.c:硬件层函数,移植时需修改sd_config.h:一些功能的宏定义,移植时需修改第一次读写SD卡时,需调用SD_Init(void),然后就可以条用Read_Single_Block或者Write_Single_Block进展读写操作注意:进展写操作时,最好不要写前700个扇区,应为这些扇区都是FAT文件系统的重要扇区,一旦误写那么可能会导致SD无法被电脑识别,需格式化。
/*******************************************************文件名:sd_drive.c作用:用户API函数,包括四个函数,读取一块扇区〔512字节〕U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf)写一个扇区〔512字节〕U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf)获取SD卡根本信息,即读CSD存放器信息〔16字节〕:void SD_info()SD卡初始化:U8 SD_Init(void)********************************************************//********************************************功能:读取一个block输入:blk_addr为第几个block,rx_buf为数据缓存区首地址输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD17, blk_addr << 9); //写命令CMD17 rsp = Get_rsp(R1); //获取容许send_clk();}if(i > 99) //如果命令超时,那么执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkread_data(rx_buf); //读取512字节SD_desel();Uart_Printf("succeed in reading the %dst block!!!\n", blk_addr); return NO_ERR;}/********************************************功能:写一个block输入:blk_addr为要写第几个block,tx_buf为数据区输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD24, blk_addr << 9); //写命令CMD24 rsp = Get_rsp(R1); //获取容许send_clk();}if(i > 99) //如果命令超时,那么执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkwrite_data(tx_buf); //读取512字节SD_desel();Uart_Printf("succeed in writing a block!!!\n");return NO_ERR;}/********************************************功能:SD卡初始化输入:无输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 SD_Init(void){U16 rsp = 1;U8 i = 0;spi_port_init(); //初始化spi端口spi_low_speed(); //初始化时SPI的速度必须低于400khzspi_ro_mode(); //只读模式SD_sel(); //选择SD卡for (i = 0;i < 10; i++) //发送至少75个clksend_clk();while(rsp && (i++ < 100)){write_cmd(CMD0, 0); //写命令CMD0rsp = Get_rsp(R1); //获取容许if (rsp == 1) //rsp为0那么初始化成功,为1那么继续写CMD0 break;send_clk();}SD_desel();if (i > 99) //初始化超时处理{Uart_Printf("fail in writing CMD0!!!\n");return INIT_FAIL;}i=0;SD_sel();while(rsp && (i++ < 100)){write_cmd(CMD1, 0); //写CMD1rsp = Get_rsp(R1); //获取容许send_clk();}SD_desel();if (i > 99){Uart_Printf("fail in writing CMD1!!!\n");return INIT_FAIL;}Uart_Printf("SD card init OK!!!\n");spi_high_speed(); //初始化工作全部完毕,SPI进入模式模式spi_rt_mode();return NO_ERR;}/********************************************功能:获取SD卡信息输入:输出:********************************************/void SD_info(){U8 rsp=0;U8 csd[16];SD_sel();write_cmd(CMD9, 0);rsp = Get_rsp(R1);if (rsp != 0){SD_desel();Uart_Printf("error in getting SD info!!!\n");return ;//GET_INFO_ERR;}if (read_register(16, csd) != NO_ERR){SD_desel();return ;}SD_desel();Uart_Printf("SD information :\n");if (csd[0] & 0x40 ==0x40){Uart_Printf("version 2.0\n");Uart_Printf("size is : %d\n",1024 * (csd[8]<<8 + csd[9]));}else{Uart_Printf("version 1.x \n");Uart_Printf("size is : %d MByte\n", ((((csd[6]&0x03)<<10) | (csd[7]<<2) | ((csd[8]&0xC0)>>6) + 1) * (1 << ((((csd[9]&0x03)<<1) | ((csd[10]&0x80)>>7)) + 2)))>>11);}Uart_Printf("max block lenght is : %d\n",1<<(csd[5]&0x0f));}/****************************************************************************文件名:sd_cmd.c作用:中间层函数****************************************************************************//********************************************功能:向SD写入一个命令输入:cmd为命令,addr为SD卡片内地址输出:无********************************************/void write_cmd(U8 cmd, U32 addr){U8 i = 0;U8 temp[4];spi_rt_mode(); //spi发送与接收模式if (cmd <= 13) //前13个命令与地址无关{spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i = 0; i < 4; i++) //发送4个0,协议规定的spi_write_byte(0);if (cmd == 0)spi_write_byte(0x95); //如果是CMD0,那么要发送CRC校正else spi_write_byte(0xff); //非CMD0,那么无需CRC校正,默认为0xFF}else{for(i = 0; i < 4; i++) //将32位的地址分割成4个字节,准备发送temp[i]=(char)(addr >> (24 - 8 * i));spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i =0; i < 4; i++)spi_write_byte(temp[i]); //发送地址,共4个字节spi_write_byte(0xff); //非CMD0,那么无需CRC校正,默认为0xFF}}/********************************************功能:获取SD卡的容许字节,可能是一个或者两个字节输入:type为容许类型输出:容许字节,个数有容许类型而定********************************************/U16 Get_rsp(U8 type){U16 rsp, temp;spi_ro_mode(); //spi只读模式send_clk(); //先发送8个clkrsp = spi_read_byte(); //用spi读取容许字节if (rsp & 0x8)rsp = spi_read_byte();if (type == R2) //如果是R2类型,那么容许为两个字节,须再次读取{temp = rsp << 8;rsp = spi_read_byte();rsp = temp | rsp;}return rsp;}/********************************************功能:读取SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:无********************************************/void read_data(U8 *buffer){U32 i;U8 rsp = 0;while(!(rsp == 0xfe)) //容许字节的最低为0那么代表起始位rsp = spi_read_byte();for(i = 0;i < BLOCK_LEN; i++) //读一个block的内容,一般为512字节buffer[i] = spi_read_byte();for(i = 0; i < 2; i++) //读两个CRC校正码send_clk();send_clk(); //读完毕字节}/********************************************功能:写入SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:********************************************/U8 write_data(U8 *buffer){U16 rsp = 0, tmp = 0, busy = 0, i = 6;spi_rt_mode();spi_write_byte(0xfe); //起始位for(i = 0; i < 512; i++) //发送512个字节spi_write_byte(buffer[i]);for(i = 0; i < 2; i++) //发送16位的CRC校正spi_write_byte(0xff);spi_ro_mode(); //等待容许while(!(rsp == 0x1)){rsp =(U16)spi_read_byte();tmp = rsp;rsp &= 0x11;}while(!(busy == 0xff)) //判忙{busy = spi_read_byte();}tmp &= 0xe;if (tmp == 4)return NO_ERR;else{Uart_Printf("writing error!!!\n");return WR_SGL_BLK_ERR;}}/******************************************** 功能:输入:输出:********************************************/ U8 read_register(U8 len, U8 *buffer){U8 rsp = 0xff, i = 0;spi_ro_mode();while((rsp == 0xff) && (i < 100)){rsp=spi_read_byte();}if (i > 99){Uart_Printf("ERR in readding register!!!\n");return rsp;}if (rsp != 0xfe){buffer[0] = rsp;i = 1;}elsei = 0;for( ; i < len; i++)buffer[i] = spi_read_byte();for(i = 0; i < 2; i++ )send_clk();send_clk();return NO_ERR;}/*******************************************************************文件名:sd_hard.c作用:硬件层函数,移植时需根据处理器或者硬件构造的不同,对该文件的函数进展修改********************************************************************//********************************************功能:使能SPI,发送CLK输入:无输出:无********************************************/void send_clk(){rSIOCON |= (1 << 3); //使能SPIwhile (!(rINTPND & BIT_SIO)); //等待发送完毕rI_ISPC|=BIT_SIO; //去除中断标志}/********************************************功能:用SPI发送一个字节输入:dat为要发送的字节输出:无********************************************/void spi_write_byte(U8 dat){rSIODAT = dat;send_clk(); //SPI发送}/********************************************功能:用SPI读取外设一个字节输入:无输出:读到的一个字节********************************************/U8 spi_read_byte(void){send_clk(); //SPI发送return rSIODAT;}/********************************************功能:初始化SPI的端口输入:无输出:无********************************************/void spi_port_init(){rIVTT = 0;rPCONF = (rPCONF & 0xe3ff) | 0x1B0C00; //除了CLK,MISO,MOSI外,不改变其他位rPUPF |= 0x160; //使能MISO的上拉电阻}/***************************************************************文件名:sd_config.h作用:相关功能的宏定义,以便被以上三个文件调用,便于移植移植时需修改***************************************************************/#ifndef _SD_CONG#define _SD_CONG#define BLOCK_LEN (512) //一个block的长度#define CMD0 0#define CMD1 1 // 读OCR存放器#define CMD9 9 // 读CSD存放器#define CMD10 10 // 读CID存放器#define CMD12 12 // 停顿读多块时的数据传输#define CMD13 13 // 读Card_Status 存放器#define CMD16 16 // 设置块的长度#define CMD17 17 // 读单块#define CMD18 18 // 读多块,直至主机发送CMD12#define CMD24 24 // 写单块#define CMD25 25 // 写多块#define CMD27 27 // 写CSD存放器#define CMD28 28 // Set the write protection bit of the addressed group#define CMD29 29 // Clear the write protection bit of the addressed group#define CMD30 30 // Ask the card for the status of the write protection bits#define CMD32 32 // 设置擦除块的起始地址#define CMD33 33 // 设置擦除块的终止地址#define CMD38 38 //擦除所选择的块#define CMD42 42 // 设置/复位密码或上锁/解锁卡#define CMD55 55 // 制止下一个命令为应用命令#define CMD56 56 // 应用命令的通用I/O#define CMD58 58 // 读OCR存放器#define CMD59 59 // 使能或制止//错误返回#define INIT_FAIL 0#define NO_ERR 1#define WR_SGL_BLK_ERR 2#define GET_INFO_ERR 3#define R1 1 //SD卡容许类型,表示一个字节#define R2 2 //SD卡容许类型,表示两个字节//一下是移植时需修改的内容#define SD_desel() rPDATE=0x20; //使能SD卡#define SD_sel() rPDATE=0x00; //放开SD卡#define spi_high_speed() rSBRDR = 5; //spi高速模式#define spi_low_speed() rSBRDR = 99; //spi低速模式#define spi_ro_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x0 << 5) | (0x0 << 4) | (0x0<< 3) | (0x0 << 2) | 0x1 //只读模式#define spi_rt_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x1 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1 //读写模式#endif。
ATmega128L单片机的MicroSD卡读写
T ECH N OLOGYRE VI E W技术纵横ATmega128L单片机的Micro SD卡读写u西安工程大学朱大锐张团善高文摘要针对电脑横机控制系统对花型文件数据存储的要求,在ATmega128L单片机基础上采用Micro SD卡实现嵌入式文件系统。
文章介绍了Micro SD卡的特点、FAT文件系统、SPI模式协议以及硬件接口的实现。
通过ATmega128L的SPI模式与Micro SD卡进行同步数据传输,实现Micro SD卡的读写,以FAT32文件格式建立相应的文件系统,把数据以文件方式写入Micro SD卡。
通过单片机向Micro SD卡发送读写扇区命令,完成文件的创建、打开、读写、删除等操作。
关键词ATmega128L Micro SD卡串行外设协议文件分配表引言随着工业控制系统功能的增强,系统对于存储介质的安全、容量、性能的要求越来越高。
Micro SD卡是在SD卡和Mini SD卡基础上发展起来的一种多功能存储卡,具备串行和随机存取能力,可以通过专用优化速度的串行接口访问,数据传输可靠,安全性好,传输速度快,存储容量大,体积小,被列为目前全球最小的迷你存储卡。
Micro SD卡支持SD模式和SPI模式。
随着高性能单片机的性能不断提高,利用高性能、低功耗的AVR8位ATmega128L单片机的串行外设接口SPI与Micro SD卡之间进行高速同步数据传输,设计开发了一种嵌入式文件系统。
1硬件电路设计Micro SD卡的接口可以支持两种操作模式:SD模式和SPI模式。
主机系统可以选择其中任一模式。
SD卡模式允许4线的高速数据传输,传输速率高,但是大部分单片机无此接口,使用软件模拟协议复杂。
SPI模式使用简单通用的SPI通道接口就可实现数据传输,目前大多数单片机提供SPI接口。
SPI模式的优势在于可以使用标准主机,从而把外设减少到最低。
SPI模式相对于SD模式的缺点是损失了传输速度;但是目前的微处理器的处理速度越来越高,利用SPI模式大都能满足工程需要。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机读写SD卡最简单最基本的程序处理器:s3c44b0 (arm7)SD卡与处理器的引脚连接:MISO -->SIORxD MOSI -->SIOTxD CLK -->SCLK CS -->PE5四个文件::用户API函数,移植时不需修改:中间层函数,移植时不需修改:硬件层函数,移植时需修改:一些功能的宏定义,移植时需修改第一次读写SD卡时,需调用SD_Init(void),然后就可以条用Read_Single_Block或者Write_Single_Block进行读写操作注意:进行写操作时,最好不要写前700个扇区,应为这些扇区都是FAT文件系统的重要扇区,一旦误写则可能会导致SD无法被电脑识别,需格式化。
/*******************************************************文件名:作用:用户API函数,包括四个函数,读取一块扇区(512字节)U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf)写一个扇区(512字节)U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf)获取SD卡基本信息,即读CSD寄存器信息(16字节):void SD_info()SD卡初始化:U8 SD_Init(void)********************************************************//********************************************功能:读取一个block输入:blk_addr为第几个block,rx_buf为数据缓存区首地址输出:返回NO_ERR则成功,其它则读取失败********************************************/U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD17, blk_addr << 9); //写命令CMD17rsp = Get_rsp(R1); //获取答应send_clk();}if(i > 99) //如果命令超时,则执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkread_data(rx_buf); //读取512字节SD_desel();Uart_Printf("succeed in reading the %dst block!!!\n", blk_addr); return NO_ERR;}/********************************************功能:写一个block输入:blk_addr为要写第几个block,tx_buf为数据区输出:返回NO_ERR则成功,其它则读取失败********************************************/U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD24, blk_addr << 9); //写命令CMD24 rsp = Get_rsp(R1); //获取答应send_clk();}if(i > 99) //如果命令超时,则执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkwrite_data(tx_buf); //读取512字节Uart_Printf("succeed in writing a block!!!\n");return NO_ERR;}/********************************************功能:SD卡初始化输入:无输出:返回NO_ERR则成功,其它则读取失败********************************************/U8 SD_Init(void){U16 rsp = 1;U8 i = 0;spi_port_init(); //初始化spi端口spi_low_speed(); //初始化时SPI的速度必须低于400khz spi_ro_mode(); //只读模式SD_sel(); //选择SD卡for (i = 0;i < 10; i++) //发送至少75个clkwhile(rsp && (i++ < 100)){write_cmd(CMD0, 0); //写命令CMD0rsp = Get_rsp(R1); //获取答应if (rsp == 1) //rsp为0则初始化成功,为1则继续写CMD0 break;send_clk();}SD_desel();if (i > 99) //初始化超时处理{Uart_Printf("fail in writing CMD0!!!\n");return INIT_FAIL;}i=0;SD_sel();while(rsp && (i++ < 100)){write_cmd(CMD1, 0); //写CMD1rsp = Get_rsp(R1); //获取答应send_clk();}SD_desel();if (i > 99){Uart_Printf("fail in writing CMD1!!!\n");return INIT_FAIL;}Uart_Printf("SD card init OK!!!\n");spi_high_speed(); //初始化工作全部完毕,SPI进入模式模式spi_rt_mode();return NO_ERR;/********************************************功能:获取SD卡信息输入:输出:********************************************/ void SD_info(){U8 rsp=0;U8 csd[16];SD_sel();write_cmd(CMD9, 0);rsp = Get_rsp(R1);if (rsp != 0){SD_desel();Uart_Printf("error in getting SD info!!!\n"); return ;//GET_INFO_ERR;if (read_register(16, csd) != NO_ERR){SD_desel();return ;}SD_desel();Uart_Printf("SD information :\n");if (csd[0] & 0x40 ==0x40){Uart_Printf("version \n");Uart_Printf("size is : %d\n",1024 * (csd[8]<<8 + csd[9])); }else{Uart_Printf("version \n");Uart_Printf("size is : %d MByte\n", ((((csd[6]&0x03)<<10) | (csd[7]<<2) |((csd[8]&0xC0)>>6) + 1) * (1 << ((((csd[9]&0x03)<<1) | ((csd[10]&0x80)>>7)) + 2)))>>11); }Uart_Printf("max block lenght is : %d\n",1<<(csd[5]&0x0f));}/****************************************************************************文件名:作用:中间层函数****************************************************************************//********************************************功能:向SD写入一个命令输入:cmd为命令,addr为SD卡片内地址输出:无********************************************/void write_cmd(U8 cmd, U32 addr){U8 i = 0;U8 temp[4];spi_rt_mode(); //spi发送与接收模式if (cmd <= 13) //前13个命令与地址无关{spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i = 0; i < 4; i++) //发送4个0,协议规定的spi_write_byte(0);if (cmd == 0)spi_write_byte(0x95); //如果是CMD0,则要发送CRC校正else spi_write_byte(0xff); //非CMD0,则无需CRC校正,默认为0xFF }else{for(i = 0; i < 4; i++) //将32位的地址分割成4个字节,准备发送temp[i]=(char)(addr >> (24 - 8 * i));spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i =0; i < 4; i++)spi_write_byte(temp[i]); //发送地址,共4个字节spi_write_byte(0xff); //非CMD0,则无需CRC校正,默认为0xFF }}/********************************************功能:获取SD卡的答应字节,可能是一个或者两个字节输入:type为答应类型输出:答应字节,个数有答应类型而定********************************************/U16 Get_rsp(U8 type){U16 rsp, temp;spi_ro_mode(); //spi只读模式send_clk(); //先发送8个clkrsp = spi_read_byte(); //用spi读取答应字节if (rsp & 0x8)rsp = spi_read_byte();if (type == R2) //如果是R2类型,则答应为两个字节,须再次读取{temp = rsp << 8;rsp = spi_read_byte();rsp = temp | rsp;}return rsp;}/********************************************功能:读取SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:无********************************************/void read_data(U8 *buffer){U32 i;U8 rsp = 0;while(!(rsp == 0xfe)) //答应字节的最低为0则代表起始位rsp = spi_read_byte();for(i = 0;i < BLOCK_LEN; i++) //读一个block的内容,一般为512字节buffer[i] = spi_read_byte();for(i = 0; i < 2; i++) //读两个CRC校正码send_clk();send_clk(); //读结束字节}/********************************************功能:写入SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:********************************************/U8 write_data(U8 *buffer){U16 rsp = 0, tmp = 0, busy = 0, i = 6;spi_rt_mode();spi_write_byte(0xfe); //起始位for(i = 0; i < 512; i++) //发送512个字节spi_write_byte(buffer[i]);for(i = 0; i < 2; i++) //发送16位的CRC校正spi_write_byte(0xff);spi_ro_mode(); //等待答应while(!(rsp == 0x1)){rsp =(U16)spi_read_byte(); tmp = rsp;rsp &= 0x11;}while(!(busy == 0xff)) //判忙{busy = spi_read_byte();}tmp &= 0xe;if (tmp == 4)return NO_ERR;else{Uart_Printf("writing error!!!\n");return WR_SGL_BLK_ERR; }}/********************************************功能:输入:输出:********************************************/U8 read_register(U8 len, U8 *buffer){U8 rsp = 0xff, i = 0;spi_ro_mode();while((rsp == 0xff) && (i < 100)){rsp=spi_read_byte();}if (i > 99){Uart_Printf("ERR in readding register!!!\n");return rsp;}if (rsp != 0xfe){buffer[0] = rsp;i = 1;}elsei = 0;for( ; i < len; i++)buffer[i] = spi_read_byte();for(i = 0; i < 2; i++ )send_clk();send_clk();return NO_ERR;}/******************************************************************* 文件名:作用:硬件层函数,移植时需根据处理器或者硬件结构的不同,对该文件的函数进行修改********************************************************************//********************************************功能:使能SPI,发送CLK输入:无输出:无********************************************/void send_clk(){rSIOCON |= (1 << 3); //使能SPIwhile (!(rINTPND & BIT_SIO)); //等待发送完毕rI_ISPC|=BIT_SIO; //清除中断标志}/********************************************功能:用SPI发送一个字节输入:dat为要发送的字节输出:无********************************************/void spi_write_byte(U8 dat){rSIODAT = dat;send_clk(); //SPI发送}/******************************************** 功能:用SPI读取外设一个字节输入:无输出:读到的一个字节********************************************/ U8 spi_read_byte(void){send_clk(); //SPI发送return rSIODAT;}/******************************************** 功能:初始化SPI的端口输入:无输出:无********************************************/void spi_port_init(){rIVTCNT = 0;rPCONF = (rPCONF & 0xe3ff) | 0x1B0C00; //除了CLK,MISO,MOSI外,不改变其他位rPUPF |= 0x160; //使能MISO的上拉电阻}/***************************************************************文件名:作用:相关功能的宏定义,以便被以上三个文件调用,便于移植移植时需修改***************************************************************/#ifndef _SD_CONG#define _SD_CONG#define BLOCK_LEN (512) //一个block的长度#define CMD0 0#define CMD1 1 // 读OCR寄存器#define CMD9 9 // 读CSD寄存器#define CMD10 10 // 读CID寄存器#define CMD12 12 // 停止读多块时的数据传输#define CMD13 13 // 读Card_Status 寄存器#define CMD16 16 // 设置块的长度#define CMD17 17 // 读单块#define CMD18 18 // 读多块,直至主机发送CMD12#define CMD24 24 // 写单块#define CMD25 25 // 写多块#define CMD27 27 // 写CSD寄存器#define CMD28 28 // Set the write protection bit of the addressed group #define CMD29 29 // Clear the write protection bit of the addressed group #define CMD30 30 // Ask the card for the status of the write protection bits #define CMD32 32 // 设置擦除块的起始地址#define CMD33 33 // 设置擦除块的终止地址#define CMD38 38 //擦除所选择的块#define CMD42 42 // 设置/复位密码或上锁/解锁卡#define CMD55 55 // 禁止下一个命令为应用命令#define CMD56 56 // 应用命令的通用I/O#define CMD58 58 // 读OCR寄存器#define CMD59 59 // 使能或禁止//错误返回#define INIT_FAIL 0#define NO_ERR 1#define WR_SGL_BLK_ERR 2#define GET_INFO_ERR 3#define R1 1 //SD卡答应类型,表示一个字节#define R2 2 //SD卡答应类型,表示两个字节//一下是移植时需修改的内容#define SD_desel() rPDATE=0x20; //使能SD卡#define SD_sel() rPDATE=0x00; //放开SD卡#define spi_high_speed() rSBRDR = 5; //spi高速模式#define spi_low_speed() rSBRDR = 99; //spi低速模式#define spi_ro_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x0 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1 //只读模式#define spi_rt_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x1 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1 //读写模式#endif。