Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30745
  • 博文数量: 12
  • 博客积分: 291
  • 博客等级: 二等列兵
  • 技术积分: 140
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-19 09:48
文章分类

全部博文(12)

文章存档

2011年(12)

我的朋友
最近访客

分类: LINUX

2011-08-19 19:56:43

SD卡初始化 及 读取程序
2009-11-03 23:01

首先是SD卡的初始化问题。SD卡的初始化很简单,各个论坛上写的也很详细,个人认为基本不存在太大问题。首先是74个clk,然后CS_LOW;发送CMD0,收到的应答是0x01;接着发送CMD1,收到的应答应该是0x00;最后CS_HIGH。至此,初始化完成。需要注意的问题:初始化的时钟不宜太快,可以在SD卡初始化完成后可提高数据读写速度;在发送命令之前和收到应答位之后,主控制器应该发送8个时钟完成相应操作;CMD0的CRC是0x95,其余命令的CRC无所谓。
读取单块数据流程:CS_LOW-->8个clk-->发送CMD17-->接收响应R1-->接收读数据起始令牌0xFE-->接收数据-->接收CRC-->8个clk-->CS_HIGH;
写入单块数据流程:CS_LOW-->8个clk-->发送CMD24-->接收响应R1-->写入读数据起始令牌0xFE-->写入数据-->接收CRC-->8个clk-->CS_HIGH;

    读写操作指令:单块写命令CMD24,多块写命令CMD25;单块读命令 CMD17,多块读命令CMD18。单块读写时,数据块的长度为512字节,多块读写时SD卡收到1个停止命令CMD12后停止读写。

本程序参考自bozaiSD卡驱动程序, 增加了SDMMC卡判断的功能,SDMMC初始化成功后能返回卡的类型参数供主程序使用。

//--------SD_MMC.H------------------------

#ifndef __SD_MMC_H__
#define __SD_MMC_H__

//
数据宏定义

#define uint8   unsigned char
#define   int8     signed char
#define uint16 unsigned int
#define   int16    signed int
#define uint32 unsigned long
#define   int32    signed long

// C8051F015
SD_MMC 的接口定义

sbit SDCS         = P3^0;
sbit SDDET         = P3^1;
sbit SDWP         = P3^2;


void SPI_SendWreit(uchar temp);         // VS1003B DATA
发送

uint8 SPI_SendByte(uint8 val);         // SPI
传送一个字节

uint8 MMC_SD_SendCmd(uint8 Cmd, uint32 arg);         //
发送卡命令

uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8 *buffer);         //
读一个扇区

uint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8 *buffer);         //
写一个扇区

uint8 MMC_SD_init();         //mmc_sd
卡初始化


#endif
//---------SD_MMC.C-----------------

//---------------------------------------------------------
//         SD_MMC  
底层驱动函数库

//        
编译环境:
Keil C V2.40
//        
编写日期:2008-04-07

//        
最后更新:2008-05-04

//---------------------------------------------------------
#include "main.h"
#include "sd_mmc.h"

//---------------------------------------------------
//        
函数名:
SPI_SendByte
//        
  能:SPI 数据发送

//        
  数:
uchar
//        
返回值:

//---------------------------------------------------

void SPI_SendWreit(uchar temp)
{
         SPI0DAT=temp;
         while(TXBSY);         //
查询发送标志位

}

//---------------------------------------------------
//        
函数名:
SPI_SendByte
//        
  能:SPI传送一个字节

//        
  数:
uchar
//        
返回值:
uchar
//---------------------------------------------------

uint8 SPI_SendByte(uint8 val)         // uint8= uchar
{
         SPI0DAT = val;
         while(TXBSY);
         return SPI0DAT;
}

//---------------------------------------------------
//        
函数名:
MMC_SD_SendCmd
//        
  能:发送卡命令

//        
  数:
uint8,uint32
//        
返回值:
uint8
//---------------------------------------------------

uint8 MMC_SD_SendCmd(uint8 Cmd, uint32 arg)
{
         uint8 r1;
         uint8 retry=0;
        
         SPI_SendWreit(0xFF);         //
发命令前先发送8个时钟

        
         SPI_SendWreit(Cmd | 0x40);         //
分别写入命令

         SPI_SendWreit(arg>>24);
         SPI_SendWreit(arg>>16);
         SPI_SendWreit(arg>>8);
         SPI_SendWreit(arg);
         SPI_SendWreit(0x95);                 //
仅本次有效的 CRC
        
        
         while((r1 = SPI_SendByte(0xFF)) == 0xFF)         //
等待响应

                 if(retry++ > 8) break;         //
超时退出


         return r1;         //
返回状态值

}

//---------------------------------------------------
//        
函数名:
MMC_SD_ReadSingleBlock
//        
  能:读一个扇区

//        
  数:扇区,数据缓冲区

//        
返回值:

//---------------------------------------------------

uint8 MMC_SD_ReadSingleBlock(uint32 sector,uint8 *buffer)
{
         uint8 r1;
         uint16 i;

         SDCS=0;                 //
使能
Card

         r1 = MMC_SD_SendCmd(17, sector<<9);         //
发读扇区命令

        
         if(r1 != 0x00) return r1;

         while(SPI_SendByte(0xFF) != 0xFE);         //--
等待数据的起始令牌号
--

         for(i=0; i<512; i++)         //
512个数据

         {
                 *buffer++ = SPI_SendByte(0xFF);
         }

         SPI_SendWreit(0xFF);         //
发送伪
CRC
         SPI_SendWreit(0xFF);
         SDCS=1;                         //
关闭
Card
         return 0;
}

//---------------------------------------------------
//        
函数名:
MMC_SD_WriteSingleBlock
//        
  能:写一个扇区

//        
  数:扇区,数据缓冲区

//        
返回值:

//---------------------------------------------------

uint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8 *buffer)
{
         uint8 r1;
         uint16 i;

         SDCS=0;                 //
使能
Card

         r1 = MMC_SD_SendCmd(24, sector<<9);         //
写命令

         if(r1 != 0x00)
                 return r1;

         SPI_SendWreit(0xFF);
         SPI_SendWreit(0xFF);
         SPI_SendWreit(0xFF);

         SPI_SendWreit(0xFE);         //
发送数据起始令牌号

        
         for(i=0; i<512; i++)         //
以扇区为单位写入数据

         {
                 SPI_SendWreit(*buffer++);
         }
        
         SPI_SendWreit(0xFF);         //
发送伪
CRC
         SPI_SendWreit(0xFF);
        
         r1 = SPI_SendByte(0xFF);         //
读数据应答令牌号

        
         if( (r1&0x1F) != 0x05)         //
等待是否成功

         {
                 SDCS=1;
                 return r1;
         }

         while(!SPI_SendByte(0xFF));          //--
等待操作完成
--

         SDCS=1;                         //
关闭
Card

         return 0;
}

//---------------------------------------------------
//        
函数名:
MMC_SD_Init
//        
  能:sd卡初始化

//        
  数:无

//        
返回值:uint8 type         // 卡类型返回值
: 0x10 SD, 0x20 MMC
//---------------------------------------------------

uint8 MMC_SD_init()
{
         uint8 i;
         uint8 retry;
         uint8 r1=0;
         uint8 type=0;         //
卡类型返回值:
0xA0 SD 0xB0 MMC
         SDCS = 0;                 //
使能
Card

         SPI_speed=0x13;         //
低速
SPI=300k    Fsystem=12Mhz
         retry = 0;

         do
         {
                 for(i=0;i<10;i++) SPI_SendByte(0xFF);    //
发送80个时钟,使卡同步

                 r1 = MMC_SD_SendCmd(0, 0);         //
Cmd0(复位)命令

                 retry++;
                 if(retry > 30) return (type=0x01); //
超时退出,个别卡需要更多次循环才有反应

         } while(r1 != 0x01);                 // MMC
SD卡成功转到SPI模式


         retry = 0;

//****** SD
卡在进入SPI模式后,激活命令和MMC卡一样为Cmd1,同时Cmd55+Cmd41 仍然有效
******//

/*         do
         {
                 r1 = MMC_SD_SendCmd(1, 0);         //
Cmd1(active激活)命令

                 retry++;
                 if(retry > 100) return 1;         //
超时退出

         } while(r1);*/
         do
         {
                 r1 = MMC_SD_SendCmd(55, 0);         //
先发送
Cmd55
                 if(r1 == 0x01)                         //
如果有反应

                 {
                         r1 = MMC_SD_SendCmd(41,0);         //
再发送 Cmd41 进行激活

                         if(r1 == 0x00) type = 0x10;         //
激活成功就是SD

                 }

                 else {                                    //
如果发送 Cmd55无反应,改发送
Cmd1
                                 r1 = MMC_SD_SendCmd(1,0);
                                 if(r1 == 0x00) type = 0x20;         //
激活成功就是MMC

                          }

                 retry++;
                 if(retry > 255) return (type=0x01);         //
超时退出, 个别卡需要更多次循环才有反应

         } while(r1 != 0x00);                 // MMC
SD卡激活后的返回值均为
0x00*/

//         SPI_SendByte(0xFF);         //
高速SPI前先发送8个时钟

//         SPI_speed = 0x07;         //
切换到高速
SPI

         r1 = MMC_SD_SendCmd(59, 0);         //
CRC
         r1 = MMC_SD_SendCmd(16, 512);         //
设置读取一次的字节数


         SDCS = 1;                         //
关闭
Card
//         SPI_speed=0x07;         //
切换到高速
SPI

         return type;         //
参数返回,1为初始化错误,10SD卡,20MMC

}

//-----------------------------------------------------------
//         End of File
//-----------------------------------------------------------

来自:
阅读(1352) | 评论(0) | 转发(0) |
0

上一篇:SD介绍

下一篇:SD卡调试关键点

给主人留下些什么吧!~~