打印

SD程序移植,结果调不出来,什么情况呢?

[复制链接]
2957|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
huangfeng33|  楼主 | 2014-6-23 11:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#define SD_CS  GpioDataRegs.GPBDAT.bit.GPIO58//IO58做CS脚
// SD卡类型定义  
#define SD_TYPE_ERR     0X00
#define SD_TYPE_MMC     0X01
#define SD_TYPE_V1      0X02
#define SD_TYPE_V2      0X04
#define SD_TYPE_V2HC    0X06   
// SD卡指令表     
#define CMD0    0       //卡复位
#define CMD1    1
#define CMD8    8       //命令8 ,SEND_IF_COND
#define CMD9    9       //命令9 ,读CSD数据
#define CMD10   10      //命令10,读CID数据
#define CMD12   12      //命令12,停止数据传输
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
#define CMD17   17      //命令17,读sector
#define CMD18   18      //命令18,读Multi sector
#define CMD23   23      //命令23,设置多sector写入前预先擦除N个block
#define CMD24   24      //命令24,写sector
#define CMD25   25      //命令25,写Multi sector
#define CMD41   41      //命令41,应返回0x00
#define CMD55   55      //命令55,应返回0x01
#define CMD58   58      //命令58,读OCR信息
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00
//数据写入回应字意义
#define MSD_DATA_OK                0x05
#define MSD_DATA_CRC_ERROR         0x0B
#define MSD_DATA_WRITE_ERROR       0x0D
#define MSD_DATA_OTHER_ERROR       0xFF
//SD卡回应标记字
#define MSD_RESPONSE_NO_ERROR      0x00
#define MSD_IN_IDLE_STATE          0x01
#define MSD_ERASE_RESET            0x02
#define MSD_ILLEGAL_COMMAND        0x04
#define MSD_COM_CRC_ERROR          0x08
#define MSD_ERASE_SEQUENCE_ERROR   0x10
#define MSD_ADDRESS_ERROR          0x20
#define MSD_PARAMETER_ERROR        0x40
#define MSD_RESPONSE_FAILURE       0xFF
     
     


//函数申明区
u8 SD_SPI_ReadWriteByte(u8 data);
void SD_SPI_SpeedLow(void);
void SD_SPI_SpeedHigh(void);
u8 SD_WaitReady(void); //等待SD卡准备
u8 SD_GetResponse(u8 Response); //获得相应
u8 SD_Initialize(void); //初始化
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt); //读块
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt); //写块
u32 SD_GetSectorCount(void);   //读扇区数
u8 SD_GetCID(u8 *cid_data);                     //读SD卡CID
u8 SD_GetCSD(u8 *csd_data);                     //读SD卡CSD
void SD_SPI_Init(void);


u8  SD_Type=0;//SD卡的类型
////////////////////////////////////移植修改区///////////////////////////////////
//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 SPI2_ReadWriteByte(u8 data)////u8=unsigned char 因为DSP没有8位数据类型,不知问题是不是出在数据类型处理上
{
SpiaRegs.SPITXBUF=((data&0xff)<<8);
while(SpiaRegs.SPISTS.bit.INT_FLAG!=1);
return (SpiaRegs.SPIRXBUF&0xff);

}
u8 SD_SPI_ReadWriteByte(u8 data)
{
return SPI2_ReadWriteByte(data);
}

void SD_SPI_SpeedLow(void)
{
  SpiaRegs.SPIBRR =0x007f;//设置到低速模式
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
  SpiaRegs.SPIBRR =0x0000;//设置到高速模式
}
//SPI硬件层初始化
void SD_SPI_Init(void)
{
  
   EALLOW;

SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1;   // SPI-A开SPI时钟


    GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0;   // Enable pull-up on GPIO54 (SPISIMOA)
    GpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;   // Enable pull-up on GPIO55 (SPISOMIA)
    GpioCtrlRegs.GPBPUD.bit.GPIO56 = 0;   // Enable pull-up on GPIO56 (SPICLKA)


    GpioCtrlRegs.GPBQSEL2.bit.GPIO54 = 3; // Asynch input GPIO54 (SPISIMOA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3; // Asynch input GPIO55 (SPISOMIA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO56 = 3; // Asynch input GPIO56 (SPICLKA)

   GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 1; // Configure GPIO54 as SPISIMOA
    GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 1; // Configure GPIO55 as SPISOMIA
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 1; // Configure GPIO56 as SPICLKA

    EDIS;
SpiaRegs.SPICCR.all =0x0007;//8位SPI             // Reset on, rising edge, 8-bit char bits  
SpiaRegs.SPICTL.all =0x0006;         // Enable master mode, normal phase,
                                                 // enable talk, and SPI int disabled.
SpiaRegs.SPIBRR =0x0007F;//波特率最低
    SpiaRegs.SPICCR.all =0x0087;//开SPI;         // Relinquish SPI from Reset   
    SpiaRegs.SPIPRI.bit.FREE = 1;                // Set so breakpoints don't disturb xmission  
SD_CS=1;
}
///////////////////////////////////////////////////////////////////////////////////
//取消选择,释放SPI总线
void SD_DisSelect(void)
{
SD_CS=1;
DELAY_US(1);
  SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{
SD_CS=0;
DELAY_US(1);
if(SD_WaitReady()==0)return 0;//等待成功
SD_DisSelect();
return 1;//等待失败
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)
{
u32 t=0;
do
{
if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
t++;   
}while(t<0XFFFFFF);//等待
return 1;
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{
u16 Count=0xFFFF;//等待次数   
while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应   
if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败   
else return MSD_RESPONSE_NO_ERROR;//正确回应
}
//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;
u8 SD_RecvData(u8*buf,u16 len)
{   
if(SD_GetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
    while(len--)//开始接收数据
    {
        *buf=SPI2_ReadWriteByte(0xFF);
        buf++;
    }
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);      
    return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;
u8 SD_SendBlock(u8*buf,u8 cmd)
{
u16 t;   
if(SD_WaitReady())return 1;//等待准备失效
SD_SPI_ReadWriteByte(cmd);
if(cmd!=0XFD)//不是结束指令
{
for(t=0;t<512;t++)SPI2_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
   SD_SPI_ReadWriteByte(0xFF);//忽略crc
   SD_SPI_ReadWriteByte(0xFF);
t=SD_SPI_ReadWriteByte(0xFF);//接收响应
if((t&0x1F)!=0x05)return 2;//响应错误      
}      
    return 0;//写入成功
}

//向SD卡发送一个命令
//输入: u8 cmd   命令
//      u32 arg  命令参数
//      u8 crc   crc校验值   
//返回值:SD卡返回的响应  
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1;
u8 Retry=0;
SD_DisSelect();//取消上次片选
if(SD_Select())return 0XFF;//片选失效
//发送
    SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
    SD_SPI_ReadWriteByte(arg >> 24);
    SD_SPI_ReadWriteByte(arg >> 16);
    SD_SPI_ReadWriteByte(arg >> 8);
    SD_SPI_ReadWriteByte(arg);  
    SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
    //等待响应,或超时退出
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);  
//返回状态值
    return r1;
}      
//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)  
//返回值:0:NO_ERR
// 1:错误   
u8 SD_GetCID(u8 *cid_data)
{
    u8 r1;   
    //发CMD10命令,读CID
    r1=SD_SendCmd(CMD10,0,0x01);
    if(r1==0x00)
{
r1=SD_RecvData(cid_data,16);//接收16个字节的数据  
    }
SD_DisSelect();//取消片选
if(r1)return 1;
else return 0;
}  
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)   
//返回值:0:NO_ERR
// 1:错误   
u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;  
    r1=SD_SendCmd(CMD9,0,0x01);//发CMD9命令,读CSD
    if(r1==0)
{
    r1=SD_RecvData(csd_data, 16);//接收16个字节的数据
    }
SD_DisSelect();//取消片选
if(r1)return 1;
else return 0;
}  
//获取SD卡的总扇区数(扇区数)   
//返回值:0: 取容量出错
//       其他:SD卡的容量(扇区数/512字节)
//每扇区的字节数必为512,因为如果不是512虺跏蓟荒芡ü?  
u32 SD_GetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity;  
    u8 n;
u16 csize;      
//取CSD信息,如果期间出错,返回0
    if(SD_GetCSD(csd)!=0) return 0;   
    //如果为SDHC卡,按照下面方式计算
    if((csd[0]&0xC0)==0x40) //V2.00的卡
    {
csize = csd[9] + ((u16)csd[8] << 8) + 1;
Capacity = (u32)csize << 10;//得到扇区数   
    }else//V1.XX的卡
    {
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
Capacity= (u32)csize << (n - 9);//得到扇区数   
    }
    return Capacity;
}
//初始化SD卡
u8 SD_Initialize(void)
{
    u8 r1;      // 存放SD卡的返回值
    u16 retry;  // 用来进行超时计数
    u8 buf[4];  
u16 i;

SD_SPI_Init(); //初始化IO
  SD_SPI_SpeedLow(); //设置到低速模式
  for(i=0;i<20;i++)SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
}while((r1!=0X01) && retry--);
  SD_Type=0;//默认无卡
if(r1==0X01)
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
else SD_Type=SD_TYPE_V2;   
}
}
}else//SD V1.x/ MMC V3
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0,0X01); //发送CMD41
if(r1<=1)
{
SD_Type=SD_TYPE_V1;
retry=0XFFFE;
do //等待退出IDLE模式
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
}while(r1&&retry--);
}else
{
SD_Type=SD_TYPE_MMC;//MMC V3
retry=0XFFFE;
do //等待退出IDLE模式
{   
r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
}while(r1&&retry--);  
}
if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
}
}
SD_DisSelect();//取消片选
SD_SPI_SpeedHigh();//高速
if(SD_Type)return 0;
else if(r1)return r1;   
return 0xaa;//其他错误
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
if(cnt==1)
{
r1=SD_SendCmd(CMD17,sector,0X01);//读命令
if(r1==0)//指令发送成功
{
r1=SD_RecvData(buf,512);//接收512个字节   
}
}else
{
r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
do
{
r1=SD_RecvData(buf,512);//接收512个字节  
buf+=512;  
}while(--cnt && r1==0);
SD_SendCmd(CMD12,0,0X01); //发送停止命令
}   
SD_DisSelect();//取消片选
return r1;//
}
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
if(cnt==1)
{
r1=SD_SendCmd(CMD24,sector,0X01);//读命令
if(r1==0)//指令发送成功
{
r1=SD_SendBlock(buf,0xFE);//写512个字节   
}
}else
{
if(SD_Type!=SD_TYPE_MMC)
{
SD_SendCmd(CMD55,0,0X01);
SD_SendCmd(CMD23,cnt,0X01);//发送指令
}
  r1=SD_SendCmd(CMD25,sector,0X01);//连续读命令
if(r1==0)
{
do
{
r1=SD_SendBlock(buf,0xFC);//接收512个字节  
buf+=512;  
}while(--cnt && r1==0);
r1=SD_SendBlock(0,0xFD);//接收512个字节
}
}   
SD_DisSelect();//取消片选
return r1;//
}   
void main(void)
{
    u8 t=0;   
u8 temperature;      
u8 humidity;  

u32 sd_size;





   InitSysCtrl();





   DINT;


   InitPieCtrl();
   InitPieVectTable();




   IER = 0x0000;
   IFR = 0x0000;
   EINT;   
   ERTM;

EALLOW;


GpioCtrlRegs.GPBMUX2..bit.GPIO58=0;//IO 58


GpioCtrlRegs.GPBDIR..bit.GPIO58= 1;//输出

  EDIS;
while(SD_Initialize())//检测不到SD卡
{
LCD_ShowString(60,150,200,16,16,"SD Card Error!");
delay_ms(500);
LCD_ShowString(60,150,200,16,16,"Please Check! ");
delay_ms(500);
}
  POINT_COLOR=BLUE;//设置字体为蓝色
//检测SD卡成功   
LCD_ShowString(60,150,200,16,16,"SD Card OK    ");
LCD_ShowString(60,170,200,16,16,"SD Card Size:     MB");
sd_size=SD_GetSectorCount();//得到扇区数
LCD_ShowNum(164,170,sd_size>>11,5,16);//显示SD卡容量*/
while(1);
}


相关帖子

沙发
zhangmangui| | 2014-6-23 17:05 | 只看该作者
看不出头绪

使用特权

评论回复
板凳
zhangmangui| | 2014-6-23 17:05 | 只看该作者
看不出头绪

使用特权

评论回复
地板
tianli1980| | 2014-7-9 21:58 | 只看该作者
SPI接口移植好之后才行喔,确保SPI配置正确,注意SPI时钟线空闲的时候电平

使用特权

评论回复
5
huangfeng33|  楼主 | 2014-7-9 21:59 | 只看该作者
我什么时序都试过了,就是不行,用IO摸拟SPI也不行,不解啊!

使用特权

评论回复
6
tianli1980| | 2014-7-10 23:33 | 只看该作者
你片子的数据类型是什么样的要对应才行的啊!

使用特权

评论回复
7
czdpj| | 2020-1-18 07:29 | 只看该作者
拷贝一个成功的例程解析啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

506

主题

2446

帖子

8

粉丝