SD卡原理及读写程序
SD卡工作原理介绍和工作原理图
SD卡工作原理介绍和工作原理图大容量SD卡在海洋数据存储中的应用本设计使用8 GB的SDHC(High Capacity SD Memory Card,大容量SD存储卡),为了方便卡上数据在操作系统上的读取,以及数据的进一步分析和处理,在SDHC卡上建立了FAT32文件系统。
海洋要素测量系统要求数据存储量大、安全性高,采用可插拔式存储卡是一种不错的选择。
目前,可插拔式存储卡有CF卡、U 盘及SD卡。
CF卡不能与计算机直接通信;U盘需要外扩接口芯片才能与单片机通信,增加了外形尺寸及功耗;而SD卡具有耐用、可靠、安全、容量大、体积小、便于携带和兼容性好等优点,非常适合于测量系统长期的数据存储。
1 SD卡接口的硬件设计STM32F103xx增强型系列是意法半导体公司生产的基于Cortex-M3的高性能的32位RISC内核,工作频率为72 MHz,O端口和连接到2条APB总线的外设。
内置高速存储器(128 KB的闪存和20 KB 的SRAM),以及丰富的增强I,STM32F103xx系列工作于-40,+105?的温度范围,供电电压为2.0,3.6 V,与SD 卡工作电压兼容,一系列的省电模式可满足低功耗应用的要求。
SD卡支持SD模式和SPI模式两种通信方式。
采用SPI模式时,占用较少的I,O资源。
STM32F103VB包含串行外设SPI接口,可方便地与SD卡进行连接。
通过4条信号线即可完成数据的传输,分别是时钟SCLK、主机输入从机输出MISO、主机输出从机输入MOSI和片选CS。
STM32F103VB与SD卡卡座的接口电路如图1所示。
SD卡的最高数据读写速度为10 MB,s,接口电压为2.7,3.6 V,具有9个引脚。
SD卡使用卡座代替传输电缆,减少了环境干扰,降低了出错率,而且1对1传输没有共享信道的问题。
SD卡在SPI模式下各引脚的定义如表1所列。
2 SD卡接口的软件设计本设计采用STM32F103VB自带的串行外设SPI接口与SD卡进行通信,这里只介绍SPI模式的通信方式。
sd卡烧写原理
sd卡烧写原理一、概述SD卡是一种常用的存储设备,它具有体积小、容量大、读写速度快等特点,并且可以被广泛应用于各种嵌入式系统中。
为了在嵌入式系统中使用SD卡,需要将系统镜像烧写到SD卡中,这就需要用到SD卡的烧写原理。
本文将详细介绍SD卡烧写原理。
二、SD卡的结构和工作原理1. SD卡的结构SD卡主要由控制器和闪存芯片组成。
其中,控制器负责与主机进行通信,并且管理闪存芯片的读写操作;而闪存芯片则是实际进行数据存储的地方。
2. SD卡的工作原理当主机需要与SD卡进行通信时,首先会向SD卡发送一个命令。
这个命令包含了操作类型、数据地址、数据长度等信息。
接着,控制器会根据命令类型执行相应的操作,并且将结果返回给主机。
具体来说,如果是读操作,则控制器会从闪存芯片中读取相应的数据并发送给主机;如果是写操作,则控制器会将主机发送过来的数据写入到闪存芯片中。
三、 SD 卡烧写原理1. 烧写流程SD卡烧写的流程主要包括以下几个步骤:(1)格式化SD卡首先需要将SD卡进行格式化,以便清除SD卡中的数据,并且为接下来的烧写操作做好准备。
(2)分区接着,需要对SD卡进行分区。
一般情况下,会将SD卡分为两个区域:一个用于存储引导程序和内核镜像,另一个用于存储文件系统。
(3)烧写引导程序和内核镜像在完成分区之后,就可以开始烧写引导程序和内核镜像了。
这里需要将引导程序和内核镜像按照一定的格式写入到相应的分区中去。
(4)烧写文件系统最后,需要将文件系统烧写到SD卡中。
这里同样需要按照一定的格式将文件系统写入到相应的分区中去。
2. 烧写工具为了方便进行SD卡烧写操作,通常会使用一些专门的工具来完成。
这些工具主要包括以下几种:(1)dd命令dd命令是Linux下的一个命令行工具,可以用来复制文件、转换文件格式等操作。
在进行SD卡烧写时,可以使用dd命令将镜像文件直接写入到SD卡中。
(2)Win32DiskImagerWin32DiskImager是一个Windows下的烧写工具,可以用来将镜像文件烧写到SD卡中。
sd卡的原理
sd卡的原理SD卡,全称Secure Digital Memory Card,是一种便携式存储设备,广泛应用于数码相机、手机、平板电脑等电子设备中。
它的原理是通过内置的闪存芯片来实现数据的存储和读写。
SD卡的原理涉及到存储介质、控制芯片、接口等多个方面,下面将逐一介绍。
首先,我们来看SD卡的存储介质。
SD卡的存储介质主要是闪存芯片,它采用了固态存储技术,不需要外部电源就可以长时间保存数据。
闪存芯片内部由大量的存储单元组成,每个存储单元可以存储一个二进制数据。
通过在存储单元中存储电荷来表示数据的0和1。
这种存储方式可以实现数据的快速读写和长时间保存,是SD卡能够高效工作的基础。
其次,控制芯片也是SD卡原理中的重要组成部分。
控制芯片负责管理SD卡的数据存储和读写过程,它包括了控制器和固件。
控制器负责处理主机发送的指令,控制数据的读写和存储,而固件则是控制芯片的操作系统,负责管理存储单元的分配和释放,保证数据的安全可靠。
控制芯片的性能直接影响了SD卡的读写速度和稳定性。
最后,接口也是SD卡原理中不可或缺的一环。
SD卡的接口包括了电源接口、数据接口和控制接口。
电源接口提供电源供给给SD卡,数据接口用于主机和SD卡之间的数据传输,而控制接口则用于主机发送指令给SD卡。
这些接口的设计直接影响了SD卡的插拔稳定性和数据传输速度,因此在SD卡的设计和制造过程中需要严格把关。
综上所述,SD卡的原理包括了存储介质、控制芯片和接口三个方面。
通过闪存芯片的固态存储技术、控制芯片的数据管理和接口的设计,SD卡实现了高效的数据存储和读写。
在实际应用中,我们需要根据具体的需求选择合适的SD卡类型和容量,以达到最佳的使用效果。
希望本文对SD卡的原理有所帮助,谢谢阅读。
sd卡原理
sd卡原理
SD卡是一种常见的存储设备,它为我们提供了便捷的数据存
储解决方案。
SD卡的原理可以简单概括为以下几个方面:
1. 存储介质:SD卡采用了闪存作为存储介质。
闪存是一种非
易失性存储器,能够持久保存数据,即使在断电的情况下也能保持数据完整性。
2. 控制器:SD卡内部含有一个控制器芯片,该芯片负责管理
和控制存储介质的读写操作。
控制器与主机之间通过SD接口
进行通信。
3. 文件系统:SD卡通常使用FAT32文件系统。
文件系统是一
种将数据组织起来的方式,使得用户可以方便地读取和写入数据。
4. 容量管理:SD卡的容量通常以GB为单位。
控制器芯片会
对存储介质进行划分和管理,将存储空间划分为多个扇区,每个扇区可存储一定大小的数据。
5. 电力管理:SD卡通过引脚接收来自主机的电源供应,其中
包括 3.3V电源线和GND地线。
通过与主机之间的电力交换,SD卡能够正常运行。
6. 数据传输:SD卡采用SPI或SDIO协议进行数据传输。
SPI
协议是一种基于串行通信的协议,而SDIO协议则是一种针对SDIO(Secure Digital Input Output)标准的通信协议。
总体来说,SD卡的原理就是通过控制器和存储介质的协同工作,实现了数据的存储和读写。
用户可以通过SD卡将数据传输到各种设备,方便地实现数据的存储和共享。
SDMMC卡初始化及读写流程分解
二、MMC/SD卡的模型和工作原理PIN脚、SD卡总线、SD卡结构、SD卡寄存器、上电过程SD卡寄存器:OCR:操作电压寄存器: 只读,32位第31位:表示卡上电的状态位CID: 卡身份识别寄存器只读128位生产厂商、产品ID,生产日期和串号等CSD:部分可写128位卡的容量、擦出扇区大小、读写最大数据块的大小、读操作的电流、电压等等 CSR: 卡配置寄存器64位数据位宽RCA:16位相关的卡地址寄存器,卡识别过程中主控器和卡协商出来的一个地址三、SD卡命令和响应格式命令和相应格式SD卡命令,命令类型,ACMD命令响应类型、卡类型、卡状态转换表命令的格式:48位起始位0 方向位(host to card: 1, card to host: 0)内容CRC7 结束位1·响应的格式:48位或者136位卡命令:命令的类型:bc: broadcast without Response 无响应的广播bcr: broadcast with Response 有响应的广播ac: Address(point-to-point) Command: 点对点,DATA0~DATA3数据线上无数据adtc: Adress(point-to-point) Data Transfer Commands 点对点,DATA0~DATA3数据线上有数据CMD0, CMD2, CMD3, CMD55, ACMD41 命令可能会导致卡的状态发生变化响应类型:R1,R1b, R2, R3,R6(SD2.0扩展了R7)扩展内容:SPI工作模式:要知道的特点:只支持一个卡,没有RCA,命令只是MMC/SD的基本的子集SDHC:(支持2GB~32GB):理解CMD8的作用,命令格式和响应,了解CSDV2.0寄存器做了扩展SDIO WIFI:增加CMD52,CMD53CMD8可以通过重新定义先前保留的位,来扩展一些已经存在的命令的新功能。
SD卡读写操作
SD卡操作一、概述1、简介SD卡是基于flash的存储卡。
SD卡和MMC卡的区别在于初始化过程不同。
SD卡的通信协议包括SD和SPI两类。
SD卡使用卡内智能控制模块进行FLASH操作控制,包括协议、安全算法、数据存取、ECC算法、缺陷处理和分析、电源管理、时钟管理。
2、功能介绍2.1 特点1)主机无关的FLASH内存擦除和编程读或写数据,主机只要发送一个带地址的命令,然后等待命令完成,主机无需关心具体操作的完成。
当采用新型的FLASH时,主机代码无需更新。
2)缺陷管理3)错误恢复4)电源管理Flash每个扇区有大约10万次的写寿命,读没有限制。
擦除操作可以加速写操作,因为在写之前会进行擦除。
3 SD总线模式3.1 Negotiating Operation Conditions当主机定义了SD卡不支持的电压范围时,SD卡将处于非活动状态,将忽略所有的总线传输。
要退出非活动状态唯一的方法就是重新上电。
3.2 SD卡获取和识别SD卡总线采用的是单主多从结构,总线上所有卡共用时钟和电源线。
主机依次分别访问每个卡,每个卡的CID寄存器中已预编程了一个唯一的卡标识号,用来区分不同的卡。
主机通过READ_CID命令读取CID寄存器。
CID寄存器在SD卡生产过程中的测试和格式化时被编程,主机只能读取该号。
DAT3线上内置的上拉电阻用来侦测卡。
在数据传输时电阻断开(使用ACMD42)。
3.3 卡状态卡状态分别存放在下面两个区域:卡状态(Card Status),存放在一个32位状态寄存器,在卡响应主机命令时作为数据传送给主机。
SD状态(SD_Status),当主机使用SD_STATUS(ACMD13)命令时,512位以一个数据块的方式发送给主机。
SD_STATUS还包括了和BUS_WIDTH、安全相关位和扩展位等的扩展状态位。
3.4 内存组织数据读写的基本单元是一个字节,可以按要求组织成不同的块。
Block:块大小可以固定,也可以改变,允许的块大小是实际大小等信息存储在CSD寄存器。
SD卡读写
SD卡读写(1)系统硬件文件系统只是数据的组织格式的统称,不涉及到硬件,所以系统的硬件与上篇日志中相同,不作修改。
(2)文件系统结构和读写原理带有文件系统的SD卡的内部结构一般如下表:256MSD卡的文件系统结构文件系统结构说明扇区起始号占用扇区数 Partiton Boot Sector 分区记录扇区 0 1 Reserved Sectors 保留扇区 0 4 FAT1 文件分配表1 4 242 FAT2 文件分配表2 246 242 DIR(FDT) 文件根目录区 488 32 User Data 数据区 520 493560 SD卡的保留扇区中一般不要写入数据,否则可能破坏其文件系统结构,导致操作系统不能识别。
在FAT文件系统中,BPB(Bios ParameterBlock)是一个很重要的参数表,该表通常位于0扇区(保留扇区中的第一个扇区)中的12-36字节,它记录了分区中的一些重要数据如总扇区数、每扇区的字节数、每簇的扇区数、保留扇区数、FAT表占用扇区数等,我这里的256M的SD卡中的BPB表如下:名称占用字节数内容说明BPB_BytesPerSec 2 0x0200 扇区大小为512字节 BPB_SecPerChus 1 0x08 每簇有8个扇区 BPB_RsvdSecCnt 2 0x0004 有4个保留扇区 BPB_NumFATs 1 0x02 有2个FAT表BPB_RootEntCnt 2 0x0200 根目录中可有512个登记项 BPB_TotSec16 20x0000 为0表示总扇区数大于65536BPB_MediaType 1 0xF8 磁盘介质为硬盘 BPB_FATSize16 2 0x00F2 每个FAT表占242个扇区 BPB_SecPerTrk 2 0x3F 每个磁道有63个扇区 BPB_NumHeads 2 0x00FF 磁头数为255BPB_HiddSec 4 0x00000000 有0个隐藏扇区 BPB_TotSec32 4 0x00078A00 共有494080个扇区保留扇区之后是文件分配表,FAT16文件系统有两份文件分配表(FAT),FAT的大小可以在BPB中查到。
sd卡数据读写流程
sd卡数据读写流程一、概述SD卡是一种常用的存储设备,应用广泛。
在进行SD卡数据读写操作时,需要了解其基本流程及相关细节。
本文将详细介绍SD卡数据读写流程。
二、准备工作1. 确认SD卡类型:根据需求选择合适的SD卡类型,如标准SD卡、Mini SD卡、Micro SD卡等。
2. 准备读写设备:需要使用支持SD卡的读写设备,如读卡器、手机、相机等。
3. 系统环境:根据不同操作系统选择相应的驱动程序和开发工具。
三、初始化SD卡1. 电源接口:将SD卡插入读写设备中,并接通电源。
2. 查找CMD线:通过CMD线查找到SD卡,并发送复位命令。
3. 发送初始化命令:发送初始化命令后,等待SD卡响应并返回状态码。
四、读取CID和CSD寄存器信息1. 发送CMD10命令:通过CMD10命令可以获取CID寄存器信息。
2. 发送CMD9命令:通过CMD9命令可以获取CSD寄存器信息。
五、设置Block长度1. 发送CMD16命令:通过CMD16命令设置Block长度,即每次读取或写入的字节数。
六、数据传输1. 读取数据:发送CMD17命令,指定读取的起始地址和读取的Block数量,等待SD卡响应并返回数据。
2. 写入数据:发送CMD24命令,指定写入的起始地址和写入的Block数量,等待SD卡响应并写入数据。
七、结束操作1. 发送CMD12命令:结束操作前需要发送CMD12命令,以停止多块传输。
2. 断开电源:操作完成后需要断开SD卡电源。
八、注意事项1. SD卡在进行读写操作时需要保持稳定的电压和供电。
2. 操作过程中需要注意各种状态码及其含义。
3. 合理选择Block长度可以提高读写速度。
以上就是SD卡数据读写流程的详细介绍。
在实际应用中,还需要根据具体情况进行合理调整和优化。
SD卡的结构原理和基本读写操作方式
SD卡的结构原理和基本读写操作方式摘要:本文首先介绍了SD Memory Card ( Secure D ig ita l MemoryCard)的基本结构和原理,着重对SD 卡的命令字和操作流程进行介绍。
接着研究了三星32位嵌入式处理器S3C2410与SD 卡硬件接口电路及其对SD卡的基本读写操作方式。
1 引言SD卡( Secure DigitalMemory Card)是一种基于Flash的新一代存储器,它着重数据存储的安全、容量和性能,是许多便携式电子产品如数码相机、手提电话, PDA 等理想的外部存储介质。
2 SD的基本概念2. 1 SD的通信协议SD卡系统可以在两种通信协议下工作: SD协议和SP I协议。
用户可以在硬件初始化时自由选择SD卡系统的通信协议。
对于特定的硬件电路,用户只需使用一种通信协议即可。
本文根据笔者的硬件,仅讨论最常用的SD协议。
2. 2 SD数据传输方式SD支持两种数据传输方式: 1 - bit方式(标准总线)和4- bit方式(宽总线)。
在1 - bit方式下,数据仅仅在数据线0(DAT[ 0 ])上传输。
在4 - bit方式下,数据在4 根数据线(DAT[ 3: 0 ])上同时传输。
在4 - bit数据传输方式下,最高的数据传输速率可达100Mb / sec。
表1列出了在两种方式下SD接口信号的定义。
上电后,缺省状态下系统工作于1 - bit方式。
在SD卡处于传输状态时,用户可以自由地更改为1 - bit或4 - bit方式。
2. 3 SD 通信原理SD总线是一个星型的总线结构,系统中允许有一个主控器,最多可达十个从设备( SD卡)。
在系统初始化时,主控器分别为每一个设备分配一个设备地址,此后主控器就可以根据此设备地址独立操作该设备。
SD总线通信是基于命令和数据位流的,每一个数据流都包括一个起始位和一个结束位。
每一个SD命令表征一个卡操作的开始。
SD命令由命令线(CMD)进行传输。
sd卡工作原理
sd卡工作原理SD卡(Secure Digital card)是一种用于存储数字信息的储存设备。
它是由Toshiba、SanDisk和Panasonic联合推出的一种便携式存储设备,通常用于存储照片、音乐、视频等文件。
那么,SD卡是如何工作的呢?下面,我们来了解一下SD卡的工作原理。
1. SD卡的基本结构SD卡由多个部分组成,包括控制器、存储器、晶振器和接口等。
其中,控制器是SD卡的关键部分,它负责管理SD卡的读写操作和数据交换。
存储器则是用于存储数据的部分,晶振器主要用于产生时钟信号,接口则用于与设备进行通信。
2. SD卡的读写过程当需要读取SD卡内的数据时,设备会向SD卡发送请求,SD卡通过控制器进行数据读取操作,并将读取的数据返回给设备。
当需要向SD卡写入数据时,设备会发送数据到SD卡,SD卡通过控制器将数据存储到存储器中。
3. SD卡的文件系统SD卡中的文件系统是通过文件分配表(FAT)来进行管理的。
FAT是一种简单的文件系统,它将文件分割成多个簇,每个簇的大小为固定值。
当存储一个文件时,FAT会分配一定数量的簇来存储该文件,并将每个簇的使用情况记录在一个文件分配表中。
当需要读取文件时,设备通过文件分配表来查找文件并读取相应的簇。
4. SD卡的数据安全SD卡具有一些安全功能,例如密码保护和数据加密等。
密码保护功能通过限制访问SD卡的设备来保护数据安全。
数据加密功能则是将数据加密后再存储到SD卡中,从而保证数据的安全性。
总之,SD卡是一种方便快捷的存储设备,它可以轻松地存储和传输各种类型的数据。
了解SD卡的工作原理有助于更好地使用和维护这种设备。
sd卡识别流程
sd卡识别流程SD卡是一种常见的存储设备,广泛应用于移动设备、数码相机等电子产品中。
本文将从SD卡的识别流程入手,介绍SD卡的工作原理和识别过程。
一、SD卡的工作原理SD卡是一种闪存存储卡,采用了非易失性存储技术,可以长期保存数据。
它由存储芯片、控制器和外壳等组成。
存储芯片负责数据的存储,控制器负责控制数据的读写和传输。
SD卡通过与设备的接口连接,实现数据的读取和写入。
二、SD卡的识别流程1. 插卡检测:当将SD卡插入设备的SD卡槽时,设备会通过插卡检测电路检测SD卡的插入状态。
如果检测到插卡动作,设备会进入下一步的识别流程。
2. 供电和时钟:设备会为SD卡提供电源,并发送时钟信号给SD 卡,以确保SD卡的正常运行。
同时,设备还会发送复位信号给SD 卡,使其回到初始状态。
3. 发送命令:设备会通过SD卡接口向SD卡发送命令,以控制SD 卡的工作。
常见的命令有初始化命令、读取命令、写入命令等。
4. 响应命令:SD卡接收到设备发送的命令后,会进行相应的处理并返回响应结果。
响应结果包括命令执行状态、数据传输状态等。
5. 初始化:设备会向SD卡发送初始化命令,以对SD卡进行初始化设置。
初始化过程中,设备会向SD卡发送一系列的命令和参数,以便建立设备与SD卡之间的通信和数据传输。
6. 容量识别:设备会向SD卡发送容量识别命令,以获取SD卡的容量信息。
SD卡会返回容量信息给设备,设备根据这些信息来判断SD卡的容量大小和可用空间。
7. 文件系统识别:设备会读取SD卡的文件系统信息,以确定SD 卡的文件系统类型和目录结构。
常见的文件系统类型有FAT32、exFAT等。
8. 数据读写:设备通过命令和参数,向SD卡发送读写命令,以读取或写入数据。
SD卡接收到命令后,会执行相应的操作,并返回读取或写入的数据给设备。
9. 结束操作:设备在完成数据读写或其他操作后,会发送结束命令给SD卡,以结束与SD卡的通信和数据传输。
sd卡保护开关原理
sd卡保护开关原理SD卡保护开关原理SD卡保护开关是一种用于控制SD卡读写状态的开关装置。
它的主要作用是保护SD卡内部的数据不被意外读写或删除,以确保数据的安全性和完整性。
下面将介绍SD卡保护开关的原理和工作方式。
一、SD卡概述SD卡,全称Secure Digital Card,是一种常见的存储设备,广泛应用于数码相机、手机、平板电脑等电子设备中。
它具有容量大、体积小、易于携带等特点,因此备受消费者青睐。
二、SD卡的读写原理SD卡内部由存储芯片和控制芯片组成。
当电子设备需要读取或写入SD卡中的数据时,首先会向控制芯片发送指令,然后控制芯片通过与存储芯片的通信接口,实现对存储芯片中数据的读取或写入。
三、SD卡保护开关的作用SD卡保护开关是一种物理开关,位于SD卡的侧面。
它的作用是控制SD卡的读写状态,从而保护SD卡中的数据不被非法读写或删除。
四、SD卡保护开关的原理SD卡保护开关的原理很简单,它通过一个小开关来控制SD卡的读写状态。
当保护开关打开时,即开关处于“开”状态,SD卡处于可读写状态;当保护开关关闭时,即开关处于“关”状态,SD卡处于只读状态,无法进行写操作。
五、SD卡保护开关的工作方式SD卡保护开关的工作方式可以分为两种情况:1. 保护开关打开时,SD卡处于可读写状态。
此时,电子设备可以向SD卡中写入数据,也可以从SD卡中读取数据。
这种状态下,用户可以自由地对SD卡进行读写操作,方便对数据进行修改和更新。
2. 保护开关关闭时,SD卡处于只读状态。
此时,SD卡只能被电子设备读取,无法进行写操作。
这种状态下,即使电子设备误操作或受到病毒攻击,也不会对SD卡中的数据产生影响。
因此,保护开关的关闭状态可以有效地保护SD卡中的数据安全。
六、SD卡保护开关的应用SD卡保护开关广泛应用于各类电子设备中,特别是那些需要保护数据安全的设备。
例如,数码相机中的SD卡保护开关可以避免用户误删照片;手机中的SD卡保护开关可以防止病毒通过SD卡传播;平板电脑中的SD卡保护开关可以保护重要文件不被非法操作。
sd工作原理
sd工作原理
SD卡(Secure Digital Card)是一种可移动存储设备,用于存储和传输数据。
它由闪存芯片和控制器芯片组成。
SD卡的工作原理如下:
1. 插入SD卡:将SD卡插入到设备的SD卡槽中。
2. 识别SD卡:设备通过识别SD卡槽中的接触点,确定SD 卡的存在。
3. 供电和信号传输:设备向SD卡提供电源,并通过SD卡槽中的引脚与SD卡进行数据传输。
4. 控制器识别:控制器芯片通过与SD卡进行通信,识别SD 卡的容量、类型和速度等信息。
5. 数据读写:设备通过控制器芯片向SD卡发送读写命令,控制芯片将读写请求翻译成SD卡能够理解的指令,SD卡将数据从闪存芯片中读取或写入。
6. 数据传输:SD卡通过与控制器芯片的数据引脚进行数据传输,将读取或写入的数据传送到设备中或从设备中接收数据。
7. 读写完成:数据传输完成后,SD卡将传输成功的信息发送给设备,设备通过控制器芯片接收并处理这些信息。
8. 移除SD卡:在使用完毕后,可以通过操作系统或设备设置中的“安全移除”功能,断开SD卡与设备的连接,并从SD卡槽中取出SD卡。
总结:SD卡的工作原理是通过设备识别和供电、控制器与SD卡的通信、控制器翻译读写请求、通过数据引脚进行数据传输等步骤,实现数据存储和传输的功能。
SD卡的初始化和读写程序
/****************************************************************************** *****SPI模式读写SD卡SD卡初始化过程:1. 初始化STM32的SPI接口使用低速模式2. 延时至少74clock3. 发送CMD0,需要返回0x01,进入Idle状态4. 循环发送CMD55+ACMD41,直到返回0x00,进入Ready状态5. 设置读写block大小为512byte5. 把STM32的SPI设置为高速模式读一个block块的过程1. 发送CMD17(单块)或CMD18(多块)读命令,返回0x002. 接收数据开始令牌0xfe + 正式数据512Bytes + CRC 校验2Bytes写一个block块的过程1. 发送CMD24(单块)或CMD25(多块)写命令,返回0x002. 发送数据开始令牌0xfe + 正式数据512Bytes + CRC校验2Bytes-----------------------------------------------------------------------------* ----------------------------------------------* | STM32F10x | MSD Pin |* ----------------------------------------------* | PE.3 | ChipSelect 1 |* | PA.7 / MOSI | DataIn 2 |* | | GND 3 (0 V) |* | | VDD 4 (3.3 V) |* | PA.5 / SCLK | Clock 5 |* | | GND 6 (0 V) |* | PA.6 / MISO | DataOut 7 |* -----------------------------------------------******************************************************************************* ****//* Includes ------------------------------------------------------------------*///#include "stm32f10x_lib.h"#include "stm32f10x.h"#include "hardwareinit.h"/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*/#define sd_cs_1 GPIO_SetBits(GPIOB,GPIO_Pin_12)#define sd_cs_0 GPIO_ResetBits(GPIOB,GPIO_Pin_12)#define sd_check GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15)/* Select MSD Card: ChipSelect pin low *///#define MSD_CS_LOW() GPIO_ResetBits(GPIOE, GPIO_Pin_3)/* Deselect MSD Card: ChipSelect pin high *///#define MSD_CS_HIGH() GPIO_SetBits(GPIOE, GPIO_Pin_3)//SD传输数据结束后是否释放总线宏定义#define NO_RELEASE 0#define RELEASE 1// SD卡类型定义#define SD_TYPE_MMC 0#define SD_TYPE_V1 1#define SD_TYPE_V2 2#define SD_TYPE_V2HC 4// SD卡指令表#define CMD0 0 //卡复位#define CMD1 1#define CMD9 9 //命令9 ,读CSD数据#define CMD10 10 //命令10,读CID数据#define CMD12 12 //命令12,停止数据传输#define CMD16 16 //命令16,设置SectorSize 应返回0x00#define CMD17 17 //命令17,读sector#define CMD18 18 //命令18,读Multi sector#define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block #define CMD24 24 //命令24,写sector#define CMD25 25 //命令25,写Multi sector#define ACMD41 41 //命令41,应返回0x00#define CMD55 55 //命令55,应返回0x01#define CMD58 58 //命令58,读OCR信息#define CMD59 59 //命令59,使能/禁止CRC,应返回0x00//数据写入回应字意义#define MSD_DATA_OK 0x05#define MSD_DATA_CRC_ERROR 0x0B#define MSD_DATA_WRITE_ERROR 0x0D#define MSD_DATA_OTHER_ERROR 0xFF//SD卡回应标记字#define MSD_RESPONSE_NO_ERROR 0x00#define MSD_IN_IDLE_STA TE 0x01#define MSD_ERASE_RESET 0x02#define MSD_ILLEGAL_COMMAND 0x04#define MSD_COM_CRC_ERROR 0x08#define MSD_ERASE_SEQUENCE_ERROR 0x10#define MSD_ADDRESS_ERROR 0x20#define MSD_PARAMETER_ERROR 0x40#define MSD_RESPONSE_FAILURE 0xFF#define Dummy_Byte 0xA5 //0xff/* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*///u8 Dummy_Byte = 0xa5; //0xff;u8 SD_Type; //SD卡的类型u8 buf[512];/* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*/FlagStatus sd_insert_check(void);u8 SD_WaitReady(void); //等待SD卡就绪u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc); //SD卡发送一个命令u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);u8 SD_Init(void); //SD卡初始化u8 SD_Idle_Sta(void); //设置SD卡到挂起模式u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据u8 SD_GetCID(u8 *cid_data); //读SD卡CIDu8 SD_GetCSD(u8 *csd_data); //读SD卡CSDu32 SD_GetCapacity(void); //取SD卡容量//USB 读卡器SD卡操作函数//u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite);//u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);u8 SD_ReadSingleBlock(u32 sector, u8 *buffer); //读一个sectoru8 SD_WriteSingleBlock(u32 sector, const u8 *buffer); //写一个sectoru8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count); //读多个sectoru8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count);//写多个sectoru8 SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes);//读取一byte//--------------------------------spi speed setting-------------------------/****************************************************************************** ** Function Name : SPI_Config* Description : Initializes the SPI1 and CS pins.* Input : None* Output : None* Return : None******************************************************************************* /void SPI_Config(u16 BaudRatePrescaler){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;/* GPIOA and GPIOC Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);/* SPI1 Periph clock enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);/* Configure SPI2 pins: SCK, MISO and MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure PE3 pin: CS pin */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_12);/* SPI1 Config */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = BaudRatePrescaler;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI2, &SPI_InitStructure);/* SPI1 enable */SPI_Cmd(SPI2, ENABLE);}void spi_high_speed(void){//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//SPI_BaudRatePrescaler_256;//SPI_Init(SPI2, &SPI_InitStructure);SPI_Config(SPI_BaudRatePrescaler_4);}void spi_low_speed(void){//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//SPI_BaudRatePrescaler_4;//SPI_Init(SPI2, &SPI_InitStructure);SPI_Config(SPI_BaudRatePrescaler_256);}//---------------sd_insert_check---------------------------FlagStatus sd_insert_check(void){FlagStatus card_exist_state;if(!sd_check){card_exist_state = SET;}else{card_exist_state = RESET;}return card_exist_state;}//-------------------------------------------------------------------------/****************************************************************************** ** Function Name : SPI_FLASH_SendByte* Description : Sends a byte through the SPI interface and return the byte* received from the SPI bus.* Input : byte : byte to send.* Output : None* Return : The value of the received byte.******************************************************************************* /u8 SPIx_ReadWriteByte(u8 byte){/* Loop while DR register in not emplty */while ((SPI2->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);/* Send byte through the SPI1 peripheral *///SPI_I2S_SendData(SPI2, byte);SPI2->DR = byte;/* Wait to receive a byte */while((SPI2->SR &SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);/* Return the byte read from the SPI bus *///return SPI_I2S_ReceiveData(SPI2);return SPI2->DR;}//u8 SPIx_ReadWriteByte(u8 byte)//{/* Loop while DR register in not emplty *///while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)/* Send byte through the SPI1 peripheral *///SPI_I2S_SendData(SPI2, byte);/* Wait to receive a byte *///while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);/* Return the byte read from the SPI bus *///return SPI_I2S_ReceiveData(SPI2);//}/****************************************************************************** ** Function Name : SPI_FLASH_ReadByte* Description : Reads a byte from the SPI Flash.* This function must be used only if the Start_Read_Sequence* function has been previously called.* Input : None* Output : None* Return : Byte Read from the SPI Flash.******************************************************************************* /u8 SPI_ReadByte(void){return (SPIx_ReadWriteByte(Dummy_Byte));}//-----------------------------------------------------------------------------------------------------------------------------------//等待SD卡回应//Response:要得到的回应值//返回值:0,成功得到了该回应值// 其他,得到回应值失败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;//正确回应}}//------------------------------------------------------------------------//等待SD卡写入完成//返回值:0,成功;// 其他,错误代码;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: //CRC校验错误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) //读到数据为0,则数据还未写完成{retry++;//delay_us(10); //SD卡写等待需要较长的时间if(retry>=0XFFFFFFFE)return 0XFF; //等待失败了};return 0; //成功了}//-----------------------------------------------------------------//向SD卡发送一个命令//输入: u8 cmd 命令// u32 arg 命令参数// u8 crc crc校验值//返回值:SD卡返回的响应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卡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;//在总线上额外增加8个时钟,让SD卡完成剩下的工作SPIx_ReadWriteByte(0xFF);//返回状态值return r1;}//-----------------------------------------------------------//向SD卡发送一个命令(结束是不失能片选,还有后续数据传来)//输入:u8 cmd 命令// u32 arg 命令参数// u8 crc crc校验值//返回值:SD卡返回的响应u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc){u8 Retry=0;u8 r1;SPIx_ReadWriteByte(0xff);//高速写命令延时SPIx_ReadWriteByte(0xff);sd_cs_0;//片选端置低,选中SD卡//发送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;}//------------------------------------------------------------//把SD卡设置到挂起模式//返回值:0,成功设置// 1,设置失败u8 SD_Idle_Sta(void){u16 i;u8 retry;for(i=0;i<0xf00;i++); //纯延时,等待SD卡上电完成//先产生>74个脉冲,让SD卡自己初始化完成for(i=0;i<10;i++)SPIx_ReadWriteByte(0xFF);//-----------------SD卡复位到idle开始-----------------//循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态//超时则直接退出retry = 0;do{//发送CMD0,让SD卡进入IDLE状态i = SD_SendCommand(CMD0, 0, 0x95);retry++;}while((i!=0x01)&&(retry<200));//跳出循环后,检查原因:初始化成功?or 重试超时?if(retry==200)return 1; //失败return 0; //成功}//---------------------------------------------------------------//初始化SD卡//如果成功返回,则会自动设置SPI速度为18Mhz//返回值:0:NO_ERR// 1:TIME_OUT// 99:NO_CARDu8 SD_Init(void){u8 r1; // 存放SD卡的返回值u16 retry; // 用来进行超时计数u8 buff[6];/*//设置硬件上与SD卡相关联的控制引脚输出//避免NRF24L01/W25X16等的影响RCC->APB2ENR|=1<<2; //PORTA时钟使能GPIOA->CRL&=0XFFF000FF;GPIOA->CRL|=0X00033300;//PA2.3.4 推挽GPIOA->ODR|=0X7<<2; //PA2.3.4上拉SPIx_Init();SPIx_SetSpeed(SPI_SPEED_256);//设置到低速模式*/spi_low_speed();sd_cs_1;if(SD_Idle_Sta()) return 1;//超时返回1 设置到idle 模式失败//-----------------SD卡复位到idle结束-----------------//获取卡片的SD版本信息sd_cs_0;r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);//如果卡片版本信息是v1.0版本的,即r1=0x05,则进行以下初始化if(r1 == 0x05){//设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC SD_Type = SD_TYPE_V1;//如果是V1.0卡,CMD8指令后没有后续数据//片选置高,结束本次命令sd_cs_1;//多发8个CLK,让SD结束后续操作SPIx_ReadWriteByte(0xFF);//-----------------SD卡、MMC卡初始化开始-----------------//发卡初始化指令CMD55+ACMD41// 如果有应答,说明是SD卡,且初始化完成// 没有回应,说明是MMC卡,额外进行相应初始化retry = 0;do{//先发CMD55,应返回0x01;否则出错r1 = SD_SendCommand(CMD55, 0, 0);if(r1 == 0XFF)return r1;//只要不是0xff,就接着发送//得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次r1 = SD_SendCommand(ACMD41, 0, 0);retry++;}while((r1!=0x00) && (retry<400));// 判断是超时还是得到正确回应// 若有回应:是SD卡;没有回应:是MMC卡//----------MMC卡额外初始化操作开始------------if(retry==400){retry = 0;//发送MMC卡初始化命令(没有测试)do{r1 = SD_SendCommand(1,0,0);retry++;}while((r1!=0x00)&& (retry<400));if(retry==400)return 1; //MMC卡初始化超时//写入卡类型SD_Type = SD_TYPE_MMC;}//----------MMC卡额外初始化操作结束------------//设置SPI为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();SPIx_ReadWriteByte(0xFF);//禁止CRC校验r1 = SD_SendCommand(CMD59, 0, 0x95);if(r1 != 0x00)return r1; //命令错误,返回r1//设置Sector Sizer1 = SD_SendCommand(CMD16, 512, 0x95);if(r1 != 0x00)return r1;//命令错误,返回r1//-----------------SD卡、MMC卡初始化结束-----------------}//SD卡为V1.0版本的初始化结束//下面是V2.0卡的初始化//其中需要读取OCR数据,判断是SD2.0还是SD2.0HC卡else if(r1 == 0x01){//V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令buff[0] = SPIx_ReadWriteByte(0xFF); //should be 0x00buff[1] = SPIx_ReadWriteByte(0xFF); //should be 0x00buff[2] = SPIx_ReadWriteByte(0xFF); //should be 0x01buff[3] = SPIx_ReadWriteByte(0xFF); //should be 0xAAsd_cs_1;SPIx_ReadWriteByte(0xFF);//the next 8 clocks//判断该卡是否支持2.7V-3.6V的电压范围//if(buff[2]==0x01 && buff[3]==0xAA) //不判断,让其支持的卡更多{retry = 0;//发卡初始化指令CMD55+ACMD41do{r1 = SD_SendCommand(CMD55, 0, 0);if(r1!=0x01)return r1;r1 = SD_SendCommand(ACMD41, 0x40000000, 0);if(retry>200)return r1; //超时则返回r1状态}while(r1!=0);//初始化指令发送完成,接下来获取OCR信息//-----------鉴别SD2.0卡版本开始-----------r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);if(r1!=0x00){sd_cs_1;//释放SD片选信号return r1; //如果命令没有返回正确应答,直接退出,返回应答}//读OCR指令发出后,紧接着是4字节的OCR信息buff[0] = SPIx_ReadWriteByte(0xFF);buff[1] = SPIx_ReadWriteByte(0xFF);buff[2] = SPIx_ReadWriteByte(0xFF);buff[3] = SPIx_ReadWriteByte(0xFF);//OCR接收完成,片选置高sd_cs_1;SPIx_ReadWriteByte(0xFF);//检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC //如果CCS=1:SDHC CCS=0:SD2.0if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC; //检查CCSelse SD_Type = SD_TYPE_V2;//-----------鉴别SD2.0卡版本结束-----------//设置SPI为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();}}return r1;}//---------------------------------------------------------------------//从SD卡中读回指定长度的数据,放置在给定位置//输入: u8 *data(存放读回数据的内存>len)// u16 len(数据长度)// u8 release(传输完成后是否释放总线CS置高0:不释放1:释放)//返回值:0:NO_ERR// other:错误信息u8 SD_ReceiveData(u8 *data, u16 len, u8 release){// 启动一次传输sd_cs_0;if(SD_GetResponse(0xFE)) //等待SD卡发回数据起始令牌0xFE {sd_cs_1;return 1;}while(len--)//开始接收数据{*data=SPIx_ReadWriteByte(0xFF);data++;}//下面是2个伪CRC(dummy CRC)SPIx_ReadWriteByte(0xFF);SPIx_ReadWriteByte(0xFF);if(release==RELEASE)//按需释放总线,将CS置高{sd_cs_1;//传输结束SPIx_ReadWriteByte(0xFF);}return 0;}//-----------------------------------------------------------------//获取SD卡的CID信息,包括制造商信息//输入: u8 *cid_data(存放CID的内存,至少16Byte)//返回值:0:NO_ERR// 1:TIME_OUT// other:错误信息u8 SD_GetCID(u8 *cid_data){u8 r1;//发CMD10命令,读CIDr1 = SD_SendCommand(CMD10,0,0xFF);if(r1 != 0x00)return r1; //没返回正确应答,则退出,报SD_ReceiveData(cid_data,16,RELEASE);//接收16个字节的return 0;}//-------------------------------------------------------------------//获取SD卡的CSD信息,包括容量和速度信息//输入:u8 *cid_data(存放CID的内存,至少16Byte)//返回值:0:NO_ERR// 1:TIME_OUT// other:错误信息u8 SD_GetCSD(u8 *csd_data){u8 r1;r1=SD_SendCommand(CMD9,0,0xFF);//发CMD9命令,读CSD if(r1)return r1; //没返回正确应答,则退出,报错SD_ReceiveData(csd_data, 16, RELEASE);//接收16个字节的数据return 0;}//------------------------------------------------------------------------ //获取SD卡的容量(字节)//返回值:0:取容量出错// 其他:SD卡的容量(字节)u32 SD_GetCapacity(void){u8 csd[16];u32 Capacity;u8 r1;u16 i;u16 temp;//取CSD信息,如果期间出错,返回0if(SD_GetCSD(csd)!=0) return 0;//如果为SDHC卡,按照下面方式计算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);//C_SIZE_MULTr1 = csd[9]&0x03;r1<<=1;r1 += ((csd[10]&0x80)>>7);r1+=2;//BLOCKNRtemp = 1;while(r1){temp*=2;r1--;}Capacity = ((u32)(i+1))*((u32)temp);// READ_BL_LENi = csd[5]&0x0f;//BLOCK_LENtemp = 1;while(i){temp*=2;i--;}//The final resultCapacity *= (u32)temp;//字节为单位}return (u32)Capacity;}//--------------------------------------------------------------------//读SD卡的一个block//输入:u32 sector 取地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)//返回值:0:成功// other:失败u8 SD_ReadSingleBlock(u32 sector, u8 *buffer){u8 r1;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);//spi_high_speed();//如果不是SDHC,给定的是sector地址,将其转换成byte地址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;}/*u8 SD_ReadSingleBlock(u32 sector, u8 *buffer){u8 r1;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);spi_high_speed();//如果不是SDHC,给定的是sector地址,将其转换成byte地址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;}*///----------------------------------------------------------------------//写入SD卡的一个block(未实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)//返回值:0:成功// other:失败u8 SD_WriteSingleBlock(u32 sector, const u8 *data){u8 r1;u16 i;u16 retry;//设置为高速模式//SPIx_SetSpeed(SPI_SPEED_4);//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type!=SD_TYPE_V2HC){sector = sector<<9;}r1 = SD_SendCommand(CMD24, sector, 0x00);if(r1 != 0x00){return r1; //应答不正确,直接返回}//开始准备数据传输sd_cs_0;//先放3个空数据,等待SD卡准备好SPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//放起始令牌0xFESPIx_ReadWriteByte(0xFE);//放一个sector的数据for(i=0;i<512;i++){SPIx_ReadWriteByte(*data++);}//发2个Byte的dummy CRCSPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//等待SD卡应答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; //写入超时返回1}}//写入完成,片选置1sd_cs_1;SPIx_ReadWriteByte(0xff);return 0;}//-------------------------------------------------------------------//读SD卡的多个block(实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)// u8 count 连续读count个block//返回值:0:成功// other:失败u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count) {u8 r1;//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式//如果不是SDHC,将sector地址转成byte地址if(SD_Type!=SD_TYPE_V2HC)sector = sector<<9;//SD_WaitDataReady();//发读多块命令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;}//------------------------------------------------------------------------//写入SD卡的N个block(未实际测试过)//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buffer 数据存储地址(大小至少512byte)// u8 count 写入的block数目//返回值:0:成功// other:失败u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count){u8 r1;u16 i;//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式if(SD_Type != SD_TYPE_V2HC)sector = sector<<9;//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count, 0x00);//如果目标卡不是MMC卡,启用ACMD23指令使能预擦除r1 = SD_SendCommand(CMD25, sector, 0x00);//发多块写入指令if(r1 != 0x00)return r1; //应答不正确,直接返回sd_cs_0;//开始准备数据传输SPIx_ReadWriteByte(0xff);//先放3个空数据,等待SD卡准备好SPIx_ReadWriteByte(0xff);//--------下面是N个sector写入的循环部分do{//放起始令牌0xFC 表明是多块写入SPIx_ReadWriteByte(0xFC);//放一个sector的数据for(i=0;i<512;i++){SPIx_ReadWriteByte(*data++);}//发2个Byte的dummy CRCSPIx_ReadWriteByte(0xff);SPIx_ReadWriteByte(0xff);//等待SD卡应答r1 = SPIx_ReadWriteByte(0xff);if((r1&0x1F)!=0x05){sd_cs_1; //如果应答为报错,则带错误代码直接退出return r1;}//等待SD卡写入完成if(SD_WaitDataReady()==1){sd_cs_1; //等待SD卡写入完成超时,直接退出报错return 1;}}while(--count);//本sector数据传输完成//发结束传输令牌0xFDr1 = SPIx_ReadWriteByte(0xFD);if(r1==0x00){count = 0xfe;}if(SD_WaitDataReady()) //等待准备好{sd_cs_1;return 1;}//写入完成,片选置1sd_cs_1;SPIx_ReadWriteByte(0xff);return count; //返回count值,如果写完则count=0,否则count=1 }//-----------------------------------------------------------------------------//在指定扇区,从offset开始读出bytes个字节//输入:u32 sector 扇区地址(sector值,非物理地址)// u8 *buf 数据存储地址(大小<=512byte)// u16 offset 在扇区里面的偏移量// u16 bytes 要读出的字节数//返回值:0:成功// other:失败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;//选中SD卡if(SD_GetResponse(0xFE))//等待SD卡发回数据起始令牌0xFE{sd_cs_1; //关闭SD卡return 1;//读取失败}for(i=0;i<offset;i++)SPIx_ReadWriteByte(0xff);//跳过offset位for(;i<offset+bytes;i++)*buf++=SPIx_ReadWriteByte(0xff);//读取有用数据for(;i<512;i++) SPIx_ReadWriteByte(0xff); //读出剩余字节SPIx_ReadWriteByte(0xff);//发送伪CRC码SPIx_ReadWriteByte(0xff);sd_cs_1;//关闭SD卡return 0;}。
sd卡数据读写流程
sd卡数据读写流程SD卡是一种常见的存储媒介,它具有轻便、易携带、容量大、存储速度快等优势。
SD卡数据读写流程是指将数据从SD卡中读取出来或将数据写入SD卡中的整个过程。
一、SD卡的物理结构SD卡主要由控制器、记忆芯片和接口组成。
控制器负责管理SD卡的读写操作;记忆芯片是存储数据的核心部件,它采用闪存技术,可存储数据并保持数据不易丢失;接口是SD卡与主控制器进行通信的桥梁,一般采用SPI(串行外设接口)或SDIO(SD输入输出)接口。
二、SD卡读写流程1.初始化SD卡当主控制器接通SD卡电源时,首先要进行初始化操作。
初始化操作主要包括向SD卡发送复位命令、读取SD卡的OCR(操作条件寄存器)以及设置SPI或SDIO接口的工作参数等操作。
2.读取SD卡信息在SD卡初始化成功后,主控制器通过SPI或SDIO接口向SD 卡发送命令,读取SD卡ID信息、SD卡容量、SD卡速度等重要参数。
这些信息将在数据读写时起到重要作用。
3.读取文件SD卡上的文件存储在文件系统中,主控制器需要先读取文件系统,找到要读取的文件所在的位置。
一般情况下,文件系统采用FAT32格式,主控制器需要读取文件系统启动区扇区信息,从而找到文件所在扇区及其起始地址。
4.读取数据在找到文件所在位置后,主控制器就可以根据文件系统的信息,向SD卡发送读操作指令,读取文件数据。
读取数据时,主控制器需要根据SD卡的速度、数据传输模式等参数设置接口波特率、时序等参数。
5.写入数据SD卡写数据流程与读数据基本相同,只是主控制器需要向SD卡发送写操作指令,将数据写入SD卡中。
写入数据时,主控制器需要根据SD卡的容量、速度等参数设置写入数据的起始位置、写入数据的长度、写入数据的校验和等参数。
6.关闭SD卡当读写操作完成后,主控制器需要向SD卡发送停止指令,将SD卡彻底关闭。
关闭SD卡可以避免SD卡数据丢失、损坏等问题。
三、SD卡的数据保护SD卡存储的数据非常重要,因此在SD卡的读写过程中,需要采取一定的措施保护数据。
sd卡工作原理
sd卡工作原理
SD卡(Secure Digital Card),是一种使用闪存技术存储数据的存储设备。
它采用了非易失性存储硅片作为存储介质,通过控制接口来读写数据。
SD卡的工作原理如下:
1. 电压传输:SD卡通过引脚传输电信号来读取和写入数据。
其中,CMD(命令)和CLK(时钟)两个引脚用于控制SD 卡的操作,DAT(数据)引脚用于读写数据。
2. 初始化和寻址:当SD卡插入设备中时,设备会发送特定的命令来初始化SD卡。
初始化完成后,设备会向SD卡发送寻址命令,用于确定要读写的数据区域。
3. 数据读写:通过引脚传输的命令和数据来实现数据的读写操作。
设备会发送相应的命令告知SD卡需要读取或写入数据,并通过DAT引脚传输具体的数据。
4. 数据保护:SD卡采用了多种数据保护机制来确保数据的完整性和安全性。
例如,CRC(循环冗余校验)用于检验传输过程中数据是否发生错误,密码保护和加密机制用于保护数据的安全性。
5. 垃圾回收:由于闪存技术的特性,SD卡的存储单元在多次擦除和写入后会出现损耗。
为了延长SD卡的使用寿命,SD 卡会自动进行垃圾回收操作,将已经无效的数据块标记为可用
状态,以便后续的数据写入。
总的来说,SD卡通过电压传输、初始化和寻址、数据读写、
数据保护和垃圾回收等步骤来实现数据的存储和读取。
它是一种方便、可靠的存储设备,广泛应用于各种便携式电子设备中。
AVRSD卡基础原理及读写经典c程序
1、简介:SD卡〔Secure Digital Memory Card〕是一种为满足平安性、容量、性能和使用环境等各方面的需求而设计的一种新型存储器件,SD卡允许在两种模式下工作,即SD模式和SPI模式,本系统采用SPI模式。
本小节仅简要介绍在SPI模式下,STM32处理器如何读写SD卡,如果读者如希望详细了解SD卡,可以参考相关资料。
SD 卡部构造及引脚如下列图所示2、SD卡管脚图:3、SPI模式下SD各管脚名称为:注:一般SD有两种模式:SD模式和SPI模式,管脚定义如下:〔A〕、SD MODE 1、CD/DATA3 2、CMD 3、VSS1 4、VDD 5、CLK 6、VSS2 7、DATA08、DATA1 9、DATA2〔B〕、SPI MODE 1、CS 2、DI 3、VSS 4、VDD 5、SCLK 6、VSS2 7、DO 8、RSV 9、RSVSD 卡主要引脚和功能为:CLK:时钟信号,每个时钟周期传输一个命令或数据位,频率可在0~25MHz之间变化,SD卡的总线管理器可以不受任何限制的自由产生0~25MHz 的频率;CMD:双向命令和回复线,命令是一次主机到从卡操作的开场,命令可以是从主机到单卡寻址,也可以是到所有卡;回复是对之前命令的答复,回复可以来自单卡或所有卡;DAT0~3:数据线,数据可以从卡传向主机也可以从主机传向卡。
SD卡以命令形式来控制SD卡的读写等操作。
可根据命令对多块或单块进展读写操作。
在SPI模式下其命令由6个字节构成,其中高位在前。
SD卡命令的格式如表1所示,其中相关参数可以查阅SD卡规。
4、MicroSD卡管脚图:5、MicroSD卡管脚名称:SD 卡与MicroSD卡仅仅是封装上的不同,MicroSD卡更小,大小上和一个SIM 卡差不多,但是协议与SD卡一样。
一般我们用单片机操作SD 卡时,都不需要对FAT分区表信息做处理,原因如下:1〕、操作FAT分区表要增加程序代码量、增加SRAM的消耗,对于便携应用来说代码大小和占用SRAM的多少至关重要。
SDMMC卡初始化及读写流程讲述
二、MMC/SD卡的模型和工作原理PIN脚、SD卡总线、SD卡结构、SD卡寄存器、上电过程SD卡寄存器:OCR:操作电压寄存器: 只读,32位第31位:表示卡上电的状态位CID: 卡身份识别寄存器只读128位生产厂商、产品ID,生产日期和串号等CSD:部分可写128位卡的容量、擦出扇区大小、读写最大数据块的大小、读操作的电流、电压等等 CSR: 卡配置寄存器64位数据位宽RCA:16位相关的卡地址寄存器,卡识别过程中主控器和卡协商出来的一个地址三、SD卡命令和响应格式命令和相应格式SD卡命令,命令类型,ACMD命令响应类型、卡类型、卡状态转换表命令的格式:48位起始位0 方向位(host to card: 1, card to host: 0)内容CRC7 结束位1·响应的格式:48位或者136位卡命令:命令的类型:bc: broadcast without Response 无响应的广播bcr: broadcast with Response 有响应的广播ac: Address(point-to-point) Command: 点对点,DATA0~DATA3数据线上无数据adtc: Adress(point-to-point) Data Transfer Commands 点对点,DATA0~DATA3数据线上有数据CMD0, CMD2, CMD3, CMD55, ACMD41 命令可能会导致卡的状态发生变化响应类型:R1,R1b, R2, R3,R6(SD2.0扩展了R7)扩展内容:SPI工作模式:要知道的特点:只支持一个卡,没有RCA,命令只是MMC/SD的基本的子集SDHC:(支持2GB~32GB):理解CMD8的作用,命令格式和响应,了解CSDV2.0寄存器做了扩展SDIO WIFI:增加CMD52,CMD53CMD8可以通过重新定义先前保留的位,来扩展一些已经存在的命令的新功能。
SD卡硬件原理图及其读写程序
SD卡硬件原理图及其读写程序2011-03-28 17:45转载自sail_007最终编辑sail_007 最近开始整理以前画过原理图和程序今天先整理出了SD卡的硬件和SPI方式的读写程序。
今后会陆续写把DS1302时钟芯片GPRS模块CAN总线通信PWM数控电压也整理出来。
一方面是想帮自己总结一下另外如果还能帮助到其他的单片机爱好者那也就更好了。
当然水平有限整理出来的东西可能也有许多错误的地方也请高手能指出不胜感激。
先发张SD卡的原理图。
说明我用的是5V单片机SD卡则是3.3v如果直接连接引脚长期使用会影响SD卡寿命。
我一开始选用了普通的光耦触发可能是导通速率不够快无法实现SPI通信后来我就改用9013就行了。
下图上US1是SD卡壳其实1到9引脚对应了SD卡的9个引脚10号引脚是卡插入标志也就是说当有SD卡插入时10号引脚会接3.3v的地这样单片机就可以查询是否有卡了。
在SPI总线模式下CS为主控制器向卡发送的片选信号SCLK为主控制器向卡发送的时钟信号INDataIn为主控制器向卡发送的单向数据信号MISODataOut为卡向主控制器发送的单向数据信号。
程序如下说明我用的是freescale的DP256单片机该单片机有SPI 设备接口只要将其初始化成功便可完成通信设置。
uchar CMD0RespCMD1RespCMD59RespCMD16RespCMD9RespC MD17RespCMD24RespCMD58Resp void SD_Initializevoiduchar csdbuf16TempValue ucharcmdparam4recbuf600resp4resptype uchar sendbuf600 ulong len ulong i ulong BlockAdd SD_InsertDetect Pim.pts.bit.pts70 //cs0 SD_SPIDelay25 Pim.pts.bit.pts71 //cs1 SD_SPIDelay2Pim.ddrs.bit.ddrs70 //pin cs direction Spi0.spicr1.bit.spe0 //spi enable Pim.ddrs.bit.ddrs71 //pin cs directionPim.pts.bit.pts70//cs0 Spi0.spibr.byte0x02 //8MHz31.25kHz0x07-0x00 Spi0.spicr1.bit.mstr1 //master modeSpi0.spicr1.bit.ssoe1 //ss output enable Spi0.spicr1.bit.cpol0//cpol0 //cpol1 070215 Spi0.spicr1.bit.cpha0 //cpha0Spi0.spicr2.byte0x18 //normal drive input pullup TempValueSpi0.spisr.byte//clear SPIF first step TempValueSpi0.spidr.byte//clear SPIF second stepSpi0.spicr1.bit.spe1 //spi enable CMD0RespSD_ResetSDCMD1RespSD_ActiveInit whileCMD1Resp0x01CMD1RespSD_ActiveInit 白开水易拉罐主页博客相册个人档案好友i贴吧看看Ta是谁吧页码1/5Ww2011/6/26/wolf9s/blog/item/47e2a620 212d80268744f98c.htmlvoid SD_SPIDelayuint value uint i for i 0 i valuei SPI_SendByte0xFF // 发送0xFF clock out 0xFF uchar SD_ResetSDvoid uchar param4 0000respSD_SendCmdCMD0 param SD_R1 resp return resp / 函数名称:void SPI_SendByte Name: void SPI_SendByte 功能描述: 通过SPI接口发送一个字节Function: send a byte by SPI interface 输入: INT8U byte: 发送的字节Input: INT8U byte: the byte that will be send 输出: 无Output: NULL / voidSPI_SendByteuchar byte uchar TempValue Spi0.spidr.byte byte / 发送数据放入SPI数据寄存器/ while0 Spi0.spisr.byte 0x80 / 等待SPIF置位即等待数据发送完毕/ / wait for SPIF being set that is wait for finishing of data being send / TempValueSpi0.spidr.byte / 函数名称: INT8U SPI_RecByte Name:INT8U SPI_RecByte 功能描述: 从SPI接口接收一个字节Function: receive a byte from SPI interface 输入: 无Input: NULL 输出: 收到的字节Output: the byte that be received / uchar SPI_RecBytevoid uint ReadCounter ReadCounter0Spi0.spidr.byte 0xFF while0 Spi0.spisr.byte 0x80 / 等待SPIF 置位即等待收到数据/ ReadCounter ifReadCounter25 break / wait for SPIF being set that is wait for being received data / returnSpi0.spidr.byte / 读取收到的字节read the byte received / / 函数名称: //INT8U SD_SendCmd Name: INT8USD_SendCmd 功能描述: 向卡发送命令并取得响应Function: send command to the cardand get a response 输入: INT8U cmd : 命令字Input: INT8U cmd : command byteINT8U param : 命令参数长度为4字节INT8U param :command parameterlength is 4 bytes INT8U resptype : 响应类型INT8U resptype: response type INT8U resp : 响应长度为1-5字节INT8U resp : responselength is 1-5 bytes 输出: 0: 正确0: 错误码Output: 0: right 0: error code / voidSD_SendCmduchar cmd uchar paramuchar resptype uchar resp long irlen uchar tmp Pim.pts.bit.pts70//cs0 SPI_SendBytecmd0x3F 0x40 / 发送命令头和命令字send command header and word / for i 3 i 0 i-- SPI_SendByteparami / 发送参数send parameters / SPI_SendByte0x95 / CRC校验码只用于第1个命令CRConly used for the first command / rlen 0 switch resptype / 根据不同的命令得到不同的响应长度/ / according various commandget the various response length / case 1: rlen 1 break case 2: rlen 2 break case 4: rlen 5 break default:SPI_SendByte0xFF Pim.pts.bit.pts71 break i 0 do / 等待响应响应的开始位为0 / / Wait for a responsea response is a start bitzero / tmp SPI_RecByte i while tmp 0x80 0 iSD_CMD_TIMEOUT for i rlen - 1 i 0 i-- respi tmp tmpSPI_RecByte / 循环的最后发送8clock at the last recycleclock out 8 clock / Pim.pts.bit.pts71//cs1 // return SD_NO_ERR //new statement 页码2/5Ww2011/6/26/wolf9s/blog/item/47e2a620 212d80268744f98c.html/ 函数名称: INT8U SD_ReadBlockName: INT8U SD_ReadBlock 功能描述: 从SD卡中读一个块Function: read a single block from sd card 输入: INT32U blockaddr: 块地址Input: INT32U blockaddr: address of block INT8U recbuf : 接收缓冲区长度512Bytes INT8U recbuf : the buffer of receivelength is 512Bytes 输出: 0: 正确0: 错误码Output: 0: right 0: error code / uchar SD_ReadBlockulong blockaddr uchar recbuf uchar param4resp // if blockaddrsds.block_num // return SD_ERR_OVER_CARDRANGE / 操作超出卡容量范围operate over the card range /SD_PackParamparam blockaddr / 将参数转化为字节形式change the parameter to bytes form / SD_SendCmdCMD17 param SD_R1 resp SD_ReadBlockDataSD_BLOCKSIZE recbuf/ 读出数据read data from sd card / return resp / 函数名称: INT8U SD_ReadBlockData Name: INT8USD_ReadBlockData 功能描述: 从SD卡中读取数据块Function: read block data from sd card 输入: INT32U len : 长度Input: INT32U len : length INT8U recbuf : 接收缓冲区INT8U recbuf : the buffer of receive 输出: 0: 正确0: 错误码Output: 0: right 0: error code / voidSD_ReadBlockDataulong len uchar recbuf uchar tmp ulong i 0 Pim.pts.bit.pts70//cs0 do / 等待接收数据开始令牌0xFE wait for receiving data start token 0xFE / tmp SPI_RecByte iwhiletmp 0xFF i SD_CMD_TIMEOUT for i 0 i len i recbufi SPI_RecByte / 接收数据receive data / i SPI_RecByte i i 0:错误码Output: 0: right 0: error code ucharSD_SetBlockLenulong length uchar param4respretSD_PackParamparam length //将参数转化为字节形式change the parameter to bytes form SD_SendCmdCMD16 paramSD_R1 resp return resp / / 函数名称: void SD_PackParam Name: void SD_PackParam 功能描述: 将32位的参数转为字节形式Function: change 32bit parameter to bytes form 输入: INT8U parameter: 字节参数缓冲区Input: INT8U parameter: the buffer of bytes parameter INT32U value : 32位参数INT32U value : 32bit parameter 输出: 无Output: NULL / void SD_PackParamuchar parameter ulong value valuevalue512 parameter3 ucharvalue 24 parameter2 ucharvalue 16 parameter1 ucharvalue 8 parameter0 ucharvalue / 函数名称: INT8USD_WriteBlock Name: INT8U SD_WriteBlock 功能描述: 向SD卡中写入一个块Function: write a block to sd card 输入: INT32U blockaddr: 块地址Input: INT32U blockaddr: address of block INT8U sendbuf : 发送缓冲区长度512Bytes INT8U sendbuf : the buffer of sendlength is 512Bytes 输出: 0: 正确0: 错误码Output: 0: right 0: error code / ucharSD_WriteBlockulong blockaddr uchar sendbuf 页码3/5Ww2011/6/26/wolf9s/blog/item/47e2a620 212d80268744f98c.html uchar param4resprettmp2 ulong i // if blockaddr sds.block_num // returnSD_ERR_OVER_CARDRANGE / 操作超出卡容量范围operate over the card range / SD_PackParamparam blockaddr / 将参数转化为字节形式change the parameter to bytes form / SD_SendCmdCMD24 param SD_R1 resp / 写单块命令write single block / SD_WriteBlockData0 SD_BLOCKSIZE sendbuf / 写入数据write data / return resp / 函数名称: INT8USD_WriteBlockData Name: INT8U SD_WriteBlockData 功能描述: 向sd卡写数据块Function: write block data to sd card 输入: INT8U bmulti : 是否为多块操作1:是0:否Input:INT8U bmulti : multi blocks operate 1:Y 0:N INT32U len : 长度INT32U len : length INT8U sendbuf: 发送缓冲区INT8U sendbuf : the buffer of send 输出: 0: 正确0: 错误码Output: 0: right 0: error code / void SD_WriteBlockDatauchar bmulti ulong len uchar sendbuf uint i uchar tmp Pim.pts.bit.pts70//cs0 SPI_SendByte0xFF / 开始发送数据之前发送8个clock clock out 8 clk before start / if bmulti 1SPI_SendByteSD_TOK_WRITE_STARTBLOCK_M / 写多块开始令牌start token of write multi blocks / elseSPI_SendByteSD_TOK_WRITE_STARTBLOCK / 写单块开始令牌start token of write single block / for i 0 i len iSPI_SendBytesendbufi / 发送数据send data / SPI_SendBytei 8 0xFF SPI_SendBytei 0xFF / 发送CRC16校验码send CRC16 check code / tmp SPI_RecByte Pim.pts.bit.pts71//cs1 SD_WaitBusy void SD_WaitBusy uchar tmpiPim.pts.bit.pts70//cs0 i0 do / 等待忙结束wait for being busy end / tmp SPI_RecByte i while tmp 0xFF i 10000 / 忙时收到的值为0xFF always receive 0xFF when card is busy /Pim.pts.bit.pts71//cs1 / 函数名称: void SD_HardWareInit Name: void SD_HardWareInit 功能描述: 初始化访问SD卡的硬件条件Function: initialize the hardware condiction that access sd card 输入: 无Input: NULL 输出: 无Output: NULL / uchar SD_InsertDetect uchar InflagifPim.ptp.bit.ptp30//sd insert Inflag1 else Inflag0 return Inflag 类别默认分类添加到搜藏分享到i贴吧浏览57 评论0 上一篇sd卡的读写转下一篇一般SD卡和SDHC卡读写函数 .c -... 最近读者网友评论发表评论姓名哦没他发内容插入表情▼ 闪光字页码4/5Ww2011/6/26/wolf9s/blog/item/47e2a620 212d80268744f98c.html 同时将此文章分享给好友验证码请点击后输入四位验证码字母不区分大小写发表评论�0�82011 Baidu看看Ta是谁吧页码5/5Ww2011/6/26/wolf9s/blog/item/47e2a620 212d80268744f98c.html。
SD卡读写操作详细说明
SD卡读写操作详细说明SD卡(Secure Digital Card)是一种常见的存储设备,广泛应用于各种数码设备,如相机、手机、音乐播放器等。
SD卡读写操作是指对SD卡进行数据的读取和写入操作。
本文将详细介绍SD卡的读写操作流程和相关细节。
一、SD卡读写操作的基本原理SD卡采用了Flash存储技术,数据的读写是通过对存储芯片中的电荷进行控制实现的。
每个存储单元可以存储一个位(0或1),多个存储单元可以组成字节、块等不同大小的数据单元。
二、SD卡的初始化在进行SD卡的读写操作之前,首先需要对SD卡进行初始化。
SD卡的初始化包括以下几个步骤:1.插入SD卡:将SD卡插入到SD卡插槽中。
2.电源供给:给SD卡供电,使其可以正常工作。
3.寻卡:通过命令与SD卡进行通信,找到SD卡并识别其属性和参数。
三、SD卡的读操作SD卡的读操作是指从SD卡中读取数据。
SD卡的读操作流程如下:1.发送读命令:通过控制器向SD卡发送读命令,告知SD卡要读取的数据的起始地址和长度。
2.接收应答:SD卡接收到读命令后,会返回一个应答信号,确认是否接收到了读命令。
3.读取数据:当SD卡接收到读命令后,在指定的地址范围内读取数据,并将数据传输给控制器。
4.数据传输:控制器接收到SD卡传输的数据后,将数据转发给主机或其他设备进行处理。
四、SD卡的写操作SD卡的写操作是指向SD卡中写入数据。
SD卡的写操作流程如下:1.发送写命令:通过控制器向SD卡发送写命令,告知SD卡要写入的数据的起始地址和长度。
2.接收应答:SD卡接收到写命令后,会返回一个应答信号,确认是否接收到了写命令。
3.写入数据:当SD卡接收到写命令后,在指定的地址范围内写入数据。
4.数据传输:控制器向SD卡传输要写入的数据,SD卡接收到数据后进行存储。
五、SD卡的块操作SD卡的读写操作是以块为单位进行的,一个块的大小一般为512字节。
SD卡的块操作流程如下:1.发送块命令:通过控制器向SD卡发送块命令,告知SD卡要进行块操作的起始块号和块数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SD_PORT |= (1< SD_PORT &= ~(1< SD_PORT |= (1< SD_PORT &= ~(1< SD_PORT |= (1< SD_PORT &= ~(1<
#define SD_MISO_IN
(SD_PIN&(1<
//------------------------------------------------------------// 错误号 //------------------------------------------------------------#define INIT_CMD0_ERROR #define INIT_CMD1_ERROR #define WRITE_BLOCK_ERROR #define READ_BLOCK_ERROR #define TRUE 0x01 0xFF 0xFE 0xFD 0xFC
以下是做 SD 卡试验时使用的电路图:
SD 卡试验时使用的电路 图.JPG
SD_CS/ 连接到单片机的片选 SD 管脚, 只有单片机设置 SD_CS/为低电平时才可以操作 SD 卡。 MOSI 连接单片机 SPI 总线的 MOSI 管脚(SPI 数据 输入),单片机从这个管脚读取 SD 卡内 的数据。 MISO 连接单片机 SPI 总线的 MISO 管脚(SPI 数据输出)、单片机通过这个管脚向 SD 卡内写 入数据。 SCK 连接单片机 SPI 总线的 SCK(SPI 时钟) SD 管脚实际上在 SD 卡内部连接到了 GND,当 SD 插座上没插入 SD 卡时,单 片机从这个管 脚能读到高电平(前提是使用单片机内部上拉输入,或者外部增加一个上拉电阻),一旦插入 SD 卡,这个管脚就变成低电平,这个功能用来检测是否 插入 SD 卡。 RSV1 和 RSV2 是保留功能管脚,不需要操作。 MicroSD 卡的连接和 SD 卡大同小异,只是 MicroSD 卡比 SD 卡少 一个 GND 管脚,所以不能 使用上面做的这种插入卡的检测,实际上现在很多 SD 卡/MicroSD 卡插座都有插入检测管脚, 当然,一分钱一分货,价格上当然 也要贵一些 顺便提一下,普通 SD 卡插座最多 5 块钱。 SPI 命令格式
1、 简介: SD 卡(Secure Digital Memory Card)是一种为满足安全性、容量、性能和使用环境等各方面 的需求而设计的一种新型存储器件,SD 卡允许在两种模式下工作,即 SD 模式和 SPI 模式,本 系统采用 SPI 模式。本小节仅简要介绍在 SPI 模式下,STM32 处理器如何读写 SD 卡,如果读 者如希望详细了解 SD 卡,可以参考相关资料。 SD 卡内部结构及引脚如下图所示:
//**************************************************************************** // 初始化 MMC/SD 卡为 SPI 模式 unsigned char SD_Init(void) //**************************************************************************** { unsigned char retry,temp; unsigned char i;
SD 卡主要引脚和功能为: CLK:时钟信号,每个时钟周期传输一个命令或数据位,频率可在 0~25MHz 之间变化,SD 卡 的总线管理器可以不受任何限制的自由产生 0~25MHz 的频率; CMD:双向命令和回复线,命令是一次主机到从卡操作的开始,命令可以是从主机到单卡寻址, 也可以是到所有卡;回复是对之前命令的回答,回复可以来自单 卡或所有卡; DAT0~3:数据线,数据可以从卡传向主机也可以从主机传向卡。 SD 卡以命令形式来控制 SD 卡的读写等操作。可根据命令对多块或单块进行读写操作。在 SPI 模式下其命令由 6 个字节构成,其中高位在前。SD 卡命令 的格式如表 1 所示,其中相关参数 可以查阅 SD 卡规范。
1) 、 操作 FAT 分区表要增加程序代码量、 增加 SRAM 的消耗, 对于便携应用来说代码大小和 占 用 SRAM 的多少至关重要。 2)、即使我们对 FAT 分区表不做任何了解,实际上我们一样可以向 SD 卡上写入数据,这就表 明使用 FAT 对我们做数 据存储应用来说如同鸡肋。 3) 、 耗费大量经历和时间去了解 FAT 分区表对于我们做嵌入式软件开发的人来说有些得不偿失。 4)、SD 卡支持 两种操作模式,SD 模式和 SPI 模式,SPI 模式做 SD 数据操作时根本不需要 知道 FAT,这时候 SD 卡对于我们来说实际上就是个大的、快速的、方便的、容 量可变的外部 存储器。 基于以上原因, 一般情况下对 SD 卡的操作只需要了解 SPI 通讯就可以了, 而现在大部分单片机 都有 SPI 接口,那么操作 SD 卡 易如反掌。
Byte 1 Byte2-5 Byte 6
7
6
5
0
31
0
7
0
0
1
Command
Command Argument
CRC
1பைடு நூலகம்
以下是一个简单的测试 SD 卡读 写的程序, 程序是基于 Atmega128 单片机编写的, 对于 Atmega 的其他单片机仅需要做管脚改动就可以使用,其他单片机更改要更大。 sd.h //****************************************************************** //SPI 各线所占用的端口 #define SD_SS #define SD_SCK #define SD_MOSI #define SD_MISO PB6 PB1 PB2 PB3
SD 卡内部图.JPG
2、SD 卡管脚图:
SD 卡图.JPG
3、SPI 模式下 SD 各管脚名称为: sd 卡:
SPI 模式下 SD 各管脚名称 为.JPG
注: 一般 SD 有两种模式:SD 模式和 SPI 模式,管脚定义如下: (A)、SD MODE 1、CD/DATA3 8、DATA1 9、DATA2 (B) 、 SPI MODE 1、 CS RSV 9、RSV 2、 DI 3、 VSS 4、 VDD 5、 SCLK 6、 VSS2 7、 DO 8、 2、CMD 3、VSS1 4、VDD 5、CLK 6、VSS2 7、DATA0
0x40 + 13 0x40 + 16 0x40 + 17 0x40 + 18 0x40 + 24 0x40 + 25
//片选关(MMC/SD-Card Invalid) #define SD_Disable() SD_SS_H
//片选开 (MMC/SD-Card Active) #define SD_Enable() SD_SS_L
while(!(UCSR0A & (1 << UDRE0))); /* UDR0 = content; /* 发送数据 */
判断上次发送有没有完成
*/
} void putstr(unsigned char *s) {
while(*s) { putchar(*s); s++; }
}
//**************************************************************************** // 端口初始化 void SD_Port_Init(void) //**************************************************************************** { SD_PORT SD_DDR SD_DDR } |= (1<< |= (1<<< &= ~(1<
//******************************************************************
#define SD_DDR #define SD_PORT #define SD_PIN
DDRB PORTB PINB
#define SD_SS_H #define SDSS_L #define SD_SCK_H #define SD_SCK_L #define SD_MOSI_H #define SD_MOSI_L
#define SD_STOP_TRANSMISSION #define SD_SEND_STATUS #define SD_SET_BLOCKLEN #define SD_READ_BLOCK #define SD_READ_MULTI_BLOCK #define SD_WRITE_BLOCK #define SD_WRITE_MULTI_BLOCK
4、MicroSD 卡管脚图:
MicroSD 卡管脚图.JPG
5、MicroSD 卡管脚名称:
MicroSD 卡管脚名 称.JPG
SD 卡与 MicroSD 卡仅仅是封装上的不同,MicroSD 卡更小,大小上和一个 SIM 卡差不多,但 是协议与 SD 卡相同。 一般我们用单片机操作 SD 卡时,都不需要对 FAT 分区表信息做处理,原因如下:
SD_TEST.C //****************************************************************************************/ //ICC-AVR application builder : 03-5-20 8:39:11 // Target : M128 // Crystal: 3.6864Mhz
//------------------------------------------------------------// MMC/SD 命令(命令号从 40 开始,只列出基本命令,并没有都使用) //------------------------------------------------------------#define SD_RESET #define SD_INIT #define SD_READ_CSD #define SD_READ_CID 0x40 + 0 0x40 + 1 0x40 + 9 0x40 + 10 0x40 + 12