sd卡读写程序(SDcardreadandwriteprogram)

合集下载

SD卡读写

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卡的可能。

出于对安全工作的考虑,有必要解决电平匹配问题。

sd卡数据读写流程

sd卡数据读写流程

SD卡数据读写流程引言SD卡(Secure Digital Card)是一种常用的存储设备,通常用于移动设备、相机等电子产品中。

在使用SD卡时,数据的读写是一个非常重要的过程。

本文将详细介绍SD卡的数据读写流程,包括初始化、文件操作和数据传输等环节。

初始化SD卡初始化SD卡是数据读写的第一步,确保SD卡可以被正确地识别和使用。

下面是SD卡数据读写的初始化流程:1.插入SD卡:将SD卡插入目标设备的SD卡插槽中。

2.电源供给:为SD卡提供稳定的电源,通常通过连接电源线或使用内置电池来实现。

3.延时等待:等待SD卡稳定,一般为几毫秒的时间。

4.发送命令:通过SPI或SDIO等接口向SD卡发送特定的命令,以初始化SD卡。

5.接收响应:SD卡将返回初始化成功与否的响应,如果初始化成功,则可以进行后续的数据读写操作。

SD卡文件系统在进行数据读写之前,需要先设置SD卡的文件系统。

常用的文件系统包括FAT16、FAT32和exFAT等。

下面是SD卡文件系统的设置流程:1.格式化SD卡:使用格式化工具对SD卡进行格式化,以清除原有的文件系统和数据。

2.创建分区:根据需求,可以将SD卡分为一个或多个分区,并设置每个分区的大小。

3.创建文件系统:选择合适的文件系统类型,在分区上创建文件系统,并分配文件系统的容量。

4.分配文件表:文件系统会维护一个文件表,记录文件的位置、大小等信息。

在创建文件系统时,会分配一块空间来存储文件表。

5.设置文件权限:根据需要,可以设置文件的读写、执行权限,以保证文件的安全性。

SD卡数据读写操作SD卡的数据读写操作包括文件的创建、打开、读取、写入和关闭等。

下面是SD卡数据读写操作的详细流程:1.创建文件:通过文件系统接口,调用相关函数创建一个新的文件,并指定文件的名称和路径。

2.打开文件:使用文件系统的函数打开已经存在的文件,以便后续的读取和写入操作。

3.读取文件:通过文件系统提供的函数,在已经打开的文件中进行读取操作。

SD卡初始化及读写流程

SD卡初始化及读写流程

SD卡初始化及读写流程默认分类2010-03-03 21:03:00 阅读264 评论0 字号:大中小SD卡调试关键点:1. 上电时要延时足够长的时间给SD卡一个准备过程,在我的程序里是5秒,根据不同的卡设置不同的延时时间。

SD卡初始化第一步在发送CMD命令之前,在片选有效的情况下首先要发送至少74个时钟,否则将有可能出现SD卡不能初始化的问题。

2. SD卡发送复位命令CMD0后,要发送版本查询命令CMD8,返回状态一般分两种,若返回0x01表示此SD卡接受CMD8,也就是说此SD卡支持版本2;若返回0x05则表示此SD卡支持版本1。

因为不同版本的SD卡操作要求有不一样的地方,所以务必查询SD卡的版本号,否则也会出现SD卡无法正常工作的问题。

3. 理论上要求发送CMD58获得SD卡电压参数,但实际过程中由于事先都知道了SD卡的工作电压,因此可省略这一步简化程序。

协议书上也建议尽量不要用这个命令。

4. SD卡读写超时时间要按照协议说明书书上的给定值(读超时:100ms;写超时:250ms),这个值要在程序中准确计算出来,否则将会出现不能正常读写数据的问题。

我自己定义了一个计算公式:超时时间=(8/clk)*arg。

5. 2GB以内的SD卡(标准卡)和2GB以上的SD卡(大容量卡)在地址访问形式上不同,这一点尤其要注意,否则将会出现无法读写数据的问题。

如标准卡在读写操作时,对读或写命令令牌当中的地址域符初值0x10,表示对第16个字节以后的地址单元进行操作(前提是此SD卡支持偏移读写操作),而对大容量卡读或写命令令牌当中的地址域符初值0x10时,则表示对第16块进行读写操作,而且大容量卡只支持块读写操作,块大小固定为512字节,对其进行字节操作将会出错。

6. 对某一块要进行写操作时最好先执行擦出命令,这样写入的速度就能大大提高。

进行擦除操作时不管是标准卡还是大容量卡都按块操作执行,也就是一次擦除至少512字节。

SD卡的传输协议和读写程序

SD卡的传输协议和读写程序

Ⳃ㄀1ゴ SD/MMC 䇏 ῵ (1)1.1 SD/MMC ⱘ 䚼⠽⧚ (1)1.1.1 SD῵ (2)1.1.2 SPI῵ (3)1.2 䆓䯂SD/MMC ⱘSPI῵ ⹀ӊ⬉䏃䆒䅵 (4)1.2.1 SPI 㒓 (5)1.2.2 կ⬉ (5)1.2.3 Ẕ⌟⬉䏃 (5)1.3 SD/MMC 䇏 ῵ ⱘ ӊ㒧 ԧ (5)1.3.1 SD/MMC 䇏 ῵ ⱘ ӊ㒘 (5)1.3.2 SD/MMC䇏 ῵ ԧḚ (6)1.4 SD/MMC 䇏 ῵ ⱘՓ⫼䇈 (6)1.4.1 SD/MMC 䇏 ῵ ⱘ⹀ӊ䜡㕂 (6)1.4.2 SD/MMC 䇏 ῵ կⱘAPI (9)1.5 SD/MMC 䇏 ῵ ⱘ ⫼⼎՟ϔ (11)1.5.1 ⹀ӊ䖲 Ϣ䜡㕂 (11)1.5.2 ⦄ ⊩ (11)1.6 SD/MMC 䇏 ῵ ⱘՓ⫼⼎՟Ѡ (18)1.6.1 ⦄ ⊩ (18)1.6.2 ՟ ゟϢ䖤㸠ℹ偸 (20)1.6.3 㗗⿟ (24)1.7 SD/MMC䕃ӊ ⫼ 㒧 (27)1 SD/MMCSD/MMC ϔ⾡ 䞣˄ 䖒4GB˅ǃ Ӌ↨催ǃԧ⿃ ǃ䆓䯂 ㅔ ⱘ DŽSD/MMC 䞣 ⫼Ѣ ⷕⳌ ǃMP3 ǃ ǃ 䞣 䆒 ˈ԰Ў䖭ѯ 䆒 ⱘ 䕑ԧˈ 䖬 Ԣ 㗫ǃ䴲 ǃ 䳔⍜㗫㛑䞣ㄝ⡍⚍DŽSD ϟ MMC˄MutliMediaCard ԧ ˅ ˈ䆓䯂SD ⱘSPI 䆂 䚼 Ҹг䗖⫼ѢMMC DŽSD/MMC 䇏 ῵ ZLG ㋏ Ё䯈ӊⱘ䞡㽕 Пϔˈ ⿄ЎZLG/SDDŽ䆹῵ ϔϾ⫼ 䆓䯂SD/MMC ⱘ䕃ӊ䇏 ῵ ˈⳂ ⠜ Ў2.00ˈ ⠜ ϡҙ㛑䇏 SD ˈ䖬 ҹ䇏 MMC ˗ϡҙ㛑 ㋏㒳˄ ԰㋏㒳˅ЁՓ⫼ˈ䖬 ҹ ԰㋏㒳ȝC/OS-IIЁՓ⫼DŽ ῵ SD/MMC ⱘSPI῵ DŽ ゴЁˈ䰸њ⡍ 䇈 ҹ ˈĀ ā䛑 SD MMC DŽ1.1 SD/MMC ⱘ 䚼⠽⧚SD MMC ⱘ 㾺⚍ 1.1 ⼎DŽ ЁSD ⱘ Ў˖24mm x 32mm x 2.1mm˄ 䗮˅ 24mm x 32mm x 1.4mm˄㭘SD ˅ˈMMC ⱘ Ў24mm x 32mm x 1.4mmDŽ1.1 SD MMC⠽1.2 SD MMC ⼎ ˄Ϟ㾚 ˅㸼1.1ЎSD/MMC 㾺⚍ⱘ ⿄ ԰⫼ˈ ЁMMC Փ⫼њ1 ~ 7㾺⚍DŽ㸼1.1 SD/MMC ⱘ⛞Ⲭ 䜡SD῵ SPI῵㛮 ⿄1㉏ 䗄 ⿄㉏ 䗄1 CD/DAT32 I/O/PP3 ⱘẔ⌟/ 㒓[Bit 3]CS I ⠛䗝˄Ԣ⬉ ˅2 CMD PP4 Ҹˋ DI I5 䕧3 V SS1 S ⬉⑤ VSS S ⬉⑤㓁Ϟ㸼SD῵ SPI῵㛮 ⿄1㉏ 䗄 ⿄㉏ 䗄4 V DD S ⬉⑤VDD S ⬉⑤5 CLK I 䩳SCLK I 䩳6 V SS2 S ⬉⑤ VSS2 S ⬉⑤7 DAT0 I/O /PP 㒓[Bit 0] DOO/PP 䕧8 DAT1 I/O /PP 㒓[Bit 1] RSV9 DAT2 I/O /PP 㒓[Bit 2] RSV⊼˖1. S˖⬉⑤˗I˖䕧 ˗O˖ 䕧 ˗PP˖ I/ODŽ2. ⱘDAT㒓˄DAT1 ~ DAT3˅ Ϟ⬉ Ѣ䕧 ⢊ DŽ Ӏ 㸠SET_BUS_WIDTH Ҹ԰ЎDAT㒓 ԰DŽ ϡՓ⫼DAT1 ~ DAT3㒓 ˈЏ Փ㞾 ⱘDAT1~DAT3㒓 Ѣ䕧 ῵ DŽ䖭ḋ Н ЎњϢMMC DŽ3. Ϟ⬉ ˈ䖭 㒓Ў 50K Ϟ ⬉䰏ⱘ䕧 㒓˄ ҹ⫼ѢẔ⌟ 䗝 SPI῵ ˅DŽ⫼ҹ ℷ ⱘ Ӵ䕧Ё⫼SET_CLR_CARD_DETECT˄ACMD42˅ Ҹ Ϟ ⬉䰏ⱘ䖲 DŽMMC ⱘ䆹 㛮 SD῵ ϟЎ ⬭ 㛮ˈ SD῵ ϟ ӏԩ԰⫼DŽ4. MMC SD῵ ϟЎ˖I/O/PP/ODDŽ5. MMC SPI῵ ϟЎ˖I/PPDŽ⬅㸼1.1 㾕ˈSD MMC ϡ ⱘ䗮 ῵ ϟˈ 㛮ⱘ 㛑гϡⳌ DŽ䖭䞠ⱘ䗮 ῵ ˄Џ ˅䆓䯂 Փ⫼ⱘ䗮 䆂ˈ ЎSD῵ SPI῵ DŽ ԧ䗮 䖛⿟ЁˈЏ 㛑䗝 Ёϔ⾡䗮 ῵ DŽ䗮 ῵ ⱘ䗝 ѢЏ 䇈 䗣 ⱘDŽ Ӯ㞾 Ẕ⌟ ԡ Ҹⱘ῵ ˄ 㞾 Ẕ⌟ ԡ ҸՓ⫼ⱘ 䆂˅ˈ㗠Ϩ㽕∖ҹ ⱘ䗮 䛑 Ⳍ ⱘ䗮 ῵ 䖯㸠DŽ ҹˈ Փ⫼ϔ⾡䗮 ῵ ⱘ ˈ 䳔Փ⫼ ϔ⾡῵ DŽϟ䴶 ㅔ ҟ㒡䖭ϸ⾡῵ DŽ1.1.1 SD῵SD῵ ϟˈЏ Փ⫼SD 㒓䆓䯂SD ˈ 㒓 㒧 1.3 ⼎DŽ⬅ 㾕ˈSD 㒓Ϟϡҙ ҹ SD ˈ䖬 ҹ MMC DŽ1.3 SD ㋏㒳˄SD῵ ˅ⱘ 㒓 㒧SD 㒓Ϟⱘ 㒓ⱘ䆺㒚 㛑 䗄 㸼1.2 ⼎DŽ㸼1.2 SD 㒓 㒓 㛑 䗄㒓 㛑 䗄CLK Џ 䗕ⱘ⫼Ѣ ℹ 䗮 ⱘ 䩳CMD ⱘ ҸˋDAT0 ~ DAT3 4Ͼ ⱘ ˄MMC DAT0 㒓˅VDD ⬉⑤ℷ ˈϔ㠀⬉ 㣗 Ў2.7 ~ 3.6VVSS1ǃVSS2 ⬉⑤SD ㋏㒳˄SD῵ ˅ⱘ 㒓 㒧 Ў: ϔϾЏ ˄ ˅ǃ ϾҢ ˄ ˅ ℹⱘ 㒧 ˄ 㗗 1.3˅DŽ ⫼ 䩳CLKǃ⬉⑤ DŽ㗠 Ҹ㒓˄CMD˅ 㒓˄DAT0 ~ DAT3˅ ⱘϧ⫼㒓ˈ ↣ 䛑⣀ゟ 䖭ѯ 㒓DŽ䇋⊼ ˈMMC 㛑Փ⫼1 㒓DAT0DŽ1.1.2 SPI῵SPI῵ ϟˈЏ Փ⫼SPI 㒓䆓䯂 ˈ Ҟ 䚼 䑿䛑 ⹀ӊSPI ˈ ҹՓ⫼ ⱘSPI 䆓䯂 ⱘDŽ Ϟ⬉ ⱘ㄀1Ͼ ԡ Ҹ ҹ䗝 䖯 SPI῵ SD῵ ˈԚ Ϟ⬉ 䯈ˈ ӀП䯈ⱘ䗮 ῵ ϡ㛑 ЎSD῵ DŽⱘSPI Ϣ ⱘSPI DŽ ⱘSPI 㒓ⱘ 㒓 㸼1.3 ⼎DŽ㸼1.3 SD ϢMMC ⱘSPI 䗄㒓 㛑 䗄CS Џ 䗕ⱘ⠛䗝CLK Џ 䗕ⱘ 䩳DataIn Џ 䗕ⱘDataOut Џ 䗕ⱘSPI 㒓ҹ 㡖Ў ԡ䖯㸠 Ӵ䕧ˈ Ҹ⠠䛑 㡖˄8ԡ˅ⱘ ˈ㗠Ϩ 㡖䗮 ϢCS 唤DŽSD ㋏㒳 1.4 ⼎DŽ1.4 SD ㋏㒳˄SPI῵ ˅ⱘ 㒓 㒧Џ 䚼䖲 SD MMC ˈЏ ⫼CS 㒓 䖯㸠 DŽ՟ ˖ 1.4Ёˈ Џ 䳔㽕 SD AӴ䕧 䳔㽕Ң䆹 ˈ 乏 CS(A)㕂ЎԢ⬉ ˄ ⱘCS 㒓 乏㕂Ў催⬉ ˅DŽCS SPI ⧚˄ Ҹǃ ˅ 䯈 乏㓁 ˄Ԣ⬉ ˅DŽ ϔ՟ ⱘ 㓪⿟ⱘ䖛⿟DŽ 䖭Ͼ䖛⿟ЁˈЏ ҹՓCS Ў催⬉ ˈԚϡ ⱘ㓪⿟DŽ⬅ 1.4 㾕ˈ SPI 㒓Ϟ N ˈ䳔㽕N CS⠛䗝㒓DŽ1.2䆓䯂SD/MMC ⱘSPI῵ ⹀ӊ⬉䏃䆒䅵SD/MMC ҹ䞛⫼SD 㒓䆓䯂ˈг ҹ䞛⫼SPI 㒓䆓䯂ˈ㗗㰥 䚼 䛑 SPI 㗠≵ SD 㒓 ˈ㗠Ϩ 䞛⫼I/O ῵ SD 㒓ˈϡԚ њ䕃ӊⱘ 䫔ˈ㗠Ϩ 㗠㿔ˈ῵ 㒓䖰ϡ ⳳℷⱘSD 㒓䗳 ˈ䖭 䰡Ԣ 㒓 Ӵ䕧ⱘ䗳 DŽѢҹϞⱘ㗗㰥ˈ䞛⫼LPC2103 ⱘSPI Ў՟ ˈ䆒䅵䆓䯂SD/MMC ⱘ⹀ӊ ⬉䏃DŽLPC2103 ϢSD/MMC ⬉䏃 1.5 ⼎DŽ1.5 SD ϢLPC2103 ⬉䏃˄SPI῵ ˅ЁˈLPC2103ϢSD/MMC ⱘ䖲 㛮 㸼1.4 ⼎DŽ㸼1.4 LPC2103ϢSD/MMC ⱘ䖲 㛮LPC2103 НP0.8_CS SPI⠛䗝 ˈ⫼Ѣ䗝 SPIҢ ˈ䆹 㛮Ў 䗮I/OP0.4_SCK SPI 䩳 ˈ⬅Џ ˈ⫼Ѣ ℹЏ П䯈ⱘ Ӵ䕧P0.6_MOSI SPIЏ 䕧 ˈҢ 䕧LPC2103 НP0.5_MISO SPIЏ 䕧 ˈҢ 䕧P0.9_SD_POWER կ⬉ ˈ LPC2103ⱘP0.9䕧 Ԣ⬉ 㒭 կ⬉P0.10_SD_INSERT ЁẔ⌟㒓ˈ 䕧 Ԣ⬉ ˈ 䕧 催⬉ P0.11_SD_WP Ẕ⌟ˈ 䕧 催⬉ ˈ 䕧 Ԣ⬉ġճ Ϣ ԅ ē Ќ ЉԨ ͬ ЉԨ Ϣ d1.2.1 SPI 㒓1.5 ⼎ˈLPC2103 SPI ⱘP0.8_CSǃP0.4_SCKǃP0.6_MOSIǃP0.5_MISOⳈ 䖲 ⱘⳌ ˈ ЁSPIⱘϸϾ 㒓P0.6_MOSIǃP0.5_MISO䖬 Ϟ ⬉䰏ˈ䖭 ЎњՓ ⬉䏃 ҹϢMMC ⱘ DŽSPI῵ ϟ 䳔⫼ ⱘ 㒓DAT2 DATA1 ϟ ⬉䰏DŽ1.2.2 կ⬉ⱘկ⬉䞛⫼ ˈ䖭 Ўњ䰆ℶSD/MMC 䖯 ϡ⹂ ⢊ ˈ ҹ䗮䖛 䞡 Ϟ⬉Փ ԡ㗠 䳔 DŽ⬉䏃䞛⫼P MOSㅵ2SJ355ˈ⬅LPC2103ⱘGPIO P0.9_SD_POWER䖯㸠 ˈ P0.9_SD_POWER䕧 催⬉ ˈ2SJ355 ˈϡ㒭 կ⬉˗ P0.9_SD_POWER 䕧 Ԣ⬉ ˈ2SJ355 䗮ˈVCC3.3⬉⑤˄⬉ Ў3.3V˅㒭 կ⬉DŽ䞛⫼2SJ355ⱘⳂⱘ 䗮 ˈㅵ Ϟⱘ 䰡↨䕗 DŽ2SJ355ⱘⳌ ⡍ 䇋㾕 DŽ⫼ г ҹ䞛⫼ P ⱘMOSㅵˈԚ 㽕㗗㰥ㅵ 䗮 ˈⓣ Ϣ⑤ П䯈ⱘ 䰡㽕䎇 ˄ 䆕SD/MMC ⱘ ԰⬉ 䆌㣗 ˅ˈㅵ 䆌䗮䖛ⱘ⬉⌕г㽕⒵䎇 ⱘ㽕∖ˈϔ㠀ϔ SD/MMC ԰ ⱘ ⬉⌕䗮 Ў45mA ˈ ҹ䗝⫼ⱘMOSㅵ㽕∖ 䆌䗮䖛100mA ⱘ⬉⌕DŽ1.2.3 Ẕ⌟⬉䏃Ẕ⌟⬉䏃 ϸ䚼 ˖ Ё DŽẔ⌟ ⬅ ⱘϸϾ 㛮ҹ⬉ ⱘ 䕧 DŽ ԡ ˈP0.10_CARD_INSERT˄㄀10㛮˅⬅Ѣ 䚼㾺⚍䖲 GNDˈ䕧 Ԣ⬉ ˗ ˈ䆹 㛮⬅ѢϞ ⬉䰏R2ⱘ 㗠䕧 催⬉ ˈ䆹䕧 ⬅LPC2103ⱘ䕧 㛮GPIO(P0.10_SD_INSERT) Ẕ⌟DŽⱘẔ⌟Ϣ ЁⱘẔ⌟ ⧚ ϔḋⱘDŽ1.3 SD/MMC 䇏 ῵ ⱘ ӊ㒧 ԧ㡖ҟ㒡 ῵ ⱘ㒘 ӊҹ ӀП䯈ⱘ ㋏DŽ1.3.1 SD/MMC 䇏 ῵ ⱘ ӊ㒘SD/MMC 䇏 ῵ ⱘ ӊ 㸼1.5 ⼎DŽ㸼1.5 SD/MMC 䇏 ῵ ⱘ ӊӊ԰⫼sdconfig.h 䇏 ῵ ⹀ӊ䜡㕂 ӊsdspihal.c 䇏 ῵ ⹀ӊ 䈵 ˈ ⦄SPI ˈSPI 㡖ⱘ ǃ ㄝϢSPI⹀ӊⳌ ⱘӊ԰⫼sdspihal.h sdspihal.c ӊsdcmd.c 䇏 ῵ Ҹ ˈ ⦄ ⱘ ⾡ Ҹҹ Џ Ϣ П䯈ⱘ ⌕sdcmd.h sdcmd.c ӊsddriver.c 䇏 ῵ ⫼ ˈ ⦄ ⱘ䇏ǃ ǃ API ˈ䆹 ӊ䖬 ϔѯ ԰ sddriver.h sddriver.c ӊˈ 㸠䫭䇃ҷⷕsdcrc.c Ⳍ ⱘCRC䖤ㅫsdcrc.h sdcrc.h ӊ㸼1.5Ё䖭ѯ ӊ њ ῵ ˈϟ䴶䇈 ⬅䖭ѯ ӊ ⱘ ԧḚ DŽ1.3.2 SD/MMC䇏 ῵ ԧḚ㗗㰥 䆹῵ ⱘ ⿏ỡ ⫼ ˈ ῵ Ў3Ͼ ˈ 1.6 ⼎DŽ Ёⱘ ԰㋏㒳 ϡ 乏ⱘˈг 䇈ˈ ῵ ҹ ⫼Ѣ ㋏㒳˄ ԰㋏㒳˅ˈг ҹ ⫼Ѣ ԰㋏㒳Ёˈ ῵ կ ㋏㒳 ԰㋏㒳ȝC/OS-IIЁ 㒳ϔⱘAPI DŽՓ⫼ ԰㋏㒳⬅ ῵ sdconfig.h ӊЁⱘ НSD_UCOSII_EN Փ㛑 ⽕ℶDŽ1.6 SD/MMC 䇏 ῵ 㒧ⱘ⡍⚍ ϟ˖(1)⹀ӊ 䈵 ˖䇏 SD/MMC ⱘ⹀ӊ ӊ䜡㕂ˈϢ⹀ӊⳌ ⱘ ˗(2) Ҹ ˖SD/MMC ⱘⳌ Ҹҹ ϢЏ П䯈 ⌕ⱘ ˈ䖭ϔ Ϣ⹀ӊ˗(3) ⫼ ˖ ⫼ ⫼⿟ ӊ㋏㒳 կ ԰ ⱘAPI DŽ 䞛⫼ ԰㋏㒳ˈ䖭ϔ ⬅ ԰㋏㒳 DŽ1.4 SD/MMC 䇏 ῵ ⱘՓ⫼䇈Փ⫼ ῵ П ˈ 乏䜡㕂 ῵ Փ⫼ⱘ⹀ӊ ӊˈ ⹀ӊ ӊϢ1.2 㡖Ёⱘ⹀ӊ ӊϔḋˈ䙷М 乏䜡㕂 䕃ӊ ҹゟ Փ⫼DŽϟ䴶䇈 ḋ䜡㕂 ῵ ⱘ⹀ӊ ӊˈ 㛑 ⫼ѢLPC2103㋏ DŽ1.4.1 SD/MMC 䇏 ῵ ⱘ⹀ӊ䜡㕂SD/MMC 䇏 ῵ LPC2103ⱘ䜡㕂 Ϣsdconfig.h ӊⳌ ˈ䜡㕂 ӊsdconfig.hՓ⫼ 㛑 䜡㕂 ῵ ⱘⳌ 㛑 㺕 ѯ ⫼ 䇈 䳔⫼ ⱘ DŽ䆹 㡖 ⱘ ⿟ ⏙ 䛑 䆹 ӊϞDŽϟ䴶䯤䗄䆹 ӊⱘ䜡㕂 ⊩DŽ1ˊ῵ 䜡㕂῵ ⱘ 䜡㕂 ⿟ ⏙ 1.1 ⼎ˈ䜡㕂䗝乍 ϟ˖(1) 䖤㸠ѢȝC/OS-II ЁDŽ ῵ ҹ䖤㸠Ѣ ㋏㒳Ёˈ ҹ䖤㸠Ѣ԰㋏㒳ȝC/OS-II ЁDŽ 䖤㸠ѢȝC/OS-II Ё ˈ НSD_UCOSII_EN ⱘ 㕂Ў1ˈ 㕂Ў0DŽ(2)CRC 偠DŽ⬅ѢSD/MMC SPI 䗮 ῵ ϟ ҹϡ䳔㽕䖯㸠 Ӵ䕧ⱘCRC偠ˈ䆹 ⫼ѢՓ㛑 ⽕ℶ 䇏 ῵ ⱘ Ӵ䕧CRC 偠 㛑DŽՓ㛑CRC 偠 䗮 䴴 催ˈԚCRC 䖤ㅫг Ӵ䕧䗳 ⱘϔѯ ˈ⬅Ѣ ῵ 䞛⫼ 㸼ⱘ ⊩䅵ㅫCRC16ˈ ҹ䗳 ⬹ DŽ(3)SPI 䩳乥⥛DŽ НSPI 㒓ⱘCLK 㒓ⱘ乥⥛ˈ䆹乥⥛ ⫼Ѣ䅵ㅫ䇏ǃ ǃ԰Ёⱘ䍙 䯈 ⱘCLK Ͼ ˈ䖭ḋ 䍙 䯈䕀 Ў䍙 䅵 DŽ䆹乥⥛ ⱘ ԡЎ˖Hz ˈ䆹 䳔㽕⫼ НDŽ(4)SD/MMC ⱘ䭓 DŽ НSD/MMC ⱘ 䭓 ˈ Ҟ⌕㸠ⱘSD/MMCⱘ 䭓 䚼 䛑 512 㡖DŽ НSD_BLOCKSIZE_NBITS Ў9ˈ Ѣ29 = 512 㡖˄ Ѣ НSD_BLOCKSIZE ⱘ ˅ˈSD_BLOCKSIZE_NBITS ϢSD_BLOCKSIZE ϔ 㽕 䖭ḋⱘ ㋏DŽSD_BLOCKSIZE_NBITS ⫼Ѣ ӊ⿟ 䅵ㅫⱘ DŽ⫼ ϔ㠀 乏 䖭ϸϾ Нⱘ DŽ ⿟ ⏙ 1.1῵ 䜡㕂#define SD_UC OSII_EN 1 /* ȝC/OS-II Ϟ䖤㸠 ῵ */ #define SD_CRC_EN/* 䆒㕂 Ӵ䕧 Փ⫼CRC */ #define SPI_CL O CK 5529600 /* ℷ 䗮 ,SPI 䩳乥⥛(Hz) */ #define SD_BLO CKSIZE512 /* SD/MMC ⱘ䭓*/#define SD_BLO CKSIZE_NBITS9/* 2ⱘ9⃵ Ў512˄ SD_BLOCKSIZE ⱘ ˅*/2ˊ 㛑䜡㕂῵ Ё ϔѯ 㛑ϡ ⫼ 䛑 㛑⫼ ⱘˈ ҹ ҹ㺕 ϡ䳔㽕ⱘ ˈҹҷⷕ䞣DŽ⿟ ⏙ 1.2ⱘ Н⫼ѢՓ㛑㓪䆥䇏 ῵ Ёⱘ ѯ↨䕗 ⫼ⱘ ˈ Ў1 ˈՓ㛑㓪䆥 ⱘ ˗Ў0 ˈ⽕ℶ㓪䆥 ⱘ DŽ䖭ѯ Н䍋 㺕 䇏 ῵ ҷⷕ ⱘⳂⱘDŽ⿟ ⏙ 1.2῵ Փ㛑/* ϟ䴶 ϡ ⫼, ⫼ ϡ䳔㽕, 㕂Ў 0 㺕 */ #define SD_ReadMultiBlock_EN 0 /* Փ㛑䇏 */ #define SD_WriteMultiBlock_EN 0 /* Փ㛑*/ #define SD_EraseBlock_EN 0 /* Փ㛑*/ #define SD_ProgramCSD_EN 0 /* Փ㛑 CSD*/ #define SD_ReadCID_EN/* Փ㛑䇏CID */#define SD_ReadSD_Status_EN 0 /* Փ㛑䇏SD Status */ #define SD_ReadSCR_EN 0 /* Փ㛑䇏SCR*/3ˊ⹀ӊ ӊ䜡㕂䖭䚼 ҹ ⱘ ⱘSPI IO Ⳍ ԰䖯㸠 Нˈ 㛑 ⹀ӊⳌ ⱘ䚼 Ѣ䖭ϔ䚼 DŽ՟ ˈ䜡㕂LPC2103ⱘ4ϾI/O ЎSPI ⱘ Н ⿟ ⏙ 1.3(1) ⼎DŽ ѢSD կ⬉ 㛮ⱘ ⿟ ⏙ 1.3(2) ⼎DŽ⫼ 䯙䇏LPC2103ⱘ ҹњ㾷䖭ѯ䜡㕂ⱘ НDŽ䆹 ӊ䖬 IO ⱘ䜡㕂ˈ䆺㾕sdconfig.h ӊDŽ⿟ ⏙ 1.3 LPC2103ⱘIO 䜡㕂 Н/* IO ЎSPI */#define SPI_INIT() PINSEL0 &= ~((0x03 << 8) + (0x03 << 10) + (0x03 << 12)); \PINSEL0 |= (0x01 << 8) + (0x01 << 10) + (0x01 << 12); (1) /* ⬉⑤ 㛮*/ (2)#defineSD_PO WER (0x01<<9)#define SD_POWER_GPIO() PINSEL0 &= ~(0x03 << 18) /* 䆒㕂 PO WER ЎGPIO */#defineSD_PO WER_OUT() IODIR|=SD_POWER /*䆒㕂 PO WER Ў䕧 */#define SD_PO WER_O FF() IO SET = SD_PO WER /* 㕂 PO WER Ў催⬉ */ #define SD_PO WER_O N() IO CLR = SD_PO WER /* 㕂 PO WER ЎԢ⬉ */ 䜡㕂 ӊⱘ 䚼 ҟ㒡 ℸˈ 㽕 ῵ ⿏ỡ MCUˈ 䖬䳔 sdhal.c ӊˈ䖭ϔ䚼 ϢMCUⱘSPI ԰Ⳍ ˈ Փ⫼LPC2103ˈ䙷М 乏 䆹 ӊDŽ䖬 ϔ⚍ ⬹ⱘˈ 乏 LPC2103ⱘ 䆒 䩳乥⥛Fpclk䇗㟇 催˄ 䆌㣗 ˅ˈ䖭ḋˈ䇏 ῵ ⱘ䇏 䗳 㛑䖒 催DŽ㗠ϨSD/MMC ⱘSPI 㒓 䆂Ёˈ㽕∖SPIЏ 乏㛑 SPI 㒓ⱘ 䩳乥⥛DŽLPC2103 SPI 㒓 䩳ⱘ 䇈 ϟDŽ4ˊ䆒㕂SPI ⱘ 䩳乥⥛ Ѣ400kHz䆹 Џ㽕 SD/MMC 䰊↉ˈ⫼Ѣ䆒㕂SPI ⱘ 䩳乥⥛ Ѣ400kHzˈ ЎMMC 䯈SPI 㒓ⱘ 䩳乥⥛ϡ㛑催Ѣ400kHzˈ䖭ḋ ῵ 㛑䖒 MMC ⱘⳂⱘDŽ䆹 ⿟ ⏙ 1.4 ⼎˄㾕sdhal.c ӊ˅DŽ䆹 LPC2103 SPI ⱘSPI 䩳䅵 SPI_SPCCRⱘ 乥 䖒 ⳂⱘDŽ⿟ ⏙ 1.4䆒㕂SPI ⱘ 䩳乥⥛ Ѣ400kHzvoid SPI_Clk400k(void){SPI_SPCCR=128; /*䆒㕂SPI 䩳 乥 Ў128 */}LPC2103ⱘ 䚼 乥⥛Fosc = 11.0592MHzˈ Ḍ 䩳乥⥛Fcclk䆒㕂ЎFosc ⱘ4 ˈ Fcclk = 44.2368 MHzDŽ 䆒 䩳乥⥛䆒㕂ЎϢ Ḍ 䩳乥⥛Ⳍ ˈ Fpclk = Fcclk = 44.2368 MHzˈ䙷МSPI 㒓ⱘ 䩳ЎFpclk㒣䖛SPI_SPCCR 乥 ⱘ 䩳DŽ ҹˈ㽕ՓSPI ⱘ 䩳乥⥛ Ѣ400kHzˈ 㽕 䆕SPI_SPCCR ⱘ Ў Ѣ8ⱘ ˈ䆹 ⱘ 乥 㽕䆒Ў128DŽⱘSPI SCKⱘ乥⥛Ў˖44.2368 / 128 = 0.3456 MHz = 345.6kHz < 400kHzDŽḋˈ 㽕䆒㕂SCKⱘ乥⥛Ў ˈ 乏䇗⫼void SPI_ClkToMax(void) ˄㾕sdhal.c ӊ˅ˈ䆹 SPI_SPCCRⱘ Ў8ˈ䙷М SCKⱘ乥⥛Ў˖44.2368 / 8 = 5.5296MHzDŽ䳔㽕⊼ ˈ Ҟ⌕㸠ⱘSD/MMC ⱘSPI ⱘ 䩳乥⥛ϔ㠀ϡ 䆌䍙䖛25MHzˈ ҹ НMCU䆓䯂SD/MMC ⱘ 䩳乥⥛ ˈ 乏⊼ 䖭ϔ⚍DŽ䇏㗙ⱘ 䚼 乥⥛Fosc LPC2103 䆒 䩳乥⥛Fpclk њˈ䇋⊼ 䖭ϸϾ Ёⱘ 乥 ˈ Ӭ 䇏 ῵ ⱘ䆓䯂䗳 DŽ䜡㕂 њ⹀ӊˈ䙷М ҹՓ⫼ ῵ њˈ䙷М ῵ կњ ѯAPI ⫼ 䆓䯂SD/MMC ˛ϟ䴶ҟ㒡䖭ѯAPI ⱘ DŽ1.4.2 SD/MMC 䇏 ῵ կⱘAPI⫼ ҹ ⫼ ῵ կⱘAPI SD/MMC 䖯㸠䆓䯂ˈ㾕㸼1.6㟇㸼1.11DŽ㸼1.6 SD_Initialize()⿄ SD_InitializeINT8U SD_Initialize(void)㛑 䗄 SD/MMC ǃ䆒㕂 Ў512 㡖ˈ㦋 ⱘⳌ䖨 SD_N O _ERR ˖ ˗ > 0: 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅ ⡍⅞䇈 ⊼ ⚍䆹 䆒㕂њ ⱘ䇏/ 䭓 Ў512 㡖㸼1.7 SD_ReadBlock ()⿄ SD_ReadBlockINT8U SD_ReadBlock(INT32U blockaddr, INT8U *recbuf) 㛑 䗄 䇏SD/MMC ⱘϔϾblockaddr ˖ҹ Ў ԡⱘ DŽ՟ ˈ ⱘ0 ~ 511 㡖Ў 0ˈ512 ~ 1023㡖ⱘ Ўˍrecbuf ˖ 㓧 ˈ䭓 Ў512 㡖䖨 SD_N O_ERR ˖䇏 ˗ > 0: 䇏 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅ ⡍⅞䇈 ⊼ ⚍recbuf ⱘ䭓 乏 512 㡖㸼1.8 SD_WriteBlock()⿄ SD_WriteBlockINT8U SD_WriteBlock(INT32U blockaddr, INT8U *sendbuf) 㛑 䗄 SD/MMC ⱘϔϾblockaddr ˖ҹ Ў ԡⱘ DŽ՟ ˈ ⱘ0 ~ 511 㡖Ў 0ˈ512 ~ 1023㡖ⱘ Ўˍsendbuf ˖ 䗕㓧 ˈ䭓 Ў512 㡖䖨 SD_N O _ERR ˖ ˗ > 0: 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅ ⡍⅞䇈 ⊼ ⚍sendbuf ⱘ䭓 乏 512 㡖㸼1.9 SD_ReadMultiBlock()⿄ SD_ReadMultiBlockINT8U SD_ReadMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *recbuf) 㛑 䗄䇏SD/MMC ⱘ Ͼ㟈䖰⬉ 䰤 Tel ˖(020)38730976 38730977 Fax ˖38730925 㓁Ϟ㸼blockaddr ˖ ҹ Ў ԡⱘ blocknum ˖recbuf ˖ 㓧 ˈ䭓 Ў512 * blocknum 㡖䖨 SD_N O _ERR ˖䇏 ˗ > 0: 䇏 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅⡍⅞䇈 ⊼ ⚍Փ⫼ 乏 sdconfig.h Ёⱘ Н SD_ReadMultiBlock_EN 㕂Ўˍ㸼1.10 SD_WriteMultiBlock ()⿄ SD_WriteMultiBlockINT8U SD_WriteMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *sendbuf) 㛑 䗄 䇏SD/MMC ⱘ Ͼblockaddr ˖ҹ Ў ԡⱘ blocknum ˖sendbuf ˖ 䗕㓧 ˈ䭓 Ў512 * blocknum 㡖䖨 SD_N O_ERR ˖ ˗ > 0: 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅⡍⅞䇈⊼ ⚍Փ⫼ 乏 sdconfig.h Ёⱘ Н SD_WriteMultiBlock_EN 㕂Ўˍ㸼1.11 SD_EraseBlock()⿄ SD_EraseBlockINT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum) 㛑 䗄 䰸SD/MMC ⱘ Ͼstartaddr˖ ҹ Ў ԡⱘ 䰸䍋 blocknum ˖ ˄ 㣗 1 ~ sds.block_num ˅䖨 SD_N O _ERR ˖ 䰸 ˗ > 0: 䰸 䋹˄䫭䇃ⷕˈ㾕㸼1.12˅ ⡍⅞䇈 ⊼ ⚍Փ⫼ 乏 sdconfig.h Ёⱘ Н SD_EraseBlock_EN 㕂ЎˍDŽStartaddr blocknum 䆂Ў sds.erase_unit ⱘ , Ў ⱘ 㛑ҹ sds.erase_unit Ў ԡ䖯㸠 䰸ϡ ⫼ˈ䖭䞠 ϡϔϔ њDŽ䳔㽕⫼ ⱘ䇏㗙 ҹ䯙䇏⑤ⷕЁⱘ䇈 DŽ㸼1.6㟇㸼1.11 䖨 ҷ㸼ⱘ Н 㸼1.12 ⼎DŽ㸼1.12䫭䇃ҷⷕ 㸼䫭䇃ⷕ НННSD_N O_ERR 0x00 㸠 SD_ERR_N O _CARD 0x01 ≵ ЁSD_ERR_USER_PARAM 0x02 ⫼ Փ⫼API ˈ 䫭䇃 SD_ERR_CARD_PARAM 0x03 Ё 䫭䇃˄Ϣ ῵ ϡ ˅ SD_ERR_V O L_N O TSUSP 0x04 ϡ 3.3V կ⬉ SD_ERR_O VER_CARDRANGE 0x05 ԰䍙 㣗 SD_ERR_UNKN OWN_CARD 0x06 ⊩䆚 SD_ERR_CMD_RESPTYPE 0x10 Ҹ㉏ 䫭䇃 SD_ERR_CMD_TIME OUT 0x11 Ҹ 䍙㓁Ϟ㸼䫭䇃ⷕ НННSD_ERR_CMD_RESP 0x12 Ҹ 䫭䇃SD_ERR_DATA_CRC16 0x20 ⌕CRC16 偠ϡ䗮䖛SD_ERR_DATA_START_T OK 0x21 䇏 ˈ Ҹ⠠ϡℷ⹂SD_ERR_DATA_RESP 0x22 ˈ Ҹ⠠ϡℷ⹂ SD_ERR_TIME O UT_WAIT 0x30 ԰ ˈ ⫳䍙 䫭䇃 SD_ERR_TIME OUT_READ 0x31 䇏 ԰䍙 䫭䇃SD_ERR_TIME O UT_WRITE 0x32 ԰䍙 䫭䇃 SD_ERR_TIME O UT_ERASE 0x33 䰸 ԰䍙 䫭䇃SD_ERR_TIME O UT_WAITIDLE 0x34 ˈㄝ 䗔 ぎ䯆⢊ 䍙 䫭䇃 SD_ERR_WRITE_BLK 0x40 䫭䇃SD_ERR_WRITE_BLKNUMS 0x41 ˈ 㽕 ⱘ Ϣℷ⹂ ⱘ ϡϔ㟈 SD_ERR_WRITE_PR OTECT 0x42 ⱘ ԡ㕂 SD_ERR_CREATE_SEMSD 0xA0 䆓䯂 ⱘ 䞣 䋹ϟ䴶㒭 Փ⫼SD/MMC 䇏 ῵ ⱘϔϾ՟ DŽ1.5 SD/MMC 䇏 ῵ ⱘ ⫼⼎՟ϔϟ䴶㒭 LPC2103 ⧚ ϞՓ⫼SD/MMC 䇏 ῵ SD/MMC 䖯㸠䇏ǃ ⱘ՟ DŽ䆹՟ ⫼LPC2103 կⱘSPI 䇏 SD/MMC ˈ ⱘ 䇏Ϣ ↨䕗ˈ偠䆕䇏 ԰ⱘℷ⹂ DŽ 1.5.1⹀ӊ䖲 Ϣ䜡㕂⫼ 䙺㒓EasyARM2103ϢSD CARD PACK 䖲 䍋 ˈ䖲㒓 ⊩ 㸼1.13 ⼎DŽ 㸼1.13 EasyARM2103ϢSD CARD PACK 䖲 ㋏EasyARM2103˄JP5˅SD CARD PACK 㛮˄J1˅㒓 Н3.3V 3.3V SD CARD PACK կ⬉⬉⑤GND GND ⬉⑤P0.9 P OW_C 3.3V ⬉⑤կ㒭 P0.8 CS 䗝 SD/MMCP0.6 M O SI Џ SPI 䕧 ˈ SPI 䕧 P0.4 SCK SPI 㒓 䩳P0.5 MIS OЏ SPI 䕧 ˈ SPI 䕧 P0.10 INSERT Ẕ⌟ P0.11 WP Ẅ Ẕ⌟SD/MMC 䇏 ῵ 咬䅸ⱘ⹀ӊ䜡㕂 㸼1.13ⱘ⹀ӊ ӊⳌヺDŽ ℸˈϡ䳔㽕 䇏 ῵ 䖯㸠䜡㕂DŽ 1.5.2⦄ ⊩՟ SD/MMC 䖯㸠䇏ǃ 䰸ㄝ ⫼ ԰DŽ՟ ⱘ䕃ӊ㒧 1.7 ⼎DŽ1.7 Џ ⌕⿟SD ⫼⼎՟Џ ⿟ ⏙ 1.5 ⼎DŽ⿟ ⏙ 1.5 SD ԰Џ ҷⷕint main (void) {uint32 i; uint8 status;uint8 sdbuf[512]={0}; /* 㓧 */ uint8 sdbuf2[512]={0}; /* 䇏 㓧 */PINSEL1 = 0x00000000; /* 䆒㕂ㅵ㛮䖲 GPI O*/ IO0DIR |= BEEP;/* 䆒㕂BEEP Ў䕧 */IO 0SET = BEEP;for(i=0;i<512;i++){ /**/sdbuf[i] = i&0xff; }status = SD_Initialize(&sds); /* SD*/if (status != SD_NO_ERR){ while(1); } status = SD_WriteBlock(&sds,0,sdbuf);/* sdbuf 㓧 ㄀0 Ё*/if (status != SD_NO_ERR){while(1); }status = SD_ReadBlock(&sds,0,sdbuf2); /* 䇏㄀0 ⱘ*/if (status != SD_NO_ERR){ while(1); }status = memcmp(sdbuf,sdbuf2,512); /* sdbuf2Ϣsdbuf ⱘ 䖯㸠↨䕗*/if(status!=0){/* ↨䕗䫭䇃,㳖号 㳖号ϝ */Beep O n O ff(3); }else{/* ↨䕗ℷ⹂,㳖号ϔ */Beep O n O ff(1); } while(1); return 0; }ϟ ⿟ ⏙ 1.5ЁⱘSD ǃSD 䇏 ㄝ ⫼ Ҹ䖯㸠ㅔ㽕䆆㾷DŽ1ˊ SDSD ⌕⿟ 1.8 ⼎ˈ佪 䆓䯂 ⱘ⹀ӊ ӊˈSdSpiHal_Initialize˄˅ ҷⷕ ⿟ ⏙ 1.6 ⼎DŽ⿟ ⏙ 1.6 䆓䯂 ⱘ⹀ӊ ӊINT8U SdSpiHal_Initialize(sd_struct *sds) {SD_Power(); /* ϟ⬉, Ϟ⬉ */ SPI_INIT();/* SPI*/SD_INSERT_GPI O ();SD_INSERT_IN(); /* Ẕ⌟ Ў䕧 */ ˄1˅ SD_WP_GPIO();SD_WP_IN();/* Ẕ⌟ Ў䕧 */ ˄2˅ SPI_CS_SET();/* CS 㕂催*/ SdSpiHal_SetMCIClock(sds, SD_RATE_SLO W); /* 䆒㕂SPI 乥⥛ ѢㄝѢ400kHZ */ SPI_SPCR = 0 << 3 |/* CPHA = 0㄀ϔϾ 䩳䞛ḋ */1 << 4 |/* CPOL = 1ˈSCK Ԣ */ 1 << 5 | /* MSTR = 1ˈ䆒㕂ЎЏ῵ */ 0 << 6 | /* LSBF = 0ˈSPI Ӵ䕧MSB */0 << 7 ;/* SPIE = 0ˈSPI Ё ⽕ℶ*/return SD_N O _ERR; }SD ϟ⬉ˈ Ϟ⬉ ˈ SPI 㒓 䖯㸠 DŽ⿟ ⏙ 1.6˄1˅ ⫼ѢẔ⌟ ⱘ ⱘI/O 㛮 ЎGPIO ˈ Ϩ䆒㕂Ў䕧 DŽ⿟ ⏙ 1.6˄2˅ ⫼ѢẔ⌟ ⱘI/O 㛮 ЎGPIO ˈ Ϩ䆒㕂Ў䕧 DŽ 䆒㕂SPI ⱘSCK 㛮䕧 乥⥛ ѢㄝѢ400KHz ˈ ЎMMC ԡ䰊↉㽕∖SPI ⱘ 䩳乥⥛㽕 ѢㄝѢ400KHz DŽġ · ͧ ӾLPC2103ԅSPI ԅP0.7ďSPI Ҷ Đ ē ē LPC2103ԅSPI ϢѩӲҶ ēϢ Ү Ѻ SPI ē Ѻ ēSPI Վ Ҷ d1.8 SD ⌕⿟Ϣ Ẕ⌟ 乏Ẕ⌟Ⳍ I/O ⱘ⬉ DŽ Ẕ⌟ ⿟ ⏙ 1.7 ⼎DŽ䆹 䖨 0㸼⼎ ˈℸ ˈSD/MMC 䇏/ 䕃ӊ ϡ㛑 䖯㸠 ԰DŽ ˈP0.10_SD_INSERT 㛮䕧 Ԣ⬉ DŽ⿟ ⏙ 1.7 Ẕ⌟INT8U SdHal_CheckCard(sd_struct *sds){if (SD_INSERT_STATUS() != 0)return 0; /* not insert entirely */elseentirely */ return 1; /* insert}ѢSD ⌕⿟Ёⱘ ԰ ԡ 䖯 ぎ䯆⢊ ǃ▔⌏ 䖯 ҹ䆒㕂 䭓 䇏 ㄝ ԰ˈ 䆓䯂 ⫼SD/MMC 㾘 乏㽕䖯㸠ⱘ ԰ˈ 㦋 Ⳍ ⱘ ˈ 䆒㕂Ў 䗖ⱘ⢊ ˈ 䖯㸠䇏 䆓䯂DŽ2ˊ SD ԰SD/MMC SPI῵ ϟⱘ ԰ ϸ⾡˖ DŽ ⼎՟䞡⚍ҟ㒡԰DŽ SD_Initialize() 㒣䇗⫼њSpiCmd_Set_BlockLen() 䆒 њ䇏/ⱘ䭓 SD_BLOCKSIZE 㡖ˈ ˈ䇏/ 䛑 ҹ Ў ԡˈϔ⃵ ԰㟇 㽕 SD_BLOCKSIZE 㡖DŽSD_BLOCKSIZE 㡖ϔ㠀䛑Ў512 㡖DŽSD ԰⌕⿟ 1.9 ⼎DŽ 䖭ḋ䖯㸠ⱘ˖1.9 SD ԰⌕⿟(1)Џ Ẕ⌟ Ё˗(2)Џ Ẕ⌟ ˗(3)ҹϞ ӊ⒵䎇 ˈЏ 䗕 Ҹˈ ЎblockaddrⱘϔϾ ˗(4)Џ ㋻䎳䖭 䗕㽕 ⱘ ˈ 䭓 ЎSD_BLOCKSIZEDŽSD ԰⿟ ⏙ ⿟ ⏙ 1.8 ⼎ˈ 䆂 ⱘ ⫼ Ⳉ 䇗⫼䕃ӊⱘAPI ԰DŽ⿟ ⏙ 1.8 SD ԰ҷⷕ/******************************************************************************************** ⿄˖SD_WriteBlock** 㛑 䗄˖SPI῵ ϟ, SD/MMC Ё ϔϾ** 䕧 ˖sd_struct *sds˖SD/MMC 㒧 ԧ** INT32U blockaddr˖ҹ Ў ԡⱘ , ՟ , ⱘ0 ~ 511 㡖Ў 0, 512 ~** 1023 㡖ⱘ Ў1** INT8U *sendbuf ˖ 䗕㓧 ,䭓 Ў 512 㡖** 䕧 ˖** 䖨 ˖0˖ℷ⹂>0˖䫭䇃ⷕ, 㾕 sddriver.h ӊ******************************************************************************************/ INT8U SD_WriteBlock(sd_struct *sds, INT32U blockaddr, INT8U *sendbuf){ret,tmp[2];INT8USD_RequestOSSem(sds);/* OS ⬇䇋䆓䯂 䞣 */if (!SdHal_CheckCard(sds)) {SD_ReleaseO SSem(sds);return SD_ERR_NO _CARD;/* ≵ Ё */}if (blockaddr > sds->block_num) { SD_Release O SSem(sds);return SD_ERR_OVER_CARDRANGE; /* ԰䍙 䞣㣗 */ }if (SdHal_CheckCardWP(sds)) {SD_Release OSSem(sds);return SD_ERR_WRITE_PR O TECT; /* */ } ret = SpiCmd_Write_Single_Block(sds, blockaddr); /* Ҹ*/if (ret != SD_NO_ERR) {SD_Release OSSem(sds); return ret; } ret = SdSpi_WriteBlockData(sds, 0, SD_BLOCKSIZE, sendbuf);/**/if (ret == SD_NO_ERR) {/* 䇏 , Ẕ */ret = SpiCmd_Send_Status(sds, 2, tmp);if (ret != SD_NO_ERR) { SD_Release OSSem(sds);return ret;/* 䇏 䋹 */}if((tmp[0] != 0) || (tmp[1] != 0)) {SD_Release O SSem(sds);ret = SD_ERR_WRITE_BLK; /* ⼎ 䋹*/}} SD_ReleaseO SSem(sds);return ret;/* 䖨 㒧*/}3ˊ SD 䇏 ԰SD/MMC SPI ῵ ϟⱘ䇏 ԰г ϸ⾡˖䇏 䇏 DŽ ⼎՟䞡⚍ҟ㒡䇏 ԰DŽ SD_Initialize() 㒣䇗⫼њSpiCmd_Set_BlockLen() 䆒 њ䇏/ ⱘ䭓 SD_BLOCKSIZE 㡖DŽ ˈ䇏/ 䛑 ҹ Ў ԡˈ ҹϔ⃵䇏 ԰㟇 㽕䇏SD_BLOCKSIZE Ͼ 㡖DŽSD_BLOCKSIZE 㡖ϔ㠀䛑Ў512 㡖DŽSD 䇏 ԰⌕⿟ 1.10 ⼎DŽ䇏 䖭ḋ䖯㸠ⱘ˖1.10 SD 䇏 ԰⌕⿟(1)Џ 佪 Ẕ 㒣 Ё˗ (2)Ẕ 䍙 ⱘ 䞣㣗 ˗(3)ҹϞ ӊ⒵䎇 ˈ 䗕䇏 Ҹˈ䇏 Ўblockaddr ⱘϔϾ ˗ (4)䇗⫼䇏 Ң 䇏 ϔϾ DŽSD 䇏 ԰⿟ ⏙ ⿟ ⏙ 1.9 ⼎ˈ 䆂 ⱘ ⫼ Ⳉ 䇗⫼䕃ӊ ⱘAPI ԰DŽ⿟ ⏙ 1.9 SD 䇏 ԰ҷⷕ/****************************************************************************************** ** ⿄˖SD_ReadBlock** 㛑 䗄˖SPI ῵ ϟ, ҢSD/MMC Ё䇏 ϔϾ ** 䕧 ˖sd_struct *sds ˖SD/MMC 㒧 ԧ** INT32U blockaddr ˖ҹ Ў ԡⱘ , ՟ , ⱘ0 ~ 511 㡖Ў 0, 512 ~ ** 1023 㡖ⱘ Ў1** 䕧 ˖INT8U *recbuf ˖ 㓧 ,䭓 Ў 512 㡖** 䖨 ˖0˖ℷ⹂ >0˖䫭䇃ⷕ, 㾕 sddriver.h ӊ******************************************************************************************/ INT8U SD_ReadBlock(sd_struct *sds, INT32U blockaddr, INT8U *recbuf) {INT8U ret;SD_RequestOSSem(sds);/* OS ⬇䇋䆓䯂 䞣 */if (!SdHal_CheckCard(sds)) { SD_ReleaseOSSem(sds);return SD_ERR_NO_CARD;/* ≵ Ё */}if (blockaddr > sds->block_num) { SD_Release OSSem(sds);return SD_ERR_O VER_CARDRANGE; /* ԰䍙 䞣㣗 */ }ret = SpiCmd_Read_Single_Block(sds, blockaddr);/* 䇏 Ҹ*/if (ret != SD_NO_ERR) {SD_ReleaseOSSem(sds);return ret;}ret = SdSpi_ReadBlockData(sds, SD_BLOCKSIZE, recbuf); /* 䇏*/ SD_Release OSSem(sds); /* 䖬䆓䯂 䞣*/return ret;}1.6 SD/MMC 䇏 ῵ ⱘՓ⫼⼎՟Ѡϟ䴶㒭 LPC2103 ⧚ ϞՓ⫼SD/MMC 䇏 ῵ SD/MMC 䖯㸠䇏ǃ ǃⱘ՟ DŽ䆹՟ ѢuCOS-II ԰㋏㒳ˈ ⫼LPC2103կⱘSPI 䇏 SD/MMC ˈ䇏 ⱘ 䗮䖛LPC2103ⱘUART0 䗕 PC ⱘ䕃ӊ⬠䴶 ⼎ ˈ㽕 ⱘ г ҹ䗮䖛PC 䕃ӊ䗮䖛UART0 Ёˈ ˈ ՟ г կњ ⱘⓨ⼎DŽ 1.6.1⦄ ⊩՟ Џ㽕ⱘӏ ⓨ⼎䇏 SD/MMC ˈЎњ ⦄㛑 ⦄LPC2103ϢPC ⱘ䗮 ˈ ՟ Փ⫼њІ Ё䯈ӊϢ 䯳 Ё䯈ӊˈ 㞾PC ⱘ DŽ՟ ⱘ䕃ӊ㒧 1.11 ⼎DŽ1.11 ՟ ⦄ ⊩1.11Ёˈ ՟ ϸϾЁ䯈ӊ ϸϾӏ ˖ z І Ё䯈ӊϢ 䯳 Ё䯈ӊDŽ䖭ϸϾЁ䯈ӊ⫼Ѣ 㞾UART0ⱘ ˈ 䗮䖛UART0 䗕 PC DŽz І ӏ DŽ 㞾PC ⱘ ˈ 䋳䋷 ⱘ 䗕㒭 ԰ӏ DŽz԰ӏ DŽ 㞾І ӏ ⱘ ˈḍ Ё ⱘ Ҹ ⦄ SD/MMC ⱘ䇏ǃ ǃ DŽ 㸠㒧 Ѹ㒭І Ё䯈ӊϢ 䯳 Ё䯈ӊˈ⬅ Ӏ 䗕 PC ˈ 䇏 ⱘ 㸠ⱘ㒧 DŽ㾕ˈPC Ϣ ԰ӏ П䯈䳔㽕ϔϾ 䆂 䇗ˈ 㛑ℷ⹂ SD/MMC ⱘ ǃ䇏ǃ ǃ DŽℸˈ ҹ ϔϾㅔ ⱘ 䆂 ˖(1) НLPC2103ⱘUART0 㾺 Ё ⏅ Ў8Ͼ 㡖ˈ Н8Ͼ 㡖Ўϔ ˈⱘӴ䕧ҹ Ў ԡˈPC 䗕ⱘ ⿄Ў Ҹ ˈLPC2103 䗕ⱘ ⿄Ў DŽ(2)PC 䗕ⱘ↣ϔ ⱘ㄀1Ͼ 㡖Ў Ҹ ˈ2 ~ 8Ͼ 㡖Ў 䚼 ˈ 1.12⼎DŽ(3)LPC2103↣ PC ⱘϔϾ ˈḍ Ҹ 䖯㸠Ⳍ ⱘ ⧚˄ 䇏 ˅ˈ✊⧚㒧 ϔ PC ˈ ЎLPC2103 ⱘ Ҹ ˈ2 ~ 8 㡖Ў䚼 DŽPC ÆLPC213x ҸLPC213x ÆPC1.12 PC 䗕ⱘ Ҹ ϢLPC2103ⱘ(4) Ё 䕳ϔ⠛㓧 INT8U sd_buf[512]ˈ Ў520 㡖˄↨SD/MMCⱘϔϾ 8Ͼ 㡖˅DŽ⫼Ѣ Ң Ё䇏 ⱘ 䖯 Ёⱘ DŽ (5)ḍ ҹϞ ⚍ˈ ԰ӏ SD/MMC 䖯㸠 ǃ䇏ǃ ǃ ⱘ ⊩ˈ⼎ 1.13 ⼎DŽ1.13 ԰ӏ Ҹ ⱘ ⼎1.13 ⼎ˈ ԰ӏ ḍ Ҹ ⱘ㄀1Ͼ 㡖ˈ 㸠ϟ䴶ⱘ DŽ z CMD_SD_INIT Ҹˈ ҸDŽ ԰ӏ 㸠 SD/MMC ⱘ ˈ✊ 㸠㒧 ⱘ㄀2Ͼ 㡖ˈ PC 㒧 DŽ zCMD_SD_READ Ҹˈ䇏 ⱘ DŽPC 㽕䇏ⱘ CMD_SD_READ Ҹ ⱘϸϾ 㡖Ёˈ ԰ӏ 䇗⫼䇏 䇏 ⱘ ˈ Ѣsd_buf[]Ёˈ䇏 ⱘ䖨 ⱘ㄀2Ͼ 㡖ˈ PC 䇏 ԰ DŽ zCMD_SD_WRITE Ҹˈ ⱘ DŽPC 㽕 ⱘ CMD_SD_WRITE Ҹ ⱘϸϾ 㡖Ёˈ ԰ӏ 䇗⫼ sd_buf[]Ёⱘ Ёˈ ⱘ䖨 ⱘ㄀2Ͼ 㡖ˈ PC ԰ DŽzCMD_SD_ERASE Ҹˈ 䰸 ⱘ DŽPC 㽕 䰸ⱘ ⱘ Ϣ㽕 䰸ⱘ 䆹 Ҹ ⱘ 䴶ˈ ԰ӏ 䇗⫼ ⱘ 䰸ˈ 䰸 ⱘ䖨 ⱘ㄀2Ͼ 㡖ˈ PC 䰸 ԰ DŽz CMD_SD_RECV Ҹˈ ҸDŽ䆹 Ҹ ⱘ2 ~ 3 㡖 ⱘsd_buf[] ˈ4 ~ 8 㡖ЎPC ⱘ ˈ ԰ӏ ⱘsd_buf[]ⱘЁDŽz CMD_SD_TRANS Ҹˈ 䗕 ҸDŽ䆹 ⱘ㄀2 ㄀3Ͼ 㡖 PC 㽕䇏 sd_buf[]Ёⱘ ⱘ㓧 ˈ ԰ӏ 䆹 ⱘ PC ˈѢ ⱘ2 ~ 8 㡖ЁDŽ㸠ҹϞӏԩϔϾ ˈ ԰ӏ 䛑 䗕 PC DŽ(6) ⫼ҹϞ Ҹˈ 䖯㸠 ǃ䇏ǃ ǃ 䖭ḋ䖯㸠ⱘˈ 1.14 ⼎DŽ䇏䰸1.14 䖯㸠 ⾡ ԰䳔㽕 㸠ⱘ ҸҹϞ ⚍ ⦄ 1.11ⱘ ԧ 䆂DŽϟ䴶 㒭 ⦄ ՟ ⱘ 偠ℹ偸ˈ✊ 㒭 ⦄ҹϞ 䆂ⱘ⼎՟ҷⷕDŽ1.6.2՟ ゟϢ䖤㸠ℹ偸ϟ䴶ㅔ 䇈 ՟ ⱘ ゟ䖛⿟DŽ1.⫼ADS1.2 ゟϔϾ ⿟ˈ ⿟ ЎSDMMCExamˈ ゟ Փ⫼ ⿟῵ ARMImage for uCOSII for LPC2103DŽ ゟ ˈ⫳ ӊ SDMMCExamDŽ2. SDMMCExamⳂ ϟ ゟϔϾⳂ SDMMCˈ 䆹Ⳃ ϟ 㕂SD/MMC 䇏῵ ⱘ ӊDŽ3. SDMMCExamⱘ 㑻Ⳃ ϟ ゟarm Source ӊ ˈSource ӊ 㕂ȝC/OS-II⑤ҷⷕDŽarmⳂ Ё 㕂ϢLPC2000⹀ӊⳌ ⱘȝC/OS-II⿏ỡҷⷕDŽ4. SDMMCExamⳂ ϟ ゟϔϾ ӊ uart0ˈ І Ё䯈ӊⳌ ӊ Ѣ䆹ӊ Ёˈ ゟqueue ӊ ˈ 䯳 Ё䯈ӊⳌ ӊ Ѣ䆹 ӊ ЁDŽ5. ⿟Ё ゟ3Ͼ㒘ˈ ЎSDMMCǃuartǃqueueˈ ⱘ῵ Ё䯈ӊ䖭ѯ㒘ЁDŽ6. config.hЁ 䰸 ⱘĀ#include "..\..\Arm_Pc\pc.h"ā䇁 DŽ7. ⿟Ёⱘconfig.h ӊˈ LPC2103 䆒 䩳乥⥛ ҹϟ DŽ#define Fpclk (Fcclk / 4) * 48. sdconfig.h ӊˈ НSD_EraseBlock_ENⱘ 㕂Ў1DŽ#define SD_EraseBlock_EN 19. config.h ӊЁ Ⳍ ῵ Ё䯈ӊⱘ ӊ 䜡㕂DŽ ⿟ ⏙ 1.10 ⼎DŽ⿟ ⏙ 1.10Ⳍ ῵ Ё䯈ӊⱘ ӊ 䜡㕂/* SD/MMC ῵ ӊ */#include "sdconfig.h"#include "sddriver.h"/* 䯳 ⱘ䜡㕂 */#define QUEUE_DATA_TYPE uint8#include "\queue\queue.h"#define EN_QUEUE_WRITE 1 /* ⽕ℶ(0) 䆌(1)FIFO 䗕 */#define EN_QUEUE_WRITE_FRO NT 0 /* ⽕ℶ(0) 䆌(1)LIFO 䗕 */#define EN_QUEUE_NDATA 1 /* ⽕ℶ(0) 䆌(1) 䯳 Ⳃ*/#define EN_QUEUE_SIZE 1 /* ⽕ℶ(0) 䆌(1) 䯳 䞣 */#define EN_QUEUE_FLUSH 0 /* ⽕ℶ(0) 䆌(1)⏙ぎ䯳 *//* UART0ⱘ䜡㕂 */#include "uart0.h"#define UART0_SEND_QUEUE_LENGTH 60 /* 㒭UART0 䗕 䯳 䜡ⱘぎ䯈 */10. os_cfg.h ӊˈ ԰㋏㒳Փ⫼ⱘ џӊ Ў3DŽ#define O S_MAX_EVENTS 311. ⹀ӊ 㒓 1.5ϔḋˈ䙷М 乏䜡㕂sdconfig.hˈ 1.4.1 㡖ⱘ䇈䖯㸠䜡㕂DŽ 䆂 sdconfig.h ӊ ѢSDMMCExam\srcⳂ ϟˈ Ў䖭 䜡㕂SD/MMC䇏 ῵ ⱘ ӊˈ ҹ㹿⫼ ⱘ ӊDŽ12. ⿟irq.s ӊⱘ ⏏ UART0Ё ⿟ ⱘ∛㓪䇁㿔䚼 ҷⷕˈ ⿟⏙ 1.11 ⼎⿟ ⏙ 1.11 UART0Ё ⿟ ⱘҷⷕ;/* 0Ё */;/*Time0 Interrupt*/Timer0_Handler HANDLER Timer0_Exception;/*䗮⫼І㸠 0Ё */UART0_Handler HANDLER UART0_Exception13. Target.c ӊⱘTargetInit() Ёˈ⏏ UART0ⱘҷⷕˈ ⿟ ⏙ 1.12⼎DŽ⿟ ⏙ 1.12⏏ UART0 ҷⷕvoid TargetInit(void){O S_ENTER_CRITICAL();srand((uint32) TargetInit);VICInit();Timer0Init();UART0Init(115200);OS_EXIT_CRITICAL();}14. Target.c ӊⱘVICInit() Ёˈ⏏ UART0 䞣Ё ⱘ ҷⷕˈ ⿟⏙ 1.13 ⼎DŽ⿟ ⏙ 1.13 U ART0 䞣Ёvoid VICInit(void){extern void IRQ_Handler(void);extern void Timer0_Handler(void);extern void UART0_Handler(void);VICIntEnClr = 0xffffffff;VICDefVectAddr = (uint32)IRQ_Handler;VICVectAddr14 = (uint32)UART0_Handler;VICVectCntl14 = (0x20 | 0x06);VICIntEnable = 1 << 6;VICVectAddr15 = (uint32)Timer0_Handler;VICVectCntl15 = (0x20 | 0x04);VICIntEnable = 1 << 4;}15.ḍ ՟ ⱘ 䆂 ˈ main.c ӊЁ㓪 䗮䖛І 䇏 SD/MMC ⱘⳌDŽ16.䗝 DebugInFlash⫳ Ⳃ ˈ✊ 㓪䆥䖲 ⿟DŽ ADS1.2䲚 ⦃ Ё䗝ProjectÆDebugˈ AXD䖯㸠JTAGӓⳳ䇗䆩ˈ 䗳䖤㸠⿟ DŽ17.⹂ ⹀ӊ䖲 ℷ⹂ˈSD MMC ЁDŽ18. ѻ ⲬЁ կⱘPC ッ 㸠䕃ӊSDExample.exe ⹀Ⲭˈ ADS1.2ⱘ⿟ 䖤㸠 䖤㸠䆹䕃ӊDŽ䕃ӊ⬠䴶 1.15 ⼎DŽ19. 1.15Ёˈ䗝 І 䗮 ⊶⡍⥛ˈ✊ Ā䖲 LPC2103ā 䬂ˈĀ 㸠㒧 āḚЁ ⼎䆹䕃ӊ 㛑ϢLPC2103 䗮 DŽ20. І ˈ䙷М䇋 Ā SD/MMC āˈ Ā㸠㒧 āЁ ⼎ DŽ 䋹ˈ䆹Ā 㸠㒧 ā ⼎ 䫭䇃ҷⷕˈ⼎ⱘ䫭䇃ⷕϢ㸼1.12ϔϔ ˈ㒭 䫭䇃ⷕⱘⳂⱘ ⫼ 䇗䆩⿟ DŽ21.SD/MMC ˈ Ā䇏 āḚЁ 㽕䇏ⱘ ⱘ ˈ✊ ˈĀ䇏ā 䬂ˈ䇏 ⱘ ⱘ Ā ⼎āḚЁ ⼎ ˈĀ 㸠㒧 āḚ⼎ 㸠㒧 ˈ 㸠㒧 䫭ˈ 㒭 䫭䇃ҷⷕDŽ1.15䖲 LPC2103 SD/MMC22. 㽕 ˈ 䳔㽕⫼哴 ⚍ Ā ⼎āḚЁⱘĀ ā ˈ✊⫼䬂Ⲭ䬂 㽕 ⱘ ˈ✊ Ā ā 䬂ˈ䕃ӊ 䆹 SD/MMC ЁˈĀ 㸠㒧 āḚ ⼎ 㸠㒧 DŽ 1.16 ⼎DŽ1.16 SD/MMC㽕 SD/MMC ˈ䙷М䇋 Ā 䰸ā 䬂ˈ 1.17 ⼎ⱘ 䰸 䆱Ḛˈ 䍋 㽕 䰸ⱘ ˈ✊ Ā 䰸āDŽ 䰸 ԰ 㸠㒧 1.16 ⼎ⱘĀ 㸠㒧 āЁ ⼎ DŽ 䰸䰤 5000 ⱘⳂⱘ 䰆ℶ 䰸 䯈 䭓 㟈І㸠䗮 䍙 ˈ 䴲䇈SD/MMC ϔ⃵ 䰸 ԰ 㛑 5000 DŽO1.17 䰸 ԰ 䆱Ḛ1.17䖬 ⼎⫼ ⱘĀ䍋 ā Ā 䞣ā 䆂Ўsds.erase_uintⱘ DŽ䖭 Ў ϔѯ ⱘ ԡЎsds.erase_uint ˈг 䇈ˈ Փ Ҹ 䰸Ā䍋 ā䖭ϔ ˈԚSD/MMC 䰸Ā䍋 ā ⱘsds.erase_uint DŽ1.6.3 㗗⿟1. main.c ӊЁ Ⳍ ӊ Н ⫼ ⱘ 䞣DŽ ⿟ ⏙ 1.14⼎DŽ⿟ ⏙ 1.14 Ⳍ ӊ НⳌ 䞣#include "config.h"#define TASK_STK_SIZE 64 (1)Ҹ*/ (2)/*CMD_SD_INIT 0x00#define#define CMD_SD_READ 0x01 /* 䇏 Ҹ*/ #define CMD_SD_WRITE 0x02 /* Ҹ*/ #define CMD_SD_ERASE 0x03 /* 䰸 Ҹ*/ #define CMD_DATA_TRANS 0x04 /* sd_bufЁⱘ 䗕 PC */ #define CMD_DATA_RECV 0x05 /* 㞾І ⱘ , sd_bufЁ */ /* SD/MMC 䇏 㓧 ,↨SD/MMC ϔϾ 8 㡖 */uint8sd_buf[520]; (3) ⿟ ⏙ 1.14(1) Нњӏ Փ⫼ⱘ ˈ⿟ ⏙ 1.14(2)ЎPC 䗕ⱘ Ҹ ⱘ Ҹ Нˈ⿟ ⏙ 1.14(3)ЎSD/MMC 䇏 Փ⫼ⱘ㓧 ˈ䆹㓧 ↨SD/MMC ⱘϔϾ 8Ͼ 㡖ˈ䖭ḋ НⱘⳂⱘ ЎњІ ԰ⱘ ˄І ⱘ ҹ8Ͼ 㡖԰Ў Ё 㾺 ⏅ ˅DŽ2. Н ӏ ⱘ UART0 䚂ㆅˈ ⿟ ⏙ 1.15 ⼎DŽ⿟ ⏙ 1.15 䚂ㆅ НO S_STK TaskStk[TASK_STK_SIZE]; /* ӏ */ O S_STK TaskCardStk[TASK_STK_SIZE]; /* ԰ӏ */І 䚂ㆅ*//*S_EVENT*Uart0ReviceMbox;3.㓪 Џ main()ˈ ⿟ ⏙ 1.16 ⼎DŽ њ ԰㋏㒳䖤㸠ⱘ㄀ϔϾӏ TaskCard ()ˈ ⿟ ⏙ 1.16(1) ⼎DŽ⿟ ⏙ 1.16 main()int main (void){O SInit();OSTaskCreate(TaskCard, (void *)0, &TaskCardStk[TASK_STK_SIZE - 1], 0); (1) OSStart();return 0;}4.㓪 ԰ӏ TaskCard()ˈ䆹 ԰Ўmain() ⱘ㄀1Ͼӏ ˈⳌ ⹀ӊ˄ ⿟ ⏙ 1.17(3)˅ˈ ゟІ 䚂ㆅ˄ ⿟ ⏙ 1.17(1)⼎˅ ӏ ˄ ⿟ ⏙ 1.17(2) ⼎˅ˈ ӏ Ў ԰ӏ DŽ⿟ ⏙ 1.17 ԰ӏvoid TaskCard(void *pdata){uint8 *pRec;uint8 err;uint32 bufaddr,blockaddr,blocknum;pdata = pdata; /* 䙓 㓪䆥䄺 */Uart0ReviceMbox = O SMboxCreate(NULL); /* ゟ䚂ㆅ*/ (1) if (Uart0ReviceMbox == NULL)while (1);O STaskCreate(TaskUart0Revice, (void *)0,&TaskStk[TASK_STK_SIZE - 1], 10); /* Uart0 ӏ */ (2) TargetInit(); /* Ⳃ */ (3)for (;;){pRec = (uint8 *)O SMboxPend(Uart0ReviceMbox, 0, &err); /* */ (4) switch(pRec[0]) (5) {case CMD_SD_INIT: pRec[1] = SD_Initialize(); /* */ (6)break;case CMD_SD_READ: (7) blockaddr = (pRec[1] << 24) + (pRec[2] << 16) + /* 䅵ㅫ */+pRec[4];<<8)(pRec[3]pRec[1] = SD_ReadBlock(blockaddr, sd_buf); /* 䇏 */ break;case CMD_SD_WRITE:blockaddr = (pRec[1] << 24) + (pRec[2] << 16) ++pRec[4];8)(pRec[3]<<pRec[1] = SD_WriteBlock(blockaddr, sd_buf); /* */ break;case CMD_SD_ERASE:blockaddr = (pRec[1] << 24) + (pRec[2] << 16) +(pRec[3] << 8) + pRec[4]; /* 䍋 */ blocknum = (pRec[5] << 16) + (pRec[6] << 8) +(pRec[7]); /* */ pRec[1] = SD_EraseBlock(blockaddr, blocknum); /* 䰸 ԰*/ break;case CMD_DATA_RECV:bufaddr = (pRec[1] << 8) + pRec[2]; /* 䅵ㅫ㓧 */memcpy(sd_buf + bufaddr, &pRec[3], 5); /* pRec */ break;case CMD_DATA_TRANS:bufaddr = (pRec[1] << 8) + pRec[2]; /* 䅵ㅫ㓧 */memcpy(&pRec[1], sd_buf + bufaddr, 7); /* sd_buf pRec */ break;default: break;}UART0Write(pRec, 8); /* 䗕 */ (8) }}⿟ ⏙ 1.17(4) 䚂ㆅㄝ І ӏ TaskUart0Revice() 䚂ӊˈ䚂ӊЎ ⱘ ⱘ㓧 䍋 pRecDŽ⿟ ⏙ 1.17(5) 䚂ㆅЁ ˈг PC ⱘϔϾ Ҹ ˈ Ҹ ⱘ㄀1Ͼ㡖Ў Ҹ ˈ䙷М 㸠 Ͼ Ҹ DŽ⿟ ⏙ 1.17(6) 㸠 Ҹ ˈ 㸠㒧 ѢpRec[1]ЁDŽ⿟ ⏙ 1.17(7) 㸠䇏 Ҹ ˈ 䅵ㅫ ˈ✊ 䇏 ⱘ ˈ䇏 ⱘѢ 㓧 sd_buf[]Ёˈ䇏 ⱘ䖨 ѢpRec[1]ЁDŽҸ ˈ ǃ ⱘ ԰ 䇏 Ҹ ⱘ⿟ 㸠 ⧚гϔḋDŽ⿟ ⏙ 1.17(8) ⱘ 㸠㒧 䗮䖛І Ё䯈ӊ 䗕 PC DŽ5.UART0 ӏ DŽ ⿟ ⏙ 1.18(1) ⼎ˈ䆹ӏ 䇗⫼І Ё䯈ӊⱘ㡖 UART0Getch()ㄝ 㞾PC ⱘ ˈ ˈ䙷МҢІ ⱘ㓧 䇏 8Ͼ 㡖ˈ䇏 ⱘ ѢBuf[]ЁDŽ✊ Buf[]ⱘ 䚂ㆅUart0ReviceMboxЁ˄ ⿟ ⏙ 1.18(2) ⼎˅䗮ⶹ ԰ӏ TaskCard()˖њˈ Buf[]ЁDŽ䖭ḋ ԰ӏ ҹḍ ⱘ 䖯㸠Ⳍ԰њDŽ⿟ ⏙ 1.18 U ART0 ӏvoid TaskUart0Revice(void *pdata){uint8 Buf[4],i;pdata = pdata; /* 䙓 㓪䆥䄺 */for (;;){Buf[0] = UART0Getch(); /* */ (1) for (i = 1; i < 8; i++)Buf[i] = UART0Getch();O SMboxPost(Uart0ReviceMbox, (void *)Buf); (2) }}ҹϞ՟ Ёˈ Ͼ Ϣ ԰Ⳍ ˈ 䚼 䇁 䛑 ⧚PC ϢLPC2103П䯈ⱘ 䗮 ˈҹ 䇗 ⱘ ⾡ ԰DŽ ՟ ϡҙ㒭 њ SD/MMC䇏 ῵ API ⱘՓ⫼ ⊩ˈ䖬⼎՟њ ԩՓ⫼ Ͼ῵ Ё䯈ӊ 㒘 ϔϾ ⿟DŽ1.7 SD/MMC䕃ӊ ⫼ 㒧ZLG/SDⱘ䬔/ 䕃ӊ ҟ㒡 ℸˈ⫼ ҹ 䰙 ⫼Ё ⫼ 䕃ӊ ˈ䞛⫼Ⳉ 䇗⫼API ⫼ ⱘ ⊩ ⦄䇏ǃ ǃ 䰸SD/MMC ㄝ ԰DŽ。

SD卡读写操作

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卡读写

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卡数据读写操作时,需要了解其基本流程及相关细节。

本文将详细介绍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卡(Secure Digital Memory Card)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。

SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。

大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。

贴程序:/*-------------------------------------1.本程序主要为了实现以下功能:1)通过对SPI方式对SD卡进行读与写2)简单的FAT操作3)对写入的数据进行打印2.编写日期:09.10.133.版本号:V1.04.作者:andyluo----------------------------------------*/#include<reg52.h> //添加头文件#define uchar unsigned char //宏定义数据类型#define uint unsigned int/*-------------------------------------与指示灯有关的IO--------------------------------------*/sbit power=P0^4;/*-------------------------------------与SD卡通信有关的IO---------------------------------------*/sbit SCL=P1^5;//时钟信号sbit CS=P1^6;//片选信号sbit SI=P1^7;//数据输入sbit SO=P3^3;//数据输出//错误码定义#define INIT_CMD0_ERROR 0X01#define INIT_CMD1_ERROR 0X02#define WRITE_BLOCK_ERROR 0X03#define READ_BLOCK_ERROR 0X04/*--------------------------------------与通信和定时器相关的变量---------------------------------------- */uchar cn=0;/*--------------------------------------变量定义-----------------------------------------*/uchar is_init;//用于控制SPI的速度,通过为1与0进行选择uchar xdata pbuf[512];//定义512个数据缓冲区/*--------------------------------------函数名称:delay()函数作用:用于某些程序中的延时函数特点:无返回值,带入口参数-----------------------------------------*/void delay(uint k){uint m,n;for(m=0;m<5;m++)for(n=0;n<k;n++);}/*-------------------------------SPI写一个字节----------------------------------*/void spi_write(uchar x)//SPI写一个字节,其中is_init为1 {uchar i;for(i=0;i<8;i++){SI=((x<<i)&0x80);SCL=0;if(is_init){delay(8);}SCL=1;if(is_init){delay(8);}}}/*--------------------------------SPI读一个字节----------------------------------*/uchar spi_read(){uchar temp=0,i;SO=1;for(i=0;i<8;i++){SCL=0;if(is_init){delay(8);}// if(SO)// {// temp+=(0x80>>i);// }temp=(temp<<1)+(uchar)SO;SCL=1;if(is_init)//放慢速度{delay(8);}}return(temp);}/*--------------------------------向SD卡写命令---------------------------------*/uchar write_cmd(uchar *pcmd)//pcmd为命令字{uchar temp,i,time=0;CS=1;spi_write(0XFF);CS=0;for(i=0;i<6;i++) //发送6个字节的命令字节序列{spi_write(*pcmd++);}spi_read();do{temp=spi_read();//一直读,直到读到的不是0XFF或者超时time++;}while((temp==0xff)&&(time<100));return temp;}/*------------------------------------SD卡复位,进入SPI模式,使用CMD0命令-------------------------------------*/uchar SD_Reset()//SD卡复位{uchar time,temp,i;uchar pcmd[]={0x40,0x00,0x00,0x00,0x00,0x95};//0号命令对应的6个字节is_init=1;//set is_init flagCS=1;for(i=0;i<0x0f;i++)//初始化时,首先要发送至少74个时钟信号,这是必须的{spi_write(0xff);//实质发了120个时钟(15*8)}CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==200){return(INIT_CMD0_ERROR );//cmd0写入失败}}while(temp!=0x01);CS=1;spi_write(0xff);//按照SD的操作时序在这里需要补8个时钟return 0;//返回0,说明SD卡复位操作成功}/*-------------------------------------SD卡初始化,使用CMD1号命令---------------------------------------*/uchar SD_Init()//SD卡初始化,使用CMD1号命令{uchar time,temp;uchar pcmd[]={0x41,0x00,0x00,0x00,0x00,0xff};CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(INIT_CMD1_ERROR );}}while(temp!=0x00);is_init=0;//初始化完成,将is_init设置为0,以提高后面数据的传输速度CS=1;spi_write(0xff);return 0;//说明初始化成功}/*-----------------------------向SD卡扇区中写数据,每一个扇区中有512个字节---------------------------------*/uchar SD_write_sector(unsigned long addr,uchar *Buffer){uchar temp,time;uint i;uchar pcmd[]={0x58,0x00,0x00,0x00,0x00,0xff};//向SD卡中写入24号命令addr=addr<<9;//addr=addr+512,将块地址(扇区地址)转化为字节地址pcmd[1]=((addr&0xff000000)>>24);//将字节地址写入到24号命令的时序中pcmd[2]=((addr&0x00ff0000)>>16);pcmd[3]=((addr&0x0000ff00)>>8);//SD卡最大容量4G// pcmd[4]=(addr&0x000000FF);//此行为增加项CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(temp);//命令写入失败}}while(temp!=0);for(i=0;i<100;i++)//这里要插入若干个时钟信号{spi_read();}spi_write(0xfe);//写入开始字节0XFE,后面就要写入512个字节for(i=0;i<512;i++)//将缓冲区中要写入的512个字节写入到SD卡中{spi_write(*Buffer++);}spi_write(0xff);spi_write(0xff);//两个字节CRC校验码temp=spi_read();//读取返回值if((temp&0x1f)!=0x05)//如果返回值为xxx00101,说明数据已经被接收{CS=1;return(WRITE_BLOCK_ERROR );//写块数据失败}while(spi_read()!=0xff);//等待SD卡不忙(数据被接收以后,SD卡要将这些数据写入自身的FLASH// 中,需要一定时间,忙时为0x00,不忙是为0xff, )CS=1;spi_write(0xff);//补8个时钟return 0;}/*--------------------------------读SD卡的一个扇区---------------------------------*/uchar SD_read_sector(unsigned long addr,uchar *Buffer){uint i;uchar time,temp;uchar pcmd[]={0x51,0x00,0x00,0x00,0x00,0xff};//CMD17号命令addr=addr<<9;pcmd[1]=((addr&0xff000000)>>24);pcmd[2]=((addr&0x00ff0000)>>16);pcmd[3]=((addr&0x0000ff00)>>8);CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(READ_BLOCK_ERROR);//读块失败}}while(temp!=0);while(spi_read()!=0xfe);//一直读,当读到0xfe时,说明后面是512个数据字节for(i=0;i<512;i++){Buffer[i]=spi_read();}spi_read();spi_read();CS=1;spi_write(0xff);//补8个时钟return 0;}/*---------------------------------串口初始化-----------------------------------*/void serial_init(void) //{TMOD = 0x21; //使用定时器1工作在方式2,做波率发生器,定时器0方式1 TH0 = 0X3c; //设置定时初值,定时20ms,1s采用20*50算法TL0 = 0Xb0;ET0 = 1; //开定时器0中断标志TR0 = 1; //启动定时器0TH1 = 0xfd; //32M,9600TL1 = 0xfd;TR1 = 1; //启动定时器1SCON=0X40; //串口工作在方式1,不允许接收REN = 1; //允许串口接收ES = 1; //允许串口中断EA = 1; //开总中断}/*-------------------------函数名称:main()函数作用:主函数---------------------------*/void main(){int i=0;SD_Reset();SD_Init();serial_init();for(i=0;i<512;i++){pbuf[i]=i;//向缓冲区中写入数据}SD_write_sector(80,pbuf);//将缓冲区中512个字节的数据写入80扇区for(i=0;i<512;i++){pbuf[i]=0;//清空数据缓冲区}SD_read_sector(80,pbuf);//从SD卡的第80个扇区中读取512个字节的数据for(i=0;i<512;i++){P2=~pbuf[i];//将缓冲区中的数据输出在P2口,delay(1000);}//P2=0X00;while(1);}void timer0_int(void) interrupt 1 //中断程序,注意中断类型号{TH0=0X3c; //重新赋初值,并且必须要这样做,不然的话定时时间会不准确的TL0=0Xb0;cn++; //每当进入中断程序,count++,当有关参数设置正确后,程序会自动进入中断程序if(cn==20){cn=0;power = !power; //本机运行指示灯闪烁}}2009-10-17,09:26:21资料邮件回复引用回复编辑删除【1楼】andyluo324积分:123派别:程序还不够完善,等会改好后上完整版.2009-10-17,09:资料邮件编辑删除---------------------------------------- */uchar cn=0;/*--------------------------------------变量定义-----------------------------------------*/uchar is_init;//用于控制SPI的速度,通过为1与0进行选择uchar xdata pbuf[512];//定义512个数据缓冲区/*--------------------------------------函数名称:delay()函数作用:用于某些程序中的延时函数特点:无返回值,带入口参数-----------------------------------------*/void delay(uint k){uint m,n;for(m=0;m<5;m++)for(n=0;n<k;n++);}/*----------------------------------------函数名称:IO_init()函数作用:对相关IO进行初始化函数特点:无返回值,无入口参数------------------------------------------*/void IO_init(){SCL=1;CS=1;SO=1;power=1;}/*----------------------------------------函数名称:send_byte(uchar i)函数作用:对相关数据进行打印函数特点:无返回值,带入口参数--------------------------------------------*/void send_byte(uchar i){TI=0;SBUF=i;while(!TI);TI=0;}/*-------------------------------------------------------函数名:send_s()功能:用户函数,发送一个字符----------------------------------------------------------*/void send_s(char *s){int len=strlen(s);int i;for(i=0;i<len;i++)send_byte(s[i]);send_byte(0x0d);send_byte(0x0a);}/*-------------------------------SPI写一个字节----------------------------------*/void spi_write(uchar x)//SPI写一个字节,其中is_init为1{uchar i;for(i=0;i<8;i++){SI=((x<<i)&0x80);SCL=0;if(is_init){delay(8);}SCL=1;if(is_init){delay(8);}}}/*--------------------------------SPI读一个字节----------------------------------*/uchar spi_read(){uchar temp=0,i;SO=1;for(i=0;i<8;i++){SCL=0;if(is_init){delay(8);}// if(SO)// {// temp+=(0x80>>i);// }temp=(temp<<1)+(uchar)SO;SCL=1;if(is_init)//放慢速度{delay(8);}}return(temp);}/*--------------------------------向SD卡写命令---------------------------------*/uchar write_cmd(uchar *pcmd)//pcmd为命令字{uchar temp,i,time=0;CS=1;spi_write(0XFF);CS=0;for(i=0;i<6;i++) //发送6个字节的命令字节序列{spi_write(*pcmd++);}spi_read();do{temp=spi_read();//一直读,直到读到的不是0XFF或者超时time++;}while((temp==0xff)&&(time<100));return temp;}/*------------------------------------SD卡复位,进入SPI模式,使用CMD0命令-------------------------------------*/uchar SD_Reset()//SD卡复位{uchar time,temp,i;uchar pcmd[]={0x40,0x00,0x00,0x00,0x00,0x95};//0号命令对应的6个字节send_s("SD_Reset start\n");is_init=1;//set is_init flagCS=1;for(i=0;i<0x0f;i++)//初始化时,首先要发送至少74个时钟信号,这是必须的{spi_write(0xff);//实质发了120个时钟(15*8)}send_s("send 120 clk succeed\n");CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==200){return(INIT_CMD0_ERROR );//cmd0写入失败send_s("send CMD0 ERROR\n");}}while(temp!=0x01);CS=1;spi_write(0xff);//按照SD的操作时序在这里需要补8个时钟send_s("send CMD0 succeed\n");return 0;//返回0,说明SD卡复位操作成功}/*-------------------------------------SD卡初始化,使用CMD1号命令---------------------------------------*/uchar SD_Init()//SD卡初始化,使用CMD1号命令{uchar time,temp;uchar pcmd[]={0x41,0x00,0x00,0x00,0x00,0xff};send_s("SD_Init start\n");CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(INIT_CMD1_ERROR );send_s("CMD1 ERROR\n");}}while(temp!=0x00);is_init=0;//初始化完成,将is_init设置为0,以提高后面数据的传输速度send_s("send CMD1 succeed\n");CS=1;spi_write(0xff);send_s("SD_Init succeed\n");return 0;//说明初始化成功}/*-----------------------------向SD卡扇区中写数据,每一个扇区中有512个字节---------------------------------*/uchar SD_write_sector(unsigned long addr,uchar *Buffer){uchar temp,time;uint i;uchar pcmd[]={0x58,0x00,0x00,0x00,0x00,0xff};//向SD卡中写入24号命令addr=addr<<9;//addr=addr+512,将块地址(扇区地址)转化为字节地址pcmd[1]=((addr&0xff000000)>>24);//将字节地址写入到24号命令的时序中pcmd[2]=((addr&0x00ff0000)>>16);pcmd[3]=((addr&0x0000ff00)>>8);//SD卡最大容量4G// pcmd[4]=(addr&0x000000FF);//此行为增加项send_s("SD_write_sector start\n");CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(temp);//命令写入失败}}while(temp!=0);for(i=0;i<100;i++)//这里要插入若干个时钟信号{spi_read();}spi_write(0xfe);//写入开始字节0XFE,后面就要写入512个字节for(i=0;i<512;i++)//将缓冲区中要写入的512个字节写入到SD卡中{spi_write(*Buffer++);}spi_write(0xff);spi_write(0xff);//两个字节CRC校验码temp=spi_read();//读取返回值if((temp&0x1f)!=0x05)//如果返回值为xxx00101,说明数据已经被接收{CS=1;return(WRITE_BLOCK_ERROR );//写块数据失败}while(spi_read()!=0xff);//等待SD卡不忙(数据被接收以后,SD卡要将这些数据写入自身的FLASH// 中,需要一定时间,忙时为0x00,不忙是为0xff, )send_s("SD_write_sector succeed\n");CS=1;spi_write(0xff);//补8个时钟return 0;}/*--------------------------------读SD卡的一个扇区---------------------------------*/uchar SD_read_sector(unsigned long addr,uchar *Buffer){uint i;uchar time,temp;uchar pcmd[]={0x51,0x00,0x00,0x00,0x00,0xff};//CMD17号命令addr=addr<<9;pcmd[1]=((addr&0xff000000)>>24);pcmd[2]=((addr&0x00ff0000)>>16);pcmd[3]=((addr&0x0000ff00)>>8);send_s("SD_read_sector start\n");CS=0;time=0;do{temp=write_cmd(pcmd);time++;if(time==100){return(READ_BLOCK_ERROR);//读块失败}}while(temp!=0);while(spi_read()!=0xfe);//一直读,当读到0xfe时,说明后面是512个数据字节for(i=0;i<512;i++){Buffer[i]=spi_read();}spi_read();spi_read();CS=1;send_s("SD_read_sector succeed\n");spi_write(0xff);//补8个时钟return 0;}/*---------------------------------串口初始化-----------------------------------*/void serial_init(void) //{TMOD = 0x21; //使用定时器1工作在方式2,做波率发生器,定时器0方式1 TH0 = 0X3c; //设置定时初值,定时20ms,1s采用20*50算法TL0 = 0Xb0;ET0 = 1; //开定时器0中断标志TR0 = 1; //启动定时器0TH1 = 0xfd; //11.0592M,9600TL1 = 0xfd;TR1 = 1; //启动定时器1SCON=0X40; //串口工作在方式1,不允许接收REN = 1; //允许串口接收ES = 1; //允许串口中断EA = 1; //开总中断}/*-------------------------函数名称:main()函数作用:主函数---------------------------*/void main(){int i=0;serial_init();send_s("serial_init!\n");IO_init();send_s("Port Init!\n");SD_Reset();SD_Init();for(i=0;i<512;i++){pbuf[i]=i;//向缓冲区中写入数据}SD_write_sector(80,pbuf);//将缓冲区中512个字节的数据写入80扇区for(i=0;i<512;i++){pbuf[i]=0;//清空数据缓冲区}SD_read_sector(80,pbuf);//从SD卡的第80个扇区中读取512个字节的数据for(i=0;i<512;i++){P2=~pbuf[i];//将缓冲区中的数据输出在P2口,send_byte(pbuf[i]);delay(1000);}//P2=0X00;while(1);}。

SD卡读写学习-----使用文档

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。

sd卡读写程序(SD card read and write program)

sd卡读写程序(SD card read and write program)

sd卡读写程序(SD card read and write program)SD card read and write programObjective: To study the SD card / / operationDesign / software1, using SPI communication / / SD card2, go to SD / / in order to 0-255 a total of 256 data, and then read back LCD1602 display/ / hardware requirements:S11 ON / / dial switchJumper J18 / / all connected#include <p30f6014.h> //dsPIC30F6014 standard header file_FOSC (CSW_FSCM_OFF & XT_PLL4); //4 doubler crystal oscillator, Failsafe clock closed_FWDT (WDT_OFF); / / close the watchdog timer_FBORPOR (PBOR_OFF & MCLR_EN); / / reset prohibited MCLR reset enable._FGS (CODE_PROT_OFF); / / code protection against#define CS PORTGbits.RG9 / / SD card selection pin definition#define RS TB4 / / definition LCD control bits (note here can only register with LATB, you cannot directly use the PORTB register)#define RW TB5#define e TB6Unsigned char __attribute__ ((address (0x900)))lcd[3]={0,0,0};Void (spi_init); / / declaration system initial functionVoid (spi_low); / / that produces low baud rate (using the SD card initialization function)Void (spi_high); / / that produce high baud rate function (SD card initialization after use)Unsigned char (sd_reset); / / that the SD card initialization functionUnsigned char SD_SendCommand (unsigned char CMD unsigned, long ARG); / / write SD card command function statementUnsigned char SPI_WriteByte (unsigned char VAL); / / write a byte function statementUnsigned char SPI_ReadByte (void); / / that receive a byte functionUnsigned char SD_WriteSingleBlock (unsigned long sector); / / that single BLOCK data write SD card functionUnsigned char SD_ReadSingleBlock (unsigned long sector); / / read SD card data function single BLOCK statementVoid (lcd_display); / / state results display functionVoid (delay); / / state delay function (shown by)/ / system initialization functionVoid spi_init (){TRISG=0x00d0; / / set the SDI output, C output port for the otherTRISB=0X0000; / / set for the output port BTRISD=0X0000; / / set for the output port DSPI2CON=0x0278; / / idle bus is high, fosc/64SPI2STAT=0x8000; / / the end of sampling the output data of input data, the rising edge of data transmission}Write a LCD program ****************************************//*************************/ / write a byte of data functionAfter changing the level / / on the need to insert a delay time, otherwise the LCD react.Void write (unsigned char x){PORTD=x; / / PORTD port to send data to be displayedDelay ();Rs=1; / / the byte data, rather than commandDelay ();Rw=0; / / the operation for writing,Instead of readingDelay ();E=0; / / low enable signal(delay); / / keep the enable signal is low for a period of timeE=1; / / pull high enable signal needed by the rising edge of the LCD operationDelay ();}//********************LCD display settings function**************************************After changing the level / / on the need to insert a delay time, otherwise the LCD react.Void lcd_enable (){Delay ();Rs=0; / / the byte data for the command, rather than the dataDelay ();Rw=0; / / the operation for writing, instead of readingDelay ();E=0; / / low enable signal(delay); / / keep the enable signal is low for a period of timeE=1; / / pull high enable signal needed by the rising edge of the LCD operationDelay ();}//*********************LCD initialization function**************************************Void lcd_init (){PORTD=0X1; / / displayLcd_enable ();PORTD=0X38; //8 bit 2 row 5*7 dot matrixLcd_enable ();PORTD=0X0e; / / display, cursor, flashingLcd_enable ();PORTD=0X06; / / the text does not move the cursor to the right. Lcd_enable ();PORTD=0X86; / / time display.Lcd_enable ();}//***********************LCD display function************************************Void lcd_display (){Unsigned char I, j;Lcd_init ();For (i=0; i<3; / / i++) a total of 3 bytes of data{Write (lcd[i]); / / look-up table for data and call to write a byte of data to the LCD display functionFor (j=0; j<5; / / j++) for a period of time (mainly in order to control the display speed){delay ();}}}//**************** write a byte ***************************functionUnsigned char SPI_WriteByte (unsigned char VAL){SPI2BUF = Val; / / to be sent to the transmitting register data loadingWhile (IFS1bits.SPI2IF!); / / wait for sentIFS1bits.SPI2IF=0; / / clear to send complete flagReturn SPI2BUF; / / read receive register (even invalid data is empty)}//**************** receive a byte ************************** functionUnsigned char SPI_ReadByte (void){SPI2BUF = 0xff; / / send register loading data, receiving data to startWhile (IFS1bits.SPI2IF!); / / wait for the completion of receivingIFS1bits.SPI2IF=0; / / clear receive complete flagReturn SPI2BUF; / / read the received data}//***************** send command function****************************Unsigned char SD_SendCommand (unsigned char CMD, unsigned long ARG){Unsigned char r1;Unsigned char retry1=0; / / the number of repeat operationCs=0; / / the chip select signalSPI_WriteByte (CMD 0x40 |); / / write command respectively.SPI_WriteByte (arg>>24); / / fourth byte data segmentSPI_WriteByte (arg>>16); / / third byte data segmentSPI_WriteByte (arg>>8); / / second byte data segmentSPI_WriteByte (ARG); / / first byte data segmentSPI_WriteByte (0x95); //CRC checksumWhile ((R1 = SPI_WriteByte (0xff)) = = 0xff) / / wait for a responseIf break (retry1++ > 200); / / exit timeoutCs=1; / / early chip select signalReturn R1; / / return status}//*******************SD initialization function**************************Unsigned char sd_reset (){Unsigned char I, tmp;Unsigned char retry; / / repeatUnsigned char r1=0;Retry=0;Delay ();Delay ();{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (0,0); / / idle commandRetry++;If (retry>20) return 1; / / exit timeout} while (R1! = 0x01); / / wait for the command to return IDLE Retry = 0;Cs=0;Do{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (1, 0); / / Active commandRetry++;If (retry>254) return 1; / / exit timeout} while (R1);For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (59, 0); / / CRCIf (R1 return 1); / / return is not correct, exit initialization For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (16, 512); / / set the sector size 512If (R1 =0 return 1!); / / return is not correct, exit initializationReturn 0; / / return to normal}//******************** write a sector**************************Unsigned char SD_WriteSingleBlock (unsigned long sector) {Unsigned char r1;Unsigned int i;Unsigned char retry=0;{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (24, sector<<9); / / write command Retry++;If (retry>10) return 1; / / exit timeout} while (R1 = = 0x00);Cs=0;SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xFE); / / the start symbolFor (i=0; i<512; / / i++) to send 512 bytes of data{If (i<255) SPI_WriteByte (I); / / send 0--255Else SPI_WriteByte (512-i); / / send 255--0}SPI_WriteByte (0x95);SPI_WriteByte (0x95); //16-bits CRCR1 = SPI_WriteByte (0xff); / / read a responseIf (retry++ >10) return 1;Timeout / exitWhile (! ((r1&0x0f) ==5)); / / wait for data receive information(while! (SPI_WriteByte (0xff))); / / wait for the internal SD card programmingReturn 0;}//****************** SD card reading a sector************************Unsigned char SD_ReadSingleBlock (unsigned long sector){Unsigned char R1, temp;Unsigned int i, j;Unsigned char retry=0;Do{R1 = SD_SendCommand (17, sector<<9); / / read commandRetry++;If (retry>10) return 1; / / exit timeout} while (R1 = = 0x00);Cs=0;While (SPI_WriteByte (0xff)! = 0xFE) / / wait for receiving a start byte{If (retry++ >100) return 1; / / exit timeout}For (i=0; i<512; i++) / / read 512 data{Temp = SPI_WriteByte (0xff); / / read the received data Lcd[0]= (temp/100) +48;Lcd[1]= ((temp%100) /10) +48;Lcd[2]= ((temp%100)%10) +48;(lcd_display); / / read data sent to the displayFor (j=0; j<500; j++) {delay ();}}SPI_WriteByte (0xff); / / pseudo 16-bits CRCSPI_WriteByte (0xff);Cs=1;Return 0;}//*********************** delay procedures*************************Void (delay) / delay procedure{Int i; / / define integer variableFor (i=0x100; i--;); / / delay}The main function of ************************** //************************Int main (void){Unsigned char loop, res;Delay ();Delay ();Delay ();Loop=1;Cs=1;While (loop){(spi_init); / / call system initialization functionRes= (sd_reset); / / call the SD card initialization functionIf (RES break); / / SD card initialization is normal, not normal, not out of the loop executes the read and write operationsSD_WriteSingleBlock (1); / / call and write SD card single BLOCK function, the sector is 1If (RES) break;SD_ReadSingleBlock (1); / / call read SD card single BLOCK function, the sector number is 1If (RES) break;Loop=0;While (1);}While (1);}。

单片机读写SD卡教程

单片机读写SD卡教程

重声明:本实验并不是对所有SD卡都能成功运行第一步:翻开winhe*软件,用读卡器读SD卡,在winhe*中查看SD卡点击查找〔ctrl+F〕Array输入FAT〔找到DBR处〕发现DBR起始于0*11200扇区地址,它必是512所以在程序中读一个扇区时一定要是5120*EB,本程序读一下这个地址的值看看是否正确。

注意有的看看程序吧*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 *data DATA[512];void delay(unsigned int z){unsigned int *,y;for(*=z;*>0;*--);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&0*80);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==0*00)break;if(response==0*01)break;i++;}return response;}//=============================================================== =//发命令到SD卡void Sdmand(unsigned char mand, unsigned long argument, unsigned char CRC) {SdWrite(mand|0*40);/*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=0*FF;P3=0*ff;SD_CS=1;for(i=0;i<=0*fe;i++)SdWrite(0*ff);SD_CS=0;Sdmand(0*00,0,0*95);SD_DI=1;response=SdResponse();if(response!=0*01){return 0;}if(response==0*01){ //不管什么SD卡都能进入这一步,同时也说明硬件没问题SD_CS=1;//Beep=0;//while(1);//用来查看程序能否运行到这一步,去掉//即可SdWrite(0*ff);SD_CS=0;while(1){Sdmand(0*01,0,0*ff);//Sdmand(0*01,0*00000000,0*ff);//进SPIresponse=0*ff;SD_DI=1;for(i=0;i<250;i++)//response!=0*00//等待回复{response=SdResponse(); //Beep=0;/if(response==0) break;}if(response==0) {break;}//回复0则通过SPI,只要通过SPI后面的指令才能继//续// Beep=0;}// Beep=0;//看程序能否跳出来,挑不出来则进不了SPISD_CS=1;SdWrite(0*ff);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;Sdmand(0*18,address,0*ff);if(SdResponse()==00){SdWrite(0*ff);SdWrite(0*ff);SdWrite(0*ff);//mand was a success - now send data//start with DATA TOKEN = 0*FESdWrite(0*fe);//now send datafor(count=0;count<len;count++) SdWrite(*Block++);for(;count<512;count++) SdWrite(0);//data block sent - now send checksumSdWrite(0*ff); //两字节CRC校验, 为0*FFFF 表示不考虑CRCSdWrite(0*ff);//Now read in the DATA RESPONSE tokendataResp=SdRead();while(SdRead()==0);dataResp=dataResp&0*0f; //mask the high byte of the DATA RESPONSE token SD_CS=1;SdWrite(0*ff);if(dataResp==0*0b){return 0;}if(dataResp==0*05)return 1;return 0;}//printf("mand 0*18 (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)// {Sdmand(0*11,address,0*ff);// SD_DO=1;// P0=SdResponse();// P0=0*ff;// while(1);while(response!=0*fe && i<200) {response=SdRead();P0=response;i++;} // if(i>=200) Beep=0;// P0=0*f0;// }// Beep=0;for(count=0;count<512;count++) *Block++=SdRead();SdRead();SdRead();//Now read in the DATA RESPONSE tokenSD_CS=1;SdWrite(0*ff);return 1;}void main(){unsigned int mm;unsigned long AddTemp=0*11200;//70144;//SD卡地址第一个数据物理地址初始值70144是通过winhe*查看,对于你的SD卡肯定要改//可以用winhe*查看,一定要是512整数倍mm=SdInit();//SdReadBlock(DATA,AddTemp,1);delay(10);// Beep=0;if(DATA[0]==0*eb)Beep=0;// 看读的对不对while(1); }。

51单片机读写SD卡程序

51单片机读写SD卡程序
if(reading==0) MMC_PORT|=MMC_CS_PIN; //MMC_CS_PIN=1; else MMC_PORT&=~MMC_CS_PIN; //MMC_CS_PIN=0; return(tmp); } //**************************************************************************** //SD卡初始化(SPI-MODE) //****************************************************************************
/thread/118916/1
回复
回复本帖
回到顶端 [4楼]
2009-6-4 ห้องสมุดไป่ตู้3:32:41
51单片机读写SD卡程序!!!
uchar SD_Init(void) { uchar retry,temp; uchar i; MMC_PORT&=~MMC_CS_PIN; //SD卡使能
RE: 51单片机读写SD卡程序!!!
l0p0c
If winter comes,Can spring be far behind?? 爱“拼”才会赢,1980元仿真器免费等你拿!
发表于 2007-11-13 09:38:52
现在不知道该怎么整? SD卡的资料是英文的,有好多地方整明白啊!
回复
回复本帖
51单片机读写SD卡程序!!! 发表于 2007-11-12 16:02:25
l0p0c
有没有做过51单片机读写SD卡项目的同行? 现在需要帮助一下咯! o(∩_∩)o...
我是GG 高级会员 加为好友 发短消息 最后登陆时间:2009-05-21 15:30:00 状态:离线

SD卡读写开发文档

SD卡读写开发文档

SD卡读写关键是对SD的初始化、块扇区的读写、以及SD卡文件结构的掌握,初始化SD首先发送0x40 0x 00 0x00 0x00 0x00 0x59 应答0x01 进入空闲模式在发送0x41 0x 00 0x00 0x00 0x00 0x59 应答0x00 激活SD卡使用WinHex分析SD卡可以得到第一数据区即根目录区,在第520区,每扇区512字节,等等,分析后得结果用于,读数据的验证。

本SD卡为1G的金士顿卡,扇区宽度为512字节,根据WinHex和读SD卡的结论得出解读,可以得出表一:读本SD卡的第0块物理扇区512字节,即常说的引导扇区。

MBR(主引导的区)的长度为446字节(0x00~0x1BD),以后每16个字节代表一个分区,由上述分析得出本SD卡的逻辑地址的0扇区应该在隐藏扇区中,块的扇区地址为0x00000020,读扇区得到的内容:如下图所示:具体分析如下图所示:主引导区数(1个)+ 保留扇区数(0x04个)+ 隐藏数(0x20个)+2个FAT表宽度(0Xf2*2)=521,即从第521个扇区(扇区地址为520)开始的32个扇区中存放根目录。

读本SD卡的根目录的第一个扇区得出如图数据:本卡卷标名为UJNX,可见第一个32字节的文件为该根目录,但是他以文件夹的形式呈现,并且大小Size为0,在大多数正常情况下我们可以认为无后缀名的,大小为零的文件为文件夹(我知道这个并不科学,谁有好的建议?)。

可以看出32个扇区的根目录最多可以存储512个目录文件。

文件就简单了,直接根据FAT表簇的地址读数据就是了。

读FAT表:在FAT表中每两个字节的数据对应唯一的一个簇地址,每个簇有64个扇区,例如在第一个(地址为0x24)FAT表的第一个扇区中的数据如下:读文件1、根据32字节的目录获取文件名、类型、大小、起始簇的地址2、根据簇的地址高位和低位计算出簇的位置,并与对应的计算出该簇的起始扇区地址簇的起始扇区地址=根目录起始扇区+目录扇区宽度+(簇地址-2)*每个簇的扇区宽度。

SD卡读写操作详细说明

SD卡读写操作详细说明

51单片机实现对SD卡的读写SD卡SPI模式下与单片机的连接图:22.23.//获得16位的回应24. Read_Byte_SD(); //read the first byte,ignore it.25.do26. { //读取后8位27. tmp = Read_Byte_SD();28. retry++;29. }30.while((tmp==0xff)&&(retry<100));31.return(tmp);32.}2)初始化SD卡的初始化是非常重要的,只有进行了正确的初始化,才能进行后面的各项操作。

在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。

在初始化成功后,应尽量提高SPI的速率。

在刚开始要先发送至少74个时钟信号,这是必须的。

在很多读者的实验中,很多是因为疏忽了这一点,而使初始化不成功。

随后就是写入两个命令CMD0与CMD1,使SD卡进入SPI模式初始化时序图:初始化例程:1.//--------------------------------------------------------------------------2.初始化SD卡到SPI模式3.//--------------------------------------------------------------------------4.unsigned char SD_Init()5.{6.unsigned char retry,temp;7.unsigned char i;8.unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};9. SD_Port_Init(); //初始化驱动端口10.11. Init_Flag=1; //将初始化标志置112.13.for (i=0;i<0x0f;i++)14. {15. Write_Byte_SD(0xff); //发送至少74个时钟信号16. }17.18.//向SD卡发送CMD019. retry=0;20.do21. { //为了能够成功写入CMD0,在这里写200次22. temp=Write_Command_SD(CMD);23. retry++;24.if(retry==200)25. { //超过200次26.return(INIT_CMD0_ERROR);//CMD0 Error!27. }28. }29.while(temp!=1); //回应01h,停止写入30.31.//发送CMD1到SD卡32. CMD[0] = 0x41; //CMD133. CMD[5] = 0xFF;34. retry=0;35.do36. { //为了能成功写入CMD1,写100次37. temp=Write_Command_SD(CMD);38. retry++;39.if(retry==100)40. { //超过100次41.return(INIT_CMD1_ERROR);//CMD1 Error!4.unsigned char Read_CSD_SD(unsigned char *Buffer)5.{6.//读取CSD寄存器的命令7.unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};8.unsigned char temp;9. temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes10.return(temp);11.}4)读取SD卡信息综合上面对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。

android手机SD卡读写操作(以txt文本为例)实现步骤

android手机SD卡读写操作(以txt文本为例)实现步骤

android⼿机SD卡读写操作(以txt⽂本为例)实现步骤要说明⼀下,我这⾥没有⽤MainActivity.class作为软件⼊⼝复制代码代码如下:AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="/apk/res/android"package="com.tes.textsd"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="16" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.tes.textsd.FileOperateActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="UNCHER" /></intent-filter></activity></application></manifest>复制代码代码如下:FileHelper.java/*** @Title: FileHelper.java* @Package com.tes.textsd* @Description: TODO(⽤⼀句话描述该⽂件做什么)* @author Alex.Z* @date 2013-2-26 下午5:45:40* @version V1.0*/package com.tes.textsd;import java.io.DataOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import android.content.Context;import android.os.Environment;public class FileHelper {private Context context;/** SD卡是否存在**/private boolean hasSD = false;/** SD卡的路径**/private String SDPATH;/** 当前程序包的路径**/private String FILESPATH;public FileHelper(Context context) {this.context = context;hasSD = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED);SDPATH = Environment.getExternalStorageDirectory().getPath(); FILESPATH = this.context.getFilesDir().getPath();}/*** 在SD卡上创建⽂件** @throws IOException*/public File createSDFile(String fileName) throws IOException { File file = new File(SDPATH + "//" + fileName);if (!file.exists()) {file.createNewFile();}return file;}/*** 删除SD卡上的⽂件** @param fileName*/public boolean deleteSDFile(String fileName) {File file = new File(SDPATH + "//" + fileName);if (file == null || !file.exists() || file.isDirectory())return false;return file.delete();}/*** 写⼊内容到SD卡中的txt⽂本中* str为内容*/public void writeSDFile(String str,String fileName){try {FileWriter fw = new FileWriter(SDPATH + "//" + fileName);File f = new File(SDPATH + "//" + fileName);fw.write(str);FileOutputStream os = new FileOutputStream(f); DataOutputStream out = new DataOutputStream(os);out.writeShort(2);out.writeUTF("");System.out.println(out);fw.flush();fw.close();System.out.println(fw);} catch (Exception e) {}}/*** 读取SD卡中⽂本⽂件** @param fileName* @return*/public String readSDFile(String fileName) {StringBuffer sb = new StringBuffer();File file = new File(SDPATH + "//" + fileName);try {FileInputStream fis = new FileInputStream(file);int c;while ((c = fis.read()) != -1) {sb.append((char) c);}fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return sb.toString();}public String getFILESPATH() {return FILESPATH;}public String getSDPATH() {return SDPATH;}public boolean hasSD() {return hasSD;}}复制代码代码如下:main.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android" android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/hasSDTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/SDPathTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/FILESpathTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="hello" /><TextViewandroid:id="@+id/createFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /><TextViewandroid:id="@+id/readFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /><TextViewandroid:id="@+id/deleteFileTextView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="false" /></LinearLayout>复制代码代码如下:FileOperateActivity.class/*** @Title: FileOperateActivity.java* @Package com.tes.textsd* @Description: TODO(⽤⼀句话描述该⽂件做什么)* @author Alex.Z* @date 2013-2-26 下午5:47:28* @version V1.0*/package com.tes.textsd;import java.io.IOException;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class FileOperateActivity extends Activity {private TextView hasSDTextView;private TextView SDPathTextView;private TextView FILESpathTextView;private TextView createFileTextView;private TextView readFileTextView;private TextView deleteFileTextView;private FileHelper helper;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);hasSDTextView = (TextView) findViewById(R.id.hasSDTextView); SDPathTextView = (TextView) findViewById(R.id.SDPathTextView); FILESpathTextView = (TextView) findViewById(R.id.FILESpathTextView); createFileTextView = (TextView) findViewById(R.id.createFileTextView); readFileTextView = (TextView) findViewById(R.id.readFileTextView); deleteFileTextView = (TextView) findViewById(R.id.deleteFileTextView); helper = new FileHelper(getApplicationContext()); hasSDTextView.setText("SD卡是否存在:" + helper.hasSD()); SDPathTextView.setText("SD卡路径:" + helper.getSDPATH()); FILESpathTextView.setText("包路径:" + helper.getFILESPATH());try {createFileTextView.setText("创建⽂件:"+ helper.createSDFile("test.txt").getAbsolutePath());} catch (IOException e) {e.printStackTrace();}deleteFileTextView.setText("删除⽂件是否成功:"+ helper.deleteSDFile("xx.txt"));helper.writeSDFile("1213212", "test.txt");readFileTextView.setText("读取⽂件:" + helper.readSDFile("test.txt"));}}看看运⾏的效果:。

SD卡读写C51

SD卡读写C51
uchar SD_Reser(void);
uchar SD_Init(void);
uchar SD_Write_Sector(unsigned long addr,uchar *buffer);
uchar SD_Read_Sector(unsigned long addr,uchar *buffer);
void Delays(uint t)
{
while(t--)
{}
}
/*长延时*/
void Delay_ms(uchar N)
{
while(N--)
{
Delays(60000);
}
}
/*LCD12232写函数*/
void Send_DATA(uchar Data,uchar A)
{
uchar i,Dat;
if(is_init) delay(DELAY_TIME);
SD_SI=_dat3;
SD_SCL=0;
if(is_init) delay(DELAY_TIME);
SD_SCL=1;
if(is_init) delay(DELAY_TIME);
SD_SI=_dat2;
SD_SCL=0;
if(is_init) delay(DELAY_TIME);
_dat7=SD_SO;
SD_SCL=1;
if(is_init) delay(DELAY_TIME);
SD_SCL=0;
if(is_init) delay(DELAY_TIME);
_dat6=SD_SO;
SD_SCL=1;
if(is_init) delay(DELAY_TIME);
SD_SCL=0;
SD_SCL=0;

sd卡数据读写流程

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卡的读程序

#include<reg52.h>//要操作的SD卡的扇区地址#define INIT_CMD0_ERROR 0x01 //CMD0错误#define INIT_CMD1_ERROR 0x02 //CMD1错误#define WRITE_BLOCK_ERROR 0x03 //写块错误#define READ_BLOCK_ERROR 0x04 //读块错误#define DELAY_TIME 80 //SD卡的复位与初始化时SPI的延时参数,根据实际速率修改其值,否则会造成SD卡复位或初始化失败#define TRY_TIME 800 //向SD卡写入命令之后,读取SD卡的回应次数,即读TRY_TIME 次,如果在TRY_TIME次中读不到回应,产生超时错误,命令写入失败sbit SD_SCL=P1^3; //SD卡同步时钟输入sbit SD_SI =P1^1; //SD卡同步数据输入sbit SD_CS =P1^2; //SD卡片选输入sbit SD_SO =P1^0; //SD卡同步数据输出unsigned long laddr;unsigned char SD_Reset();unsigned char SD_Init();unsigned char SD_Read_Sector(unsigned long addr);unsigned char xdata pbuf[512]; //数据缓冲区unsigned char pbu[10];unsigned char is_init; //在初始化的时候设置此变量为1,unsigned char bdata _dat;sbit _dat7=_dat^7;sbit _dat6=_dat^6;sbit _dat5=_dat^5;sbit _dat4=_dat^4;sbit _dat3=_dat^3;sbit _dat2=_dat^2;sbit _dat1=_dat^1;sbit _dat0=_dat^0;void delay(unsigned int time){while(time--);}/******************************************************************- 功能描述:IO模拟SPI,发送一个字节- 隶属模块:SD卡模块- 函数属性:内部- 参数说明:x是要发送的字节- 返回说明:无返回- 注:其中is_init为1时,写的速度放慢,初始化SD卡SPI速度不能太高******************************************************************/void SD_spi_write(unsigned char x){_dat=x;SD_SI=_dat7;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat6;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat5;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat4;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat3;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat2;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat1;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SI=_dat0;SD_SCL=0;if(is_init) delay(DELAY_TIME);SD_SCL=1;if(is_init) delay(DELAY_TIME);}/****************************************************************** - 功能描述:IO模拟SPI,读取一个字节- 隶属模块:SD卡模块- 函数属性:内部- 参数说明:无- 返回说明:返回读到的字节******************************************************************/unsigned char SD_spi_read() //SPI读一个字节{SD_SO=1;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat7=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat6=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat5=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat4=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat3=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat2=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat1=SD_SO;SD_SCL=1;if(is_init) delay(DELAY_TIME);SD_SCL=0;if(is_init) delay(DELAY_TIME);_dat0=SD_SO;return (_dat);}/******************************************************************- 功能描述:向SD卡写命令- 隶属模块:SD卡模块- 函数属性:内部- 参数说明:SD卡的命令是6个字节,pcmd是指向命令字节序列的指针- 返回说明:命令写入后,SD卡的回应值,调用不成功,将返回0xff******************************************************************/unsigned char SD_Write_Cmd(unsigned char *pcmd) //向SD卡写命令,pcmd是命令字节序列的首地址{unsigned char temp,tim;tim=0;SD_CS=1;SD_spi_write(0xff); //提高兼容性,如果没有这里,有些SD卡可能不支持SD_CS=0;SD_spi_write(pcmd[0]);SD_spi_write(pcmd[1]);SD_spi_write(pcmd[2]);SD_spi_write(pcmd[3]);SD_spi_write(pcmd[4]);SD_spi_write(pcmd[5]);do{temp = SD_spi_read();//一直读,直到读到的不是0xff或超时tim++;}while((temp==0xff)&&(tim<TRY_TIME));return(temp);}/******************************************************************- 功能描述:复位SD卡,用到CMD0,使用SD卡切换到SPI模式- 隶属模块:SD卡模块- 函数属性:外部,供用户调用- 参数说明:无- 返回说明:调用成功,返回0x00,否则返回INIT_CMD0_ERROR (sd.h中有定义)******************************************************************//******************************************************************- 功能描述:初始化SD卡,使用CMD1- 隶属模块:SD卡模块- 函数属性:外部,供用户调用- 参数说明:无- 返回说明:调用成功,返回0x00,否则返回INIT_CMD1_ERROR (sd.h中有定义)******************************************************************/unsigned char SD_Init() //初始化,使用CMD1(命令1){unsigned char temp;unsigned char pcmd[] = {0x41,0x00,0x00,0x00,0x00,0xff}; //命令1的字节序列SD_CS=0; //打开片选temp=SD_Write_Cmd(pcmd);is_init=0; //初始化完毕,将is_init设置为0,为了提高以后的数据传输速度SD_CS=1; //关闭片选SD_spi_write(0xff); //按照SD卡的操作时序在这里补8个时钟return(temp); //返回0,说明初始化操作成功}/**************************************************************************** - 功能描述:读取addr扇区的512个字节到buffer指向的数据缓冲区- 隶属模块:SD卡模块- 函数属性:外部,供用户调用- 参数说明:addr:扇区地址buffer:指向数据缓冲区的指针- 返回说明:调用成功,返回0x00,否则返回READ_BLOCK_ERROR (sd.h中有定义)- 注:SD卡初始化成功后,读写扇区时,尽量将SPI速度提上来,提高效率****************************************************************************/unsigned char SD_Read_Sector(unsigned long addr)//从SD卡的指定扇区中读出512个字节,使用CMD17(17号命令){unsigned char temp;unsigned char pcmd[]={0x51,0x00,0x00,0x00,0x00,0xff}; //CMD17的字节序列addr<<=9; //addr=addr*512 将块地址(扇区地址)转为字节地址pcmd[1]=((addr&0xff000000)>>24);//将字节地址写入到CMD17字节序列中pcmd[2]=((addr&0x00FF0000)>>16);pcmd[3]=((addr&0x0000FF00)>>8);SD_CS=0;//打开片选//time=0;temp=SD_Write_Cmd(pcmd); //写入CMD17return (temp);}unsigned char SD_Reset()//SD卡复位,进入SPI模式,使用CMD0(命令0){unsigned char temp,i;unsigned char pcmd[] = {0x40,0x00,0x00,0x00,0x00,0x95}; //命令0的字节序列is_init=1; //将is_init置为1SD_CS=1; //关闭片选for(i=0;i<0x0f;i++) //复位时,首先要发送最少74个时钟信号,这是必须的!!!{SD_spi_write(0xff);//120个时钟}SD_CS=0; //打开片选temp=SD_Write_Cmd(pcmd);//写入CMD0SD_CS=1; //关闭片选//按照SD卡的操作时序在这里补8个时钟return (temp);//返回0,说明复位操作成功}void main(){unsigned char t,s;unsigned int j;laddr=1892;//P2=0x00;t=0x00;while(t!=0x01){t=SD_Reset();}SD_spi_write(0xff);//P2=0x0f;while(t!=0x00){t=SD_Init();}//SD_Write_Sector(ADDR,pbuf);//将数据缓冲区中的512个字节的数据写入SD卡的第ADDR扇区中t=0xff;while(t!=0x00){t=SD_Read_Sector(laddr);}//从SD卡的第ADDR扇区中读取512个字节的数据到数据缓冲区//P2=0xca;while (t!=0xfe){t=SD_spi_read(); //一直读,当读到0xfe时,说明后面的是512字节的数据了/*P2=t;for(s=0;s<200;s++){delay(1000);}P2=0xff;*/}//P2=0x0f;for(j=0;j<512;j++) //将数据写入到数据缓冲区中{pbuf[j]=SD_spi_read();}for(j=0;j<10;j++) //将数据写入到数据缓冲区中{pbu[j]=pbuf[j];}SD_spi_read();SD_spi_read();//读取两个字节的CRC校验码,不用关心它们SD_CS=1; //SD卡关闭片选SD_spi_write(0xff);//按照SD卡的操作时序在这里补8个时钟for(j=0;j<10;j++) //将数据写入到数据缓冲区中{P2=pbu[j];for(s=0;s<200;s++){delay(1000);}}//P2=0x0c;while(1);}。

SD卡读写操作详细说明

SD卡读写操作详细说明

SD卡读写操作详细说明51单⽚机实现对SD卡的读写SD卡SPI模式下与单⽚机的连接图:22.23.//获得16位的回应24. Read_Byte_SD(); //read the first byte,ignore it.25.do26. { //读取后8位27. tmp = Read_Byte_SD();28. retry++;29. }30.while((tmp==0xff)&&(retry<100));31.return(tmp);32.}2)初始化SD卡的初始化是⾮常重要的,只有进⾏了正确的初始化,才能进⾏后⾯的各项操作。

在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。

在初始化成功后,应尽量提⾼SPI的速率。

在刚开始要先发送⾄少74个时钟信号,这是必须的。

在很多读者的实验中,很多是因为疏忽了这⼀点,⽽使初始化不成功。

随后就是写⼊两个命令CMD0与CMD1,使SD卡进⼊SPI 模式初始化时序图:初始化例程:1.//--------------------------------------------------------------------------2.初始化SD卡到SPI模式3.//--------------------------------------------------------------------------4.unsigned char SD_Init()5.{6.unsigned char retry,temp;7.unsigned char i;8.unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};9. SD_Port_Init(); //初始化驱动端⼝10.11. Init_Flag=1; //将初始化标志置112.13.for (i=0;i<0x0f;i++)14. {15. Write_Byte_SD(0xff); //发送⾄少74个时钟信号16. }17.18.//向SD卡发送CMD019. retry=0;20.do21. { //为了能够成功写⼊CMD0,在这⾥写200次22. temp=Write_Command_SD(CMD);23. retry++;24.if(retry==200)25. { //超过200次26.return(INIT_CMD0_ERROR);//CMD0 Error!27. }28. }29.while(temp!=1); //回应01h,停⽌写⼊30.31.//发送CMD1到SD卡32. CMD[0] = 0x41; //CMD133. CMD[5] = 0xFF;34. retry=0;35.do36. { //为了能成功写⼊CMD1,写100次37. temp=Write_Command_SD(CMD);38. retry++;39.if(retry==100)40. { //超过100次41.return(INIT_CMD1_ERROR);//CMD1 Error!4.unsigned char Read_CSD_SD(unsigned char *Buffer)5.{6.//读取CSD寄存器的命令7.unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};8.unsigned char temp;9. temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes10.return(temp);11.}4)读取SD卡信息综合上⾯对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。

SD卡初始化及读取程序

SD卡初始化及读取程序

uint8 SPI_SendByte(uint8 val) {
SPI0DAT = val; while(TXBSY); return SPI0DAT; }
// uint8= uchar
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ // 函数名:MMC_SD_SendCmd // 功 能:发送卡命令
if(r1 == 0x00) type = 0x10; // 激活成功就是 SD 卡
}
else { }
// 如果发送 Cmd55 无反应,改发送 Cmd1 r1 = MMC_SD_SendCmd(1,0); if(r1 == 0x00) type = 0x20; // 激活成功就是 MMC 卡
retry++;
} while(r1 != 0x01);
// MMC、SD 卡成功转到 SPI 模式
retry = 0;
//****** SD 卡在进入 SPI 模式后,激活命令和 MMC 卡一样为 Cmd1,同时 Cmd55+Cmd41 仍 然有效******//
/* do
{
r1 = MMC_SD_SendCmd(1, 0); //发 Cmd1(active 激活)命令
//分别写入命令 //仅本次有效的 CRC 值
while((r1 = SPI_SendByte(0xFF)) == 0xFF) //等待响应 if(retry++ > 8) break; //超时退出
return r1; }
//返回状态值
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ // 函数名:MMC_SD_ReadSingleBlock // 功 能:读一个扇区 // 参 数:扇区,数据缓冲区 // 返回值: //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

sd 卡读写程序( SD card read and write program )SD card read and write programObjective: To study the SD card / / operationDesign / software1, using SPI communication / / SD card2, go to SD / / in order to 0-255 a total of 256 data, and then read back LCD1602 display/ / hardware requirements:S11 ON / / dial switchJumper J18 / / all connected#include <p30f6014.h> //dsPIC30F6014 standard header file_FOSC( CSW_FSCM_O&F FX T_PLL4); //4 doubler crystal oscillator, Failsafe clock closed_FWDT (WDT_OFF); / / close the watchdog timer_FBORPO(RP BOR_OFF& MCLR_EN);/ / reset prohibited MCLRr eset enable._FGS (CODE_PROT_OFF); / / code protection against #define CS PORTGbits.RG9 / / SD card selection pin definition #define RSL TB4 / / definition LCDc ontrol bits (note here can only register with LATB, you cannot directly use thePORTB register)#define RW TB5#define e TB6Unsigned char __attribute__ ((address (0x900)))lcd[3]={0,0,0};Void (spi_init); / / declaration system initial functionVoid (spi_low); / / that produces low baud rate (using the SD card initialization function)Void (spi_high); / / that produce high baud rate function (SDcard initialization after use)Unsigned char (sd_reset); / / that the SD cardinitialization functionUnsigned char SD_SendComman(udn signed char CMDu nsigned, longARG); / / write SD card command function statementUnsigned char SPI_WriteByte (unsigned char VAL); / / write a byte function statementUnsigned char SPI_ReadByte (void); / / that receive a byte functionUnsigned char SD_WriteSingleBlock (unsigned long sector); / / that single BLOCK data write SD card functionUnsigned char SD_ReadSingleBlock (unsigned long sector); / / read SD card data function single BLOCK statementVoid (lcd_display); / / state results display functionVoid (delay); / / state delay function (shown by)/ / system initialization functionVoid spi_init (){TRISG=0x00d0; / / set the SDI output, C output port for the otherTRISB=0X0000; / / set for the output port BTRISD=0X0000; / / set for the output port DSPI2CON=0x0278; / / idle bus is high, fosc/64SPI2STAT=0x8000; / / the end of sampling the output data of input data, the rising edge of data transmissionWrite a LCD program/ / write a byte of data functionAfter changing the level / / on the need to insert a delay time, otherwise the LCD react.Void write (unsigned char x){PORTD=x; / / PORTD port to send data to be displayedDelay ();Rs=1; / / the byte data, rather than commandDelay ();Rw=0; / / the operation for writing,Instead of readingDelay ();E=0; / / low enable signal(delay); / / keep the enable signal is low for a period of timeDelay ();E=1; / / pull high enable signal needed by the rising edge of the LCD operation}//********************LCD display settings functionAfter changing the level / / on the need to insert a delay time, otherwise the LCD react.Void lcd_enable (){Delay ();Rs=0; / / the byte data for the command, rather than the dataDelay ();Rw=0; / / the operation for writing, instead of readingDelay ();E=0; / / low enable signal(delay); / / keep the enable signal is low for a period of timeE=1; / / pull high enable signal needed by the rising edge of the LCD operationDelay ();}//*********************LCD initialization functionVoid lcd_init (){PORTD=0X1; / / displayLcd_enable ();PORTD=0X38; //8 bit 2 row 5*7 dot matrixLcd_enable ();PORTD=0X0e; / / display, cursor, flashingLcd_enable ();PORTD=0X06/; / the text does not move the cursor to the right.Lcd_enable ();PORTD=0X86; / / time display.Lcd_enable ();//***********************LCD display functionVoid lcd_display (){Unsigned char I, j;Lcd_init ();For (i=0; i<3; / / i++) a total of 3 bytes of data{Write (lcd[i]); / / look-up table for data and call to write a byte of data to the LCD display functionFor (j=0; j<5; / / j++) for a period of time (mainly in order to control the display speed){delay ();}}}write a bytefunctionUnsigned char SPI_WriteByte (unsigned char VAL){SPI2BUF= Val; / / to be sent to the transmittingregister loadingWhile (IFS1bits.SPI2IF!); / / wait for sentIFS1bits.SPI2IF=0; / / clear to send complete flagReturn SPI2BUF; / / read receive register (even invalid data is empty)}functionUnsigned char SPI_ReadByte (void){SPI2BUF= 0xff; / / send register loading data,receiving to start While (IFS1bits.SPI2IF!); / / wait for the completion of receiving data receive a bytedataIFS1bits.SPI2IF=0; / / clear receive complete flagReturn SPI2BUF; / / read the received data}send command functionUnsigned char SD_SendComman(udn signed char CMD,u nsigned long ARG){Unsigned char r1;Unsigned char retry1=0; / / the number of repeat operationCs=0; / / the chip select signalSPI_WriteByte (CMD 0x40 |); / / write command respectively.SPI_WriteByte (arg>>24); / / fourth byte data segmentSPI_WriteByte (arg>>16); / / third byte data segmentSPI_WriteByte (arg>>8); / / second byte data segmentSPI_WriteByte (ARG); / / first byte data segmentSPI_WriteByte (0x95); //CRC checksumWhile ((R1 = SPI_WriteByte (0xff)) = = 0xff) / / wait for a responseIf break (retry1++ > 200); / / exit timeoutCs=1; / / early chip select signalReturn R1; / / return status}//*******************SD initialization function Unsigned char sd_reset (){Unsigned char I, tmp;Unsigned char retry; / / repeatUnsigned char r1=0;Retry=0;Delay ();Delay ();Do{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (0,0); / / idle commandRetry++;If (retry>20) return 1; / / exit timeout} while (R1! = 0x01); / / wait for the command to return IDLERetry = 0;Cs=0;Do{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (1, 0); / / Active commandRetry++;If (retry>254) return 1; / / exit timeout } while (R1);For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (59, 0); / / CRCIf (R1 return 1); / / return is not correct, exit initializationFor (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (16, 512); / / set the sector size 512If (R1 =0 return 1!); / / return is not correct, exit initializationReturn 0; / / return to normal}write a sectorUnsigned char SD_WriteSingleBlock (unsigned long sector) { Unsigned char r1;Unsigned int i;Unsigned char retry=0;Do{For (i=0; i<100; i++) SPI_WriteByte (0xff);R1 = SD_SendCommand (24, sector<<9); / / write command Retry++;If (retry>10) return 1; / / exit timeout} while (R1 = = 0x00);Cs=0;SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xff);SPI_WriteByte (0xFE); / / the start symbolFor (i=0; i<512; / / i++) to send 512 bytes of data If (i<255) SPI_WriteByte (I); / / send 0--255Else SPI_WriteByte (512-i); / / send 255--0}SPI_WriteByte (0x95);SPI_WriteByte (0x95); //16-bits CRCR1 = SPI_WriteByte (0xff); / / read a responseIf (retry++ >10) return 1;Timeout / exitWhile (! ((r1&0x0f) ==5)); / / wait for datainformation receive(while! (SPI_WriteByte (0xff))); / / wait for the internal SD card programmingReturn 0;}//****************** SD card reading a sectorUnsigned char SD_ReadSingleBlock (unsigned long sector){Unsigned char R1, temp;Unsigned int i, j;Unsigned char retry=0;Do{R1 = SD_SendCommand (17, sector<<9); / / read commandRetry++;If (retry>10) return 1; / / exit timeout} while (R1 = = 0x00);Cs=0;While (SPI_WriteByte (0xff)! = 0xFE) / / wait for receiving a start byte{If (retry++ >100) return 1; / / exit timeoutFor (i=0; i<512; i++) / / read 512 data{Temp = SPI_WriteByte (0xff); / / read the received data Lcd[0]= (temp/100) +48;Lcd[1]= ((temp%100) /10) +48;Lcd[2]= ((temp%100)%10) +48;(lcd_display); / / read data sent to the displayFor (j=0; j<500; j++) {delay ();}}SPI_WriteByte (0xff); / / pseudo 16-bits CRCSPI_WriteByte (0xff);Cs=1;Return 0;}delay proceduresVoid (delay) / delay procedure{Int i; / / define integer variable For (i=0x100; i--;); / / delay}The main function ofInt main (void){Unsigned char loop, res;Delay ();Delay ();Delay ();Loop=1;Cs=1;While (loop){(spi_init); / / call system initialization functionRes= (sd_reset); / / call the SD card initialization functionIf (RES break); / / SDc ard initialization is normal, not normal,not out of the loop executes the read and write operationsSD_WriteSingleBlock (1); / / call and write SDc ard single BLOCK function, the sector is 1If (RES) break;SD_ReadSingleBlock (1); / / call read SD card single BLOCK function, the sector number is 1If (RES) break;Loop=0;While (1);}While (1);}。

相关文档
最新文档