关于SD卡的问题

     1. 如何判断一个卡所属的版本,像V2.0,V1.X,这个信息应该从哪里获得?一开始我对这个问题有疑问,我用的是1GB的kingston和sandisk。其实,只有SDHC才有版本问题,即内存大于2GB的SD卡才涉及这个问题,1GB的sd卡不用关心这个问题。

     2. Proteus仿真只能起到辅助作用,但是不可过度迷恋。在SD卡的调试中,我试图用proteus检测单片机端口的发出的数值,很快出了问题,片选信号置高,但在示波器里片选给了高电平后却渐渐的降低,直至为零。而此处找不到任何原因。

    但是也有可以借鉴的一面。我从SCK总是为高得出单片机并未发数据,因为在时钟极性中设置空闲状态时钟为高电平。另外,用SPI debuger也检测不到SDO的输出,也可以作为SPI未工作的佐证。

  3.有时,在程序执行一段时间以后,我们不确定单片机的端口或寄存器是什么样的状态,而寄存器的状态有反应了程序的执行状态。端口可用电表测得电平,但是某些寄存器的某些位,我们可以用串口USART将寄存器的某些位读回,并返回串口小助手,从而做到对单片机运行的足够了解,因为单片机的所有寄存器几乎都是可读的。我在此次的实验中读了一些端口或寄存器的值,像PORTC中用到的各个位,RC4为输入,读到的值为0,还读了写冲突检测位WCOL,0,说明没有写冲突,BF=1,说明SSPSR在发送完一个字节后,同时收到一个字节,给了SSPBUF,引起BF置位。

  4.另外,我一般写SPI的数据与发送是如下格式

    SSPBUF=data;

    While(!SSPIF;

    SSPIF=0;//与下面比,此句可省

   而我在这次试验发现,写成这样亦可

    SSPBUF=dataWhile(!BF;

    因为SSPSR输出数据的同时,也在接收数据,并将接收数据给了SSPBUF,引起BF,SSPIF的置位,当读SSPBUF时,BF会清零,而不用管中断标志SSPIF也不会引起写冲突。这样就可没发一个数据就可节省一条指令。

  5.在每次CS拉低使能SD卡后,都要有八个时钟信号,且单片机的输出为高,即SD卡的输入为高。

  6.在给扇区写完数据后,SD卡将作出回应,回应之后,还有一段忙时间(busy,所以写完数据后要有恰当的延时。不可马上去读。

  7.给芯片写数据一定要注意大小端,本次实验sd卡的逻辑块地址发送(共4个字节)写反了。应该先发地址高字节。

以下是程序摘要:

#include<pic.h>
#define uchar unsigned char
#define uint  unsigned int
#define _XTAL_FREQ 12000000
#define CS RC2
uchar response=0XFF;
void init_pic_spi();
void init_pic_usart();
void init_sd_spi();
uchar receive_response();
void write_command(uchar command,unsigned long arguement,uchar CRC);
void write_sd(uchar command,unsigned long address,uchar CRC,uint len);
void read_sd(uchar command,unsigned long address,uchar CRC,uint len);
void test();
__CONFIG(0X2f42);
void main()

 init_pic_usart();
 init_pic_spi(); 
 init_sd_spi();
 write_sd(0X18,102400,0XFF,512);
 read_sd(0X11,102400,0XFF,512);
 while(1);
}
void init_pic_spi()
{
 TRISC2=0;//CS 
 TRISC3=0;//SCK
 TRISC4=1;//SDI
 TRISC5=0;//SDO
 SSPSTAT=0X80;
 //SMP=1,input data sampled at the end of data output time
 //CKE=1;transmit occurs on transition from idle to active clock
 SSPCON=0X30;
 //SSPM3-SSPM0 0000 SPI master mode ,clock=fosc/64
 //CKP=1 idle state for clock high level
 //SPEN=1 enable serial port
 //WCOL=0 no collision
 //falling edge of SCK transmit data
}
void init_pic_usart()
{
     TRISC7=1; 
     TRISC6=1;  
     RCSTA=0x90;//1001 0000,SPEN=1,serial port enabled.CREN=1,
     TXSTA=0X24;//0010 0100,TX9=0,select 8 bits transmission.
           //TXEN=1,transmit enabled .
       //SYNC=0,Asynchronous mode.
       //BRGH=1,High speed.
     SPBRG=77;      
}
void init_sd_spi()
{
 int i=0;
 do   
 { 
  CS=1;//disable sd card 
  for(i=0;i<15;i++) //more than 74 clock pules,15*8=120,FOR YU JU CUO LE
  { 
   SSPBUF=0XFF;
   while(!BF);
  }
  CS=0; 
  SSPBUF=0XFF;
  while(!BF);//8 clock
  write_command(0x00,0,0x95);  
 }while(receive_response()!=0x01);
 CS=1; 
 SSPBUF=0XFF;//8 clock pules
 while(!BF);//untile now ,reset completed
 
 do
 {
  CS=0;
  __delay_us(10);
  write_command(0x01,0,0xff);
 }while(receive_response()!=0x00); 
 CS=1;
 __delay_us(10);
 SSPBUF=0XFF;//8 clock pules
 while(!BF);//untile now ,SD card has came into SPI work mode 
}
void write_command(uchar command,unsigned long arguement,uchar CRC)
{
 uchar arg[4],i=0; 
 arg[0]=(uchar)(arguement>>24);
 arg[1]=(uchar)(arguement>>16); 
 arg[2]=(uchar)(arguement>>8);
 arg[3]=(uchar)(arguement);//four 0x00
 SSPBUF=command|0x40;
 while(!BF);
 for(i=0;i<4;i++)
 {
  SSPBUF=arg[i];
  while(!BF);
 }
 SSPBUF=CRC;
 while(!BF);
}
void write_sd(uchar command,unsigned long address,uchar CRC,uint len)
{
 int i=0;
 do
 {
  CS=1;
  CS=0;
  SSPBUF=0XFF;//8 clock pules
  while(!BF);
  write_command(command,address,CRC);
 }while(receive_response()!=0x00);
 SSPBUF=0XFE;//head data
 while(!BF);
 for(i=0;i<512;i++)//data block
 {
  SSPBUF=i;//SSPBUF is 8 bit,the max data is 11111111 ff 256
  while(!BF); 
 }
 SSPBUF=0XFF;//CRC
 while(!BF); 
 SSPBUF=0XFF;//CRC
 while(!BF); 
 receive_response();
 CS=1;
 SSPBUF=0XFF;
 while(!BF);  
}
void read_sd(uchar command,unsigned long address,uchar CRC,uint len)
{
 int i=0;  
 do
 { 
  CS=1;
  CS=0;
  SSPBUF=0XFF;//8 clock pules
  while(!BF);
  write_command(command,address,CRC);//CMD11:the command of read data block,address must be integer multiple of 512
 }while(receive_response()!=0x00);
 while(receive_response()!=0xfe);
 for(i=0;i<len;i++)//read and output data
 { 
  SSPBUF=0XFF;
  while(!BF); 
  TXREG=SSPBUF;
  while(!TRMT);
 }
 SSPBUF=0XFF;
 while(!BF);
 i=SSPBUF;  //abandon two CRC bytes
 SSPBUF=0XFF;
 while(!BF);
 i=SSPBUF;
 CS=1; 
 SSPBUF=0XFF;
 while(!BF);
}
uchar receive_response()
{
 uchar a=0;
 while(a++<100)
 {
  SSPBUF=0XFF;//if we want to read a data,must send first,we send complete,receive comlete
  while(!BF);//receive flag
  if(0xff!=SSPBUF)
  {
   break;
  }
  if(0xff!=SSPBUF)
  {
   break;
  }
 }
 return(SSPBUF);  
}
void test()
{
 int i=0;
 for(i=0;i<5;i++)
 {
  TXREG=SSPBUF;
  while(!TRMT); 
 } 
}













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值