sd卡读写程序(SDcardreadandwriteprogram)
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卡(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卡初始化及读写流程默认分类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卡的传输协议和读写程序
Ⳃ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 SDSD ϟˈЏ Փ⫼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 SPISPI ϟˈЏ Փ⫼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卡操作一、概述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卡(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 卡是基于 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 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卡都能成功运行第一步:翻开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卡程序
/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首先发送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卡读写操作详细说明
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⽂本为例)实现步骤要说明⼀下,我这⾥没有⽤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
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卡与主控制器进行通信的桥梁,一般采用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卡的读程序
#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卡读写操作详细说明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卡初始化及读取程序
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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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);}。