打印

请教读写SD卡的问题

[复制链接]
2796|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lhwaizhu|  楼主 | 2012-11-23 21:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
hgjinwei| | 2012-11-23 22:26 | 只看该作者
肯定物理扇区啦,逻辑扇区号只是个虚拟号,哄骗上层的。

使用特权

评论回复
板凳
znmcu| | 2012-11-23 22:27 | 只看该作者
逻辑地址是文件系统层面的概念,你物理层扇区读写当然是物理地址。你可以关注www.znfat.com

使用特权

评论回复
地板
zzf119| | 2013-1-10 21:20 | 只看该作者
znmcu 发表于 2012-11-23 22:27
逻辑地址是文件系统层面的概念,你物理层扇区读写当然是物理地址。你可以关注www.znfat.com ...

你好,ZN,我现在用stm32控制sd卡,4g的,卡的初始化都正常,但是我试着从sd卡里读出数据,比如(cmd17,0x00000000,0x00),我理解是读地址为0的数据512字节,但是读出来的和用winhex查看到的实际数据部一致,读出的全是0x00,不知道自己在哪迷糊了,

使用特权

评论回复
5
znmcu| | 2013-1-14 10:24 | 只看该作者
你可以直接用我的SDHC驱动,你可以把你的SDHC驱动,发出来,我来分析一下。

使用特权

评论回复
6
zzf119| | 2013-1-30 22:12 | 只看该作者
znmcu 发表于 2013-1-14 10:24
你可以直接用我的SDHC驱动,你可以把你的SDHC驱动,发出来,我来分析一下。 ...

谢谢,我最近调试还是一样的问题,前面的全是是0x00,后面的全是0xff外加一两个0x09,
//SD卡发送命令函数:
u8 SD_Sendcommand(u8 command,u32 arg,u8 crc)
{
  u8 r1=0x00;
  u8 retry=0x00;
//  SPI1_SetSpeed(SPI1_SPEED_256);  //低速
  SD_XCS2_SET();
  SPI1_ReadWriteByte(0xFF);
  SPI1_ReadWriteByte(0xFF);
  SD_XCS2_CLR();
  SPI1_ReadWriteByte(command | 0x40);  
  SPI1_ReadWriteByte(arg>>24);   
  SPI1_ReadWriteByte(arg>>16);
  SPI1_ReadWriteByte(arg>>8);
  SPI1_ReadWriteByte(arg);
  SPI1_ReadWriteByte(crc);
   while((r1=SPI1_ReadWriteByte(0xFF))==0xFF)
      { if(retry++>250)
          break;
      }
  SD_XCS2_SET();
// SPI1_ReadWriteByte(0xFF);
// SPI1_SetSpeed(SPI1_SPEED_4);
  return r1;
}


//SD卡初始化函数:
u8 SD_Init(void)        //返回1操作失误,0操作正确
{
  u8 i=0x00;
  u8 r1=0x00;
  u8 retry=0x00;
  u32 j=0x00000000;
  u8 buffer[8];
  SPI1_Init();
  SPI1_SetSpeed(SPI1_SPEED_256);  // 采用低频
  for(j=0;j<42949;j++);            //上电延时
  for(i=0;i<5;i++)
    {
     SPI1_ReadWriteByte(0xFF);
    }
   do
     {
        r1=SD_Sendcommand(0x00,0x00000000,0x95);    //CMD0复位命令
        retry++;
        if(retry>20)
        return 1;     //返回1操作失误   
     }while(r1!=0x01);   //r1响应为0x01操作正确

   SPI1_SetSpeed(SPI1_SPEED_256);  // 采用低频
   for(i=0;i<20;i++)
    {
     SPI1_ReadWriteByte(0xFF);
    }
        r1=0x00;     
    retry=0x00;
        r1=SD_Sendcommand(0x08,0x1AA,0x87);     //CMD8命令,查看版本
        if(r1==0x05)
        {
         SD_XCS2_SET();
         SPI1_ReadWriteByte(0xFF);
         r1=0x00;     
     retry=0x00;
          do
            {
                  r1=SD_Sendcommand(0x37,0x00000000,0x00);  //CMD55激活卡命令,此时为SPI模式
                 if(r1==0xFF)
                  return 1;
                 r1=SD_Sendcommand(0x29,0x00000000,0x00);  //CMD41激活卡命令,此时为SPI模式
         retry++;  
                } while(r1&&(retry<254));
          if(retry==254)
            {
                   retry=0x00;
                    do
                         {
                          r1=SD_Sendcommand(0x01,0x00000000,0x00);     //CMD1命令,mmc卡初始化
                          retry++;
                         }while(retry&&(retry<254));
                }
                 if(retry==254)
                  return 1;
                  SD_XCS2_SET();
                r1=0x00;
                for(i=0;i<100;i++)
                {
                  SPI1_ReadWriteByte(0xFF);
                }
                r1=SD_Sendcommand(0x10,512,0x95);//CMD16,设置扇区大小512
                SPI1_SetSpeed(SPI1_SPEED_4);
                if(r1!=0)
                return 1;   
                return 0;              //返回0操作正确
        }
        else if(r1==0x01)
         {          
                  SD_XCS2_CLR();
            buffer[0]=SPI1_ReadWriteByte(0xFF);               
            buffer[1]=SPI1_ReadWriteByte(0xFF);
            buffer[2]=SPI1_ReadWriteByte(0xFF);
            buffer[3]=SPI1_ReadWriteByte(0xFF);
                SD_XCS2_SET();
                SPI1_ReadWriteByte(0xFF);
                retry=0x00;
                do
                  {
                   r1=SD_Sendcommand(0x37,0x00000000,0x00);  //CMD55激活卡命令,此时为SPI模式
                   if(r1!=0x01)
                   return 1;
                  r1=SD_Sendcommand(0x29,0x40000000,0x00);  //CMD41激活卡命令,此时为SPI模式
           retry++;
                   if(retry>254)
                   return r1;
                  }        while(r1!=0x00);
                  r1=SD_Sendcommand(0x3A,0x00000000,0x00);           //鉴别SD卡2.0版本
                  if(r1!=0x00)
                   {
                         SD_XCS2_SET();
                         return r1;
                   }
                   SD_XCS2_CLR();
                    buffer[4]=SPI1_ReadWriteByte(0xFF);           //4B的OCR信息
                    buffer[5]=SPI1_ReadWriteByte(0xFF);
                    buffer[6]=SPI1_ReadWriteByte(0xFF);
                    buffer[7]=SPI1_ReadWriteByte(0xFF);       
                        SD_XCS2_SET();       
                        SPI1_ReadWriteByte(0xFF);
                        if(buffer[4]&0x40)
                          sdtype=0x02;                           //SDHC
                          else sdtype=0x03;                   //SD2.0
                         SD_XCS2_SET();
                        r1=0x00;
                        for(i=0;i<100;i++)
                        {
                          SPI1_ReadWriteByte(0xFF);
                        }
                        r1=SD_Sendcommand(0x10,512,0x95);//CMD16,设置扇区大小512
                        SPI1_SetSpeed(SPI1_SPEED_4);
                        if(r1!=0)
                        return 1;   
                   }
                                  return 0;              //返回0操作正确
}          




//SD卡读数据函数:
u8 SD_ReadData(u32 addr, u8 *buffer2)
{
  u8 r1=0x00;
  u8 i=0x00;
  u16 cnt=0x0000;
  SPI1_SetSpeed(SPI1_SPEED_4);
  SD_XCS2_SET();
   if(sdtype!=0x02)
    addr=addr<<9;
  r1=SD_Sendcommand(0x11,addr,0x00);//CMD17
   if(r1!=0x00)
    return r1;
//  SPI1_SetSpeed(SPI1_SPEED_8);
  SD_XCS2_CLR();  
   do                                    //收字牌0xFE;
     {
           r1=SPI1_ReadWriteByte(0xFE);
           i=i+1;
         }while(r1!=0xFE&&i<0xFD);
         if(i==0xFD)
          return 1;
         r1=0x00;
        for(cnt=0;cnt<512;cnt++)
         {
            buffer2[cnt]=SPI1_ReadWriteByte(0xFF);
           //  buffer2++;
         }
         SPI1_ReadWriteByte(0xFF);
         SPI1_ReadWriteByte(0xFF);
         SD_XCS2_SET();
         SPI1_ReadWriteByte(0xFF);
    return 0;
}


使用特权

评论回复
7
zzf119| | 2013-1-30 22:15 | 只看该作者
znmcu 发表于 2013-1-14 10:24
你可以直接用我的SDHC驱动,你可以把你的SDHC驱动,发出来,我来分析一下。 ...

这是收到的从SD卡读到的数据[ 串口收到从SD卡读到的数据.rar (629 Bytes)

使用特权

评论回复
8
lbx_00| | 2013-1-31 16:25 | 只看该作者
我用的也是stm32,  也是用程序模拟的sd卡时序,我的读出来了,看了看你的程序, 有两点不同:

1, 我的crc校验是真校验, 你的没有校验, 无校验的我没有试过, 虽然说spi模式不需要校验吧,好象网上都是把校验字节写成0xff;

2,发送cmd17, 等待卡应答, 这个过程我会尝试多次, 超出次数,我才会认为不成功.

还有winhex的0地址, 好象不是真正的0, 这个我忘记了, 当时头都大了, 程序过去后,也记不清了

以下是程序,只作参考:

/***********************************************
        TF卡, 亦称micro SD卡
************************************************/

#include <stm32f10x_lib.h>

#include "my.h"

#define SPI_MODE

#ifndef SPI_MODE
  #define SD_MODE
#endif

//#define  NCR 5         //5clk
#define  NID 5
//#define  NAC 2
//#define  NRC 8
#define  NCC 8
//#define  NWR 5

#define  NCS  5   //clk  ,   0 *8 clock cycles
#define  NCR  10  //clk  1 8  *8 clock cycles
#define  NCX  5   //clk 0 8 *8 clock cycles
#define  NRC  10  //clk 1 8 clock cycles
#define  NAC  10  // 1           *8 clock cycles
#define  NWR  10  //clk, 1 *8 clock cycles
#define  NEC  5   //clk, 0 *8 clock cycles
#define  NDS  5   //clk,0 *8 clock cycles
#define  NBR  8          //clk, 1  *8 clock cycles

#define TF_CLK_H   GPIO_SetBits(GPIOB, GPIO_Pin_15)
#define TF_CLK_L   GPIO_ResetBits(GPIOB, GPIO_Pin_15)                 //SPI CLK

#define TF_CMD_H   GPIO_SetBits(GPIOD, GPIO_Pin_13)
#define TF_CMD_L   GPIO_ResetBits(GPIOD, GPIO_Pin_13) //SPI DI
#define TF_DI_H           TF_CMD_H
#define TF_DI_L           TF_CMD_L

#define TF_D0_H   GPIO_SetBits(GPIOB, GPIO_Pin_14)
#define TF_D0_L   GPIO_ResetBits(GPIOB, GPIO_Pin_14)

#define TF_D1_H   GPIO_SetBits(GPIOB, GPIO_Pin_13)
#define TF_D1_L   GPIO_ResetBits(GPIOB, GPIO_Pin_13)

#define TF_D2_H   GPIO_SetBits(GPIOA, GPIO_Pin_11)
#define TF_D2_L   GPIO_ResetBits(GPIOA, GPIO_Pin_11)

#define TF_D3_H   GPIO_SetBits(GPIOC, GPIO_Pin_6)
#define TF_D3_L   GPIO_ResetBits(GPIOC, GPIO_Pin_6)                   //SPI CS        , ACTIVE LOW
#define TF_CS_H   TF_D3_H
#define TF_CS_L   TF_D3_L

#define TF_CMD_R   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_13)

#define TF_D0_R    GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14)  //SPI DOUT

#define TF_D1_R    GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13)

#define TF_D2_R    GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)

#define TF_D3_R    GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6)

#define TF_TEST_R    GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12)         //检测TF卡有无, 低电平有效




uchar tf_crc7(uchar *pda, uchar n) //CRC-7生成函数(直接生成最后一个CMD指令字节), pda: 数据地址(*(pda+0)为首字节); n: 数据字节数;        //G(x) =x7 + x3 + 1
{
  uchar i,j,crc, temp;  //crc: bit6--bit0有效, bit7: 做移出位

  crc =0;
  for(i=0; i<n; i++)
  {
    temp =*(pda+i);
        j =8;
    do
        {
          crc <<=1;

          if(temp & 0x80)
          {
            crc |=0x01;
          }
          else
          {
            crc &=0xfe;
          }
      
          temp <<=1; //移位

          if(crc & 0x80)
          {
            crc =crc ^ 0x89;
          }          //异或

          j -=1;
        }
        while(j);
  }

  for(i=0; i<7; i++)
  {
    crc <<=1;
        if(crc & 0x80)
        {
          crc =crc ^ 0x89;
        }
  }  //完成这一步已经是 CRC检验码了

  return((crc<<1) | 0x01);
}

void tf_send_cmd(uchar *pcmd,uchar speed) //发送cmd指令, *pcmd中不包括CRC和停止位, speed速度, 调用此函数时, 要求clk 为L //speed =1 for slow(<=400KHz), 0 for quick
{
#ifdef SPI_MODE          //SPI模式

  uchar i,j,temp,cmd[6];

  for(i =0; i<6-1; i++)
  {
    cmd[i] =*(pcmd+i);
  }
  
  cmd[5] =tf_crc7(cmd,5);

  for(i=0; i<6; i++)
  {
    TF_CLK_L;
    temp =cmd[i];
        for(j=0; j<8; j++)
        {
          TF_CLK_L;
          if(speed) delayus(1);
          if(temp & 0x80)
          {
            TF_DI_H;
          }
          else
          {
            TF_DI_L;
          }
          TF_CLK_H;
          if(speed) delayus(1);       
          temp <<=1;
        }
  }

  TF_CLK_L;

#endif

#ifdef SD_MODE  //SD模式
   uchar i,j,temp,cmd[6];
   
  while(!TF_D0_R)
  {
    TF_CLK_L;
        delay(1);
        TF_CLK_H;
        delay(1);
        TF_CLK_L;
  }

  for(i =0; i<6-1; i++)
  {
    cmd[i] =*(pcmd+i);
  }
  
  cmd[5] =tf_crc7(cmd,5);

  for(i=0; i<6; i++)
  {
    TF_CLK_L;
    temp =cmd[i];
        for(j=0; j<8; j++)
        {
          TF_CLK_L;
          if(speed) delayus(1);
          if(temp & 0x80)
          {
            TF_DI_H;
          }
          else
          {
            TF_DI_L;
          }
          TF_CLK_H;
          if(speed) delayus(1);       
          temp <<=1;
        }
  }

  TF_CLK_L;
  TF_CMD_H;
#endif
}

void tf_rev_res(uchar *prev,uchar n,uchar speed)  //接收响应,SPI模式, *prev: 接收的数据放在这里; n: 要求接收的字节数; speed:速度 1 for slow, 0 for quick
{
#ifdef SPI_MODE    //SPI模式
  uchar i,j,temp,en;  
  ushort k;

  TF_CLK_L;
  TF_D0_H;

  en =0;
  k =0;
  for(i=0; i<n; i++)
  {
    temp =0;
    for(j=0; j<8; j++)
        {
          TF_CLK_L;
          if(speed) delayus(1);
          TF_CLK_H;
          if(speed) delayus(1);
          temp <<=1;
          if(TF_D0_R && en)
          {
            temp |=0x01;
          }
          else if((!TF_D0_R) && (!en))
          {       
            k =0;
            en =1;
          }
          else if(en==0)
          {
            if(k<0xffff) k +=1;
            j =255;
          }

          if(k>60000) break;
        }
        if(k>60000) break;
        *(prev+i) =temp;
  }
  if(en==0) *prev =0xff;
#endif

#ifdef SD_MODE  //SD模式
  uchar i,j,temp,en;  
  ushort k;

  TF_CLK_L;
  TF_CMD_H;

  en =0;
  k =0;
  for(i=0; i<n; i++)
  {
    temp =0;
        if(i==0)
        {
          k =0;
          while(1)
          {
                  TF_CLK_L;
            if(speed) delayus(1);
            TF_CLK_H;
            if(speed) delayus(1);
                if(!TF_CMD_R) break;

                k +=1;
                if(k>60000) goto tf_rev_res_1;
          }
          j =1;
        }
        else j =0;
        en =1;
        k =0;
    for(; j<8; j++)
        {
          TF_CLK_L;
          if(speed) delayus(1);
          TF_CLK_H;
          if(speed) delayus(1);
          temp <<=1;
          if(TF_CMD_R && en)
          {
            temp |=0x01;
          }
          else if((!TF_CMD_R) && (!en))
          {       
            k =0;
            en =1;
          }
          else if(en==0)
          {
            if(k<0xffff) k +=1;
            j =255;
          }

          if(k>60000) break;
        }
        if(k>60000) break;
        *(prev+i) =temp;
  }
tf_rev_res_1:
if(en==0) *prev =0xff;
#endif
}

uchar tf_rev_byte_data() //接收1个字节数据
{
#ifdef SPI_MODE    //SPI模式
  uchar i,result;

  TF_CLK_L;
  TF_D0_H;

  result =0;
  for(i=0; i<8; i++)
  {
    TF_CLK_L;
        result <<=1;
        TF_CLK_H;
        if(TF_D0_R)
        {
          result |=0x01;
        }
  }
  TF_CLK_L;  

  return(result);
#endif

#ifdef SD_MODE  //SD模式
  uchar i,result;

  TF_CLK_L;
  TF_D0_H;
  TF_D1_H;
  TF_D2_H;
  TF_D3_H;

  result =0;
  for(i=0; i<2; i++)
  {
    TF_CLK_L;
        result <<=4;
        TF_CLK_H;
        if(TF_D0_R)
        {
          result |=0x01;
        }
        if(TF_D1_R)
        {
          result |=0x02;
        }
        if(TF_D2_R)
        {
          result |=0x04;
        }
        if(TF_D3_R)
        {
          result |=0x08;
        }
  }
  TF_CLK_L;  

  return(result);
#endif
}

void tf_rev_data(uchar *prdata,ushort n) //接收数据, SPI模式, *prdata: 接收存储; n: 要求接收的字节数
{
#ifdef SPI_MODE    //SPI模式
  ushort i;

  for(i=0; i<n; i++)
  {
    *(prdata+i) =tf_rev_byte_data();
  }
#endif

#ifdef SD_MODE  //SD模式
  ushort i;

  for(i=0; i<n; i++)
  {
    *(prdata+i) =tf_rev_byte_data();
  }
#endif
}

void tf_74clk() //CMD线上的74个逻辑1
{
#ifdef SPI_MODE    //SPI模式
  uchar i;

  TF_CMD_H;
  for(i=0; i<74; i++)
  {
    TF_CLK_L;
        delayus(1);
        TF_DI_H;
        TF_CLK_H;
        delayus(1);
  }
  TF_CLK_L;
#endif

#ifdef SD_MODE  //SD模式
  uchar i;

  TF_CMD_H;
  for(i=0; i<74; i++)
  {
    TF_CLK_L;
        delayus(1);
        TF_DI_H;
        TF_CLK_H;
        delayus(1);
  }
  TF_CLK_L;
#endif
}

void delayclk(uchar nclk,uchar speed) //等待,nclk:等待的时钟周期数; speed =1 for slow, 0 for quick
{
#ifdef SPI_MODE    //SPI模式
  uchar i;
  
  TF_CMD_H;
  for(i=0; i<nclk; i++)
  {
    TF_CLK_L;
        if(speed) delayus(1);
        TF_D0_H;
        TF_CLK_H;
        if(speed) delayus(1);
  }

  TF_CLK_L;
#endif

#ifdef SD_MODE  //SD模式
  uchar i;
  
  TF_CMD_H;
  for(i=0; i<nclk; i++)
  {
    TF_CLK_L;
        if(speed) delayus(1);
        TF_D0_H;
        TF_CLK_H;
        if(speed) delayus(1);
  }

  TF_CLK_L;
#endif
}

void tf_inti() //TF卡初始化
{
#ifdef SPI_MODE    //SPI模式
  uchar i,temp,cmd[5];

  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;     

  i =0;
  while(TF_TEST_R)
  {
    delay(10);
        i +=1;
        if(i>200) break;
  };  //等待TF卡插入

  if(i>200)
  {
    OwnErr =1;
        return;
  }

  delay(1); //延迟1ms
  cmd[0] =0x40;
  cmd[1] =0x00;
  cmd[2] =0x00;
  cmd[3] =0x00;
  cmd[4] =0x00;
  
  tf_74clk(); //等待74个周期  

  TF_CS_H;
  TF_CLK_L;
  TF_CS_L;
  delayus(1);
  //tf_send_cmd(cmd,1); //发送CMD0

  //delayclk(8,1);

  i =0;
  do
  {
    tf_send_cmd(cmd,1); //发送CMD0
        delay(24);
    tf_rev_res(&temp,1,1); //接收R1
        i +=1;
        if(i>200) break;
  }
  while(temp !=0x01);

  if(i >200)
  {
    OwnErr =2;
        TF_CS_H;
        return;
  }

  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;
  
  delayclk(8,1);
  cmd[0] =0x41;
  cmd[1] =0x00;
  cmd[2] =0x00;
  cmd[3] =0x00;
  cmd[4] =0x00;

  //tf_send_cmd(cmd,1); //发送CMD1
  
  //delayclk(8,1);

  
  TF_CS_H;
  TF_CLK_L;
  TF_CS_L;
  delayus(1);
  
  i =0;
  do
  {
        tf_send_cmd(cmd,1); //发送CMD1
        delay(24);
        tf_rev_res(&temp,1,1);
        i +=1;
  }
  while((temp !=0x00)&&(i<200)); //激活卡

  if(i==200)
  {
          OwnErr =3;
        TF_CS_H;
        return;
  }

  TF_CS_H;         
  
  delayclk(8,1);
#endif

#ifdef SD_MODE  //SD模式
  uchar i,j,cmd[5],tem[6];

  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;     

  i =0;
  while(TF_TEST_R)
  {
    delay(10);
        i +=1;
        if(i>200) break;
  };  //等待TF卡插入

  if(i>200)
  {
    OwnErr =1;
        return;
  }

  delay(1); //延迟1ms
  cmd[0] =0x40;
  cmd[1] =0x00;
  cmd[2] =0x00;
  cmd[3] =0x00;
  cmd[4] =0x00;
  
  tf_74clk(); //等待74个周期  

  //tf_send_cmd(cmd,1); //发送CMD0

  //delayclk(8,1);

  i =0;
  //do
  {
    tf_send_cmd(cmd,1); //发送CMD0
        delay(24);
    //tf_rev_res(&temp,1,1); //接收R1
        //i +=1;
        //if(i>200) break;
  }
  //while(temp !=0x01);

  cmd[0] =0x40 | 8;
  cmd[1] =0x00;
  cmd[2] =0x00;
  cmd[3] =0x01;
  cmd[4] =0xaa;

   tf_send_cmd(cmd,1); //发送CMD8
   delay(24);

  if(i >200)
  {
    OwnErr =2;
        TF_CS_H;
        return;
  }

  j =0;
tf_inti_1:
  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;
  
  delayclk(8,1);

  cmd[0] =0x40 | 55;
  cmd[1] =0x00;
  cmd[2] =0x00;
  cmd[3] =0x00;
  cmd[4] =0x00;

  
  TF_CS_H;
  TF_CLK_L;
  //TF_CS_L;
  delayus(1);
  
  i =0;
  do
  {
        tf_send_cmd(cmd,1); //发送CMD55
        delay(24);
        tf_rev_res(tem,6,1);
        i +=1;
  }
  while(  (((tem[0] & 0xc0) !=0x00)||((tem[1] & 0x80) !=0x00)) && (i<200) ) ; //下一个发送应用指令


  cmd[0] =0x40 | 41;
  cmd[1] =0x00;
  cmd[2] =0xff;
  cmd[3] =0x80;
  cmd[4] =0x00;
  {
    tf_send_cmd(cmd,1); //发送ACMD41
        delayclk(8,1);
        tf_rev_res(tem,6,1);
        j +=1;
  }
  if((((tem[0] & 0xc0) !=0x00)||((tem[1]& 0x80) !=0x80)) && (j<200)) goto  tf_inti_1;  

  if(j==200)
  {
          OwnErr =3;
        TF_CS_H;
        return;
  }

  if(i==200)
  {
          OwnErr =3;
        TF_CS_H;
        return;
  }

  TF_CS_H;         
  
  delayclk(8,1);
#endif
}

uchar tf_single_read(uchar *pbuf, uint sector) //读扇区(512字节), *pbuf: 存储区;  sector: 扇区号;  返回0表示成功
{
#ifdef SPI_MODE    //SPI模式
  uchar cmd[5],i,temp;
  uint addr;
  
  addr =sector;
  addr <<=9;

  cmd[0] =0x40 | 0x11;  
  cmd[1] =(addr>>24);
  cmd[2] =(addr>>16);
  cmd[3] =(addr>>8);
  cmd[4] =addr;

  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;
  //delay(1);
  TF_CS_L;
  //delay(1);
  //tf_send_cmd(cmd,0);        //发送单块数据读指令

  //delayus(1);                        //间断一下

  i =0;
  while(1)
  {
    tf_send_cmd(cmd,0);        //发送单块数据读指令
        //delayus(1);                        //间断一下
        tf_rev_res(&temp,1,0);
        if(temp ==0) break;
    i +=1;
        if(i>200)
        {
          TF_CS_H;
          return(1);
        }
  };                                          //读回应R1, 0x00才合法

  delayus(1);

  i=0;
  while(tf_rev_byte_data() !=0xfe)
  {
    i +=1;
        if(i>200)
        {
          TF_CS_H;
          return(1);
        };
  }                                           //读起始令牌, 0xfe合法

  tf_rev_data(pbuf,512); //读512字节数据

  i =tf_rev_byte_data();
  i =tf_rev_byte_data(); //读CRC16

  //delayus(1);
  TF_CS_H;

  //delayclk(8,0);
   
  return(0); //成功
#endif

#ifdef SD_MODE  //SD模式
  uchar cmd[5],i,temp[6];
  uint addr;

  addr =sector;
  addr <<=9;

  cmd[0] =0x40 | 0x11;  
  cmd[1] =(addr>>24);
  cmd[2] =(addr>>16);
  cmd[3] =(addr>>8);
  cmd[4] =addr;

  TF_CS_H;
  TF_CLK_L;   
  TF_DI_H;   
  TF_D0_H;   
  TF_D1_H;   
  TF_D2_H;
  //delay(1);
// TF_CS_L;
  //delay(1);
  //tf_send_cmd(cmd,0);        //发送单块数据读指令

  //delayus(1);                        //间断一下

  i =0;
  while(1)
  {
    tf_send_cmd(cmd,0);        //发送单块数据读指令
        //delayus(1);                        //间断一下
        tf_rev_res(temp,6,0);
        if((temp[1]&0x80) ==0) break;
    i +=1;
        if(i>200)
        {
          TF_CS_H;
          return(1);
        }
  };                                          //读回应R1, 0x00才合法

  delayus(1);

  i=0;
  while(tf_rev_byte_data() !=0xfe)
  {
    i +=1;
        if(i>200)
        {
          TF_CS_H;
          return(1);
        };
  }                                           //读起始令牌, 0xfe合法

  tf_rev_data(pbuf,512); //读512字节数据

  i =tf_rev_byte_data();
  i =tf_rev_byte_data(); //读CRC16

  //delayus(1);
  TF_CS_H;

  //delayclk(8,0);
   
  return(0); //成功
#endif
}


使用特权

评论回复
9
zzf119| | 2013-1-31 22:52 | 只看该作者
恩,校验确实没什么影响,我改了0xff,还是一样的,没什么变化,手册也说spi模式默认为无校验。
至于发送cmd17命令,我发现也有很大关系~
今晚刚刚调出来了,哈哈,能够读到数据了,不过还没用winhex去对应是否一致,
原因找到了,是我设置的sclk始终高了,具体还没去想,我把频率设为281K,就可以正常读写了
继续分析问题,哈哈~~

使用特权

评论回复
10
jielin| | 2013-1-31 22:54 | 只看该作者
xgfhjd

使用特权

评论回复
11
apple| | 2013-2-1 00:36 | 只看该作者
在单片机上读写应该都是物理扇区吧。

使用特权

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

本版积分规则

24

主题

79

帖子

2

粉丝